]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/security/audit/audit_bsd.c
xnu-7195.101.1.tar.gz
[apple/xnu.git] / bsd / security / audit / audit_bsd.c
index 6f4d416c941fdd77cb9d3a7fefdf431deb9af090..2f3adbace2fa454349a6fdb39a885ab7a54b14d9 100644 (file)
 #include <mach/host_priv.h>
 #include <mach/host_special_ports.h>
 #include <mach/audit_triggers_server.h>
+#include <mach/audit_triggers_types.h>
+
+#include <os/overflow.h>
+
+extern void ipc_port_release_send(ipc_port_t port);
 
 #if CONFIG_AUDIT
 struct mhdr {
-       size_t                   mh_size;
-       au_malloc_type_t        *mh_type;
-       u_long                   mh_magic;
-       char                     mh_data[0];
+       size_t                   mh_size;
+       au_malloc_type_t        *mh_type;
+       u_long                   mh_magic;
+       char                     mh_data[0];
 };
 
 /*
- * The lock group for the audit subsystem. 
+ * The lock group for the audit subsystem.
  */
-static lck_grp_t *audit_lck_grp = NULL;
+static LCK_GRP_DECLARE(audit_lck_grp, "Audit");
 
-#define        AUDIT_MHMAGIC   0x4D656C53
+#define AUDIT_MHMAGIC   0x4D656C53
 
 #if AUDIT_MALLOC_DEBUG
-#define AU_MAX_SHORTDESC       20
-#define AU_MAX_LASTCALLER      20
+#define AU_MAX_SHORTDESC        20
+#define AU_MAX_LASTCALLER       20
 struct au_malloc_debug_info {
-       SInt64          md_size;
-       SInt64          md_maxsize;
-       SInt32          md_inuse;
-       SInt32          md_maxused;
-       unsigned        md_type;
-       unsigned        md_magic;
-       char            md_shortdesc[AU_MAX_SHORTDESC];
-       char            md_lastcaller[AU_MAX_LASTCALLER];
+       SInt64          md_size;
+       SInt64          md_maxsize;
+       SInt32          md_inuse;
+       SInt32          md_maxused;
+       unsigned        md_type;
+       unsigned        md_magic;
+       char            md_shortdesc[AU_MAX_SHORTDESC];
+       char            md_lastcaller[AU_MAX_LASTCALLER];
 };
 typedef struct au_malloc_debug_info   au_malloc_debug_info_t;
 
-au_malloc_type_t       *audit_malloc_types[NUM_MALLOC_TYPES];
+au_malloc_type_t        *audit_malloc_types[NUM_MALLOC_TYPES];
 
 static int audit_sysctl_malloc_debug(struct sysctl_oid *oidp, void *arg1,
     int arg2, struct sysctl_req *req);
@@ -90,11 +95,11 @@ SYSCTL_PROC(_kern, OID_AUTO, audit_malloc_debug, CTLFLAG_RD, NULL, 0,
     audit_sysctl_malloc_debug, "S,audit_malloc_debug",
     "Current malloc debug info for auditing.");
 
-#define        AU_MALLOC_DBINFO_SZ \
+#define AU_MALLOC_DBINFO_SZ \
     (NUM_MALLOC_TYPES * sizeof(au_malloc_debug_info_t))
 
 /*
- * Copy out the malloc debug info via the sysctl interface.  The userland code 
+ * Copy out the malloc debug info via the sysctl interface.  The userland code
  * is something like the following:
  *
  *  error = sysctlbyname("kern.audit_malloc_debug", buffer_ptr, &buffer_len,
@@ -112,35 +117,38 @@ audit_sysctl_malloc_debug(__unused struct sysctl_oid *oidp, __unused void *arg1,
        /*
         * This provides a read-only node.
         */
-       if (req->newptr != USER_ADDR_NULL)
-               return (EPERM);
+       if (req->newptr != USER_ADDR_NULL) {
+               return EPERM;
+       }
 
        /*
-        * If just querying then return the space required. 
+        * If just querying then return the space required.
         */
        if (req->oldptr == USER_ADDR_NULL) {
-               req->oldidx = AU_MALLOC_DBINFO_SZ; 
-               return (0);
+               req->oldidx = AU_MALLOC_DBINFO_SZ;
+               return 0;
        }
 
        /*
         *  Alloc a temporary buffer.
         */
-       if (req->oldlen < AU_MALLOC_DBINFO_SZ)
-               return (ENOMEM);
-       amdi_ptr = (au_malloc_debug_info_t *)kalloc(AU_MALLOC_DBINFO_SZ);
-       if (amdi_ptr == NULL)
-               return (ENOMEM);
-       bzero(amdi_ptr, AU_MALLOC_DBINFO_SZ);
+       if (req->oldlen < AU_MALLOC_DBINFO_SZ) {
+               return ENOMEM;
+       }
+       amdi_ptr = kheap_alloc(KHEAP_TEMP, AU_MALLOC_DBINFO_SZ, Z_WAITOK | Z_ZERO);
+       if (amdi_ptr == NULL) {
+               return ENOMEM;
+       }
 
        /*
-        * Build the record array. 
+        * Build the record array.
         */
        sz = 0;
        nxt_ptr = amdi_ptr;
-       for(i = 0; i < NUM_MALLOC_TYPES; i++) {
-               if (audit_malloc_types[i] == NULL)
+       for (i = 0; i < NUM_MALLOC_TYPES; i++) {
+               if (audit_malloc_types[i] == NULL) {
                        continue;
+               }
                if (audit_malloc_types[i]->mt_magic != M_MAGIC) {
                        nxt_ptr->md_magic = audit_malloc_types[i]->mt_magic;
                        continue;
@@ -153,22 +161,22 @@ audit_sysctl_malloc_debug(__unused struct sysctl_oid *oidp, __unused void *arg1,
                strlcpy(nxt_ptr->md_shortdesc,
                    audit_malloc_types[i]->mt_shortdesc, AU_MAX_SHORTDESC - 1);
                strlcpy(nxt_ptr->md_lastcaller,
-                   audit_malloc_types[i]->mt_lastcaller, AU_MAX_LASTCALLER-1);
+                   audit_malloc_types[i]->mt_lastcaller, AU_MAX_LASTCALLER - 1);
                sz += sizeof(au_malloc_debug_info_t);
                nxt_ptr++;
        }
 
        req->oldlen = sz;
        err = SYSCTL_OUT(req, amdi_ptr, sz);
-       kfree(amdi_ptr, AU_MALLOC_DBINFO_SZ);
+       kheap_free(KHEAP_TEMP, amdi_ptr, AU_MALLOC_DBINFO_SZ);
 
-       return (err);
+       return err;
 }
 #endif /* AUDIT_MALLOC_DEBUG */
-       
+
 /*
  * BSD malloc()
- * 
+ *
  * If the M_NOWAIT flag is set then it may not block and return NULL.
  * If the M_ZERO flag is set then zero out the buffer.
  */
@@ -176,28 +184,25 @@ void *
 #if AUDIT_MALLOC_DEBUG
 _audit_malloc(size_t size, au_malloc_type_t *type, int flags, const char *fn)
 #else
-_audit_malloc(size_t size, au_malloc_type_t *type, int flags)
+_audit_malloc(size_t size, au_malloc_type_t * type, int flags)
 #endif
 {
-       struct mhdr     *hdr;
-       size_t  memsize = sizeof (*hdr) + size;
+       struct mhdr     *hdr;
+       size_t  memsize;
+       if (os_add_overflow(sizeof(*hdr), size, &memsize)) {
+               return NULL;
+       }
 
-       if (size == 0)
-               return (NULL);
-       if (flags & M_NOWAIT) {
-               hdr = (void *)kalloc_noblock(memsize);
-       } else {
-               hdr = (void *)kalloc(memsize);
-               if (hdr == NULL)
-                       panic("_audit_malloc: kernel memory exhausted");
+       if (size == 0) {
+               return NULL;
+       }
+       hdr = kheap_alloc(KHEAP_AUDIT, memsize, flags);
+       if (hdr == NULL) {
+               return NULL;
        }
-       if (hdr == NULL)
-               return (NULL);
        hdr->mh_size = memsize;
        hdr->mh_type = type;
        hdr->mh_magic = AUDIT_MHMAGIC;
-       if (flags & M_ZERO)
-               memset(hdr->mh_data, 0, size);
 #if AUDIT_MALLOC_DEBUG
        if (type != NULL && type->mt_type < NUM_MALLOC_TYPES) {
                OSAddAtomic64(memsize, &type->mt_size);
@@ -208,7 +213,7 @@ _audit_malloc(size_t size, au_malloc_type_t *type, int flags)
                audit_malloc_types[type->mt_type] = type;
        }
 #endif /* AUDIT_MALLOC_DEBUG */
-       return (hdr->mh_data);
+       return hdr->mh_data;
 }
 
 /*
@@ -222,13 +227,15 @@ _audit_free(void *addr, __unused au_malloc_type_t *type)
 #endif
 {
        struct mhdr *hdr;
-       
-       if (addr == NULL)
+
+       if (addr == NULL) {
                return;
+       }
        hdr = addr; hdr--;
 
-       KASSERT(hdr->mh_magic == AUDIT_MHMAGIC,
-           ("_audit_free(): hdr->mh_magic != AUDIT_MHMAGIC"));
+       if (hdr->mh_magic != AUDIT_MHMAGIC) {
+               panic("_audit_free(): hdr->mh_magic (%lx) != AUDIT_MHMAGIC", hdr->mh_magic);
+       }
 
 #if AUDIT_MALLOC_DEBUG
        if (type != NULL) {
@@ -236,7 +243,7 @@ _audit_free(void *addr, __unused au_malloc_type_t *type)
                OSAddAtomic(-1, &type->mt_inuse);
        }
 #endif /* AUDIT_MALLOC_DEBUG */
-       kfree(hdr, hdr->mh_size);
+       kheap_free(KHEAP_AUDIT, hdr, hdr->mh_size);
 }
 
 /*
@@ -245,11 +252,11 @@ _audit_free(void *addr, __unused au_malloc_type_t *type)
 void
 _audit_cv_init(struct cv *cvp, const char *desc)
 {
-
-       if (desc == NULL)
+       if (desc == NULL) {
                cvp->cv_description = "UNKNOWN";
-       else
+       } else {
                cvp->cv_description = desc;
+       }
        cvp->cv_waiters = 0;
 }
 
@@ -259,7 +266,6 @@ _audit_cv_init(struct cv *cvp, const char *desc)
 void
 _audit_cv_destroy(struct cv *cvp)
 {
-
        cvp->cv_description = NULL;
        cvp->cv_waiters = 0;
 }
@@ -270,7 +276,6 @@ _audit_cv_destroy(struct cv *cvp)
 void
 _audit_cv_signal(struct cv *cvp)
 {
-
        if (cvp->cv_waiters > 0) {
                wakeup_one((caddr_t)cvp);
                cvp->cv_waiters--;
@@ -283,7 +288,6 @@ _audit_cv_signal(struct cv *cvp)
 void
 _audit_cv_broadcast(struct cv *cvp)
 {
-
        if (cvp->cv_waiters > 0) {
                wakeup((caddr_t)cvp);
                cvp->cv_waiters = 0;
@@ -298,7 +302,6 @@ _audit_cv_broadcast(struct cv *cvp)
 void
 _audit_cv_wait(struct cv *cvp, lck_mtx_t *mp, const char *desc)
 {
-
        cvp->cv_waiters++;
        (void) msleep(cvp, mp, PZERO, desc, 0);
 }
@@ -312,9 +315,8 @@ _audit_cv_wait(struct cv *cvp, lck_mtx_t *mp, const char *desc)
 int
 _audit_cv_wait_sig(struct cv *cvp, lck_mtx_t *mp, const char *desc)
 {
-
        cvp->cv_waiters++;
-       return (msleep(cvp, mp, PSOCK | PCATCH, desc, 0));
+       return msleep(cvp, mp, PSOCK | PCATCH, desc, 0);
 }
 
 /*
@@ -327,20 +329,19 @@ _audit_mtx_init(struct mtx *mp, const char *lckname)
 _audit_mtx_init(struct mtx *mp, __unused const char *lckname)
 #endif
 {
-       mp->mtx_lock = lck_mtx_alloc_init(audit_lck_grp, LCK_ATTR_NULL);
-       KASSERT(mp->mtx_lock != NULL, 
+       mp->mtx_lock = lck_mtx_alloc_init(&audit_lck_grp, LCK_ATTR_NULL);
+       KASSERT(mp->mtx_lock != NULL,
            ("_audit_mtx_init: Could not allocate a mutex."));
 #if DIAGNOSTIC
-       strlcpy(mp->mtx_name, lckname, AU_MAX_LCK_NAME);        
+       strlcpy(mp->mtx_name, lckname, AU_MAX_LCK_NAME);
 #endif
 }
 
 void
 _audit_mtx_destroy(struct mtx *mp)
 {
-
        if (mp->mtx_lock) {
-               lck_mtx_free(mp->mtx_lock, audit_lck_grp);
+               lck_mtx_free(mp->mtx_lock, &audit_lck_grp);
                mp->mtx_lock = NULL;
        }
 }
@@ -355,20 +356,19 @@ _audit_rw_init(struct rwlock *lp, const char *lckname)
 _audit_rw_init(struct rwlock *lp, __unused const char *lckname)
 #endif
 {
-       lp->rw_lock = lck_rw_alloc_init(audit_lck_grp, LCK_ATTR_NULL);
-       KASSERT(lp->rw_lock != NULL, 
+       lp->rw_lock = lck_rw_alloc_init(&audit_lck_grp, LCK_ATTR_NULL);
+       KASSERT(lp->rw_lock != NULL,
            ("_audit_rw_init: Could not allocate a rw lock."));
 #if DIAGNOSTIC
-       strlcpy(lp->rw_name, lckname, AU_MAX_LCK_NAME); 
+       strlcpy(lp->rw_name, lckname, AU_MAX_LCK_NAME);
 #endif
 }
 
 void
 _audit_rw_destroy(struct rwlock *lp)
 {
-
        if (lp->rw_lock) {
-               lck_rw_free(lp->rw_lock, audit_lck_grp);
+               lck_rw_free(lp->rw_lock, &audit_lck_grp);
                lp->rw_lock = NULL;
        }
 }
@@ -395,7 +395,7 @@ _audit_cv_wait_continuation(struct cv *cvp, lck_mtx_t *mp, thread_continue_t fun
 }
 
 /*
- * Simple recursive lock. 
+ * Simple recursive lock.
  */
 void
 #if DIAGNOSTIC
@@ -404,12 +404,11 @@ _audit_rlck_init(struct rlck *lp, const char *lckname)
 _audit_rlck_init(struct rlck *lp, __unused const char *lckname)
 #endif
 {
-
-       lp->rl_mtx = lck_mtx_alloc_init(audit_lck_grp, LCK_ATTR_NULL);
-       KASSERT(lp->rl_mtx != NULL, 
+       lp->rl_mtx = lck_mtx_alloc_init(&audit_lck_grp, LCK_ATTR_NULL);
+       KASSERT(lp->rl_mtx != NULL,
            ("_audit_rlck_init: Could not allocate a recursive lock."));
 #if DIAGNOSTIC
-       strlcpy(lp->rl_name, lckname, AU_MAX_LCK_NAME); 
+       strlcpy(lp->rl_name, lckname, AU_MAX_LCK_NAME);
 #endif
        lp->rl_thread = 0;
        lp->rl_recurse = 0;
@@ -417,11 +416,10 @@ _audit_rlck_init(struct rlck *lp, __unused const char *lckname)
 
 /*
  * Recursive lock.  Allow same thread to recursively lock the same lock.
- */ 
+ */
 void
 _audit_rlck_lock(struct rlck *lp)
 {
-
        if (lp->rl_thread == current_thread()) {
                OSAddAtomic(1, &lp->rl_recurse);
                KASSERT(lp->rl_recurse < 10000,
@@ -439,7 +437,7 @@ _audit_rlck_lock(struct rlck *lp)
 void
 _audit_rlck_unlock(struct rlck *lp)
 {
-       KASSERT(lp->rl_thread == current_thread(), 
+       KASSERT(lp->rl_thread == current_thread(),
            ("_audit_rlck_unlock(): Don't own lock."));
 
        /* Note: OSAddAtomic returns old value. */
@@ -448,13 +446,12 @@ _audit_rlck_unlock(struct rlck *lp)
                lck_mtx_unlock(lp->rl_mtx);
        }
 }
-               
+
 void
 _audit_rlck_destroy(struct rlck *lp)
 {
-
        if (lp->rl_mtx) {
-               lck_mtx_free(lp->rl_mtx, audit_lck_grp);
+               lck_mtx_free(lp->rl_mtx, &audit_lck_grp);
                lp->rl_mtx = NULL;
        }
 }
@@ -466,13 +463,15 @@ void
 _audit_rlck_assert(struct rlck *lp, u_int assert)
 {
        thread_t cthd = current_thread();
-       
-       if (assert == LCK_MTX_ASSERT_OWNED && lp->rl_thread == cthd)
+
+       if (assert == LCK_MTX_ASSERT_OWNED && lp->rl_thread == cthd) {
                panic("recursive lock (%p) not held by this thread (%p).",
                    lp, cthd);
-       if (assert == LCK_MTX_ASSERT_NOTOWNED && lp->rl_thread != 0)
+       }
+       if (assert == LCK_MTX_ASSERT_NOTOWNED && lp->rl_thread != 0) {
                panic("recursive lock (%p) held by thread (%p).",
                    lp, cthd);
+       }
 }
 
 /*
@@ -485,12 +484,11 @@ _audit_slck_init(struct slck *lp, const char *lckname)
 _audit_slck_init(struct slck *lp, __unused const char *lckname)
 #endif
 {
-
-       lp->sl_mtx = lck_mtx_alloc_init(audit_lck_grp, LCK_ATTR_NULL);
-       KASSERT(lp->sl_mtx != NULL, 
+       lp->sl_mtx = lck_mtx_alloc_init(&audit_lck_grp, LCK_ATTR_NULL);
+       KASSERT(lp->sl_mtx != NULL,
            ("_audit_slck_init: Could not allocate a sleep lock."));
 #if DIAGNOSTIC
-       strlcpy(lp->sl_name, lckname, AU_MAX_LCK_NAME); 
+       strlcpy(lp->sl_name, lckname, AU_MAX_LCK_NAME);
 #endif
        lp->sl_locked = 0;
        lp->sl_waiting = 0;
@@ -498,7 +496,7 @@ _audit_slck_init(struct slck *lp, __unused const char *lckname)
 
 /*
  * Sleep lock lock.  The 'intr' flag determines if the lock is interruptible.
- * If 'intr' is true then signals or other events can interrupt the sleep lock. 
+ * If 'intr' is true then signals or other events can interrupt the sleep lock.
  */
 wait_result_t
 _audit_slck_lock(struct slck *lp, int intr)
@@ -509,13 +507,14 @@ _audit_slck_lock(struct slck *lp, int intr)
        while (lp->sl_locked && res == THREAD_AWAKENED) {
                lp->sl_waiting = 1;
                res = lck_mtx_sleep(lp->sl_mtx, LCK_SLEEP_DEFAULT,
-                  (event_t) lp, (intr) ? THREAD_INTERRUPTIBLE : THREAD_UNINT);
+                   (event_t) lp, (intr) ? THREAD_INTERRUPTIBLE : THREAD_UNINT);
        }
-       if (res == THREAD_AWAKENED)
+       if (res == THREAD_AWAKENED) {
                lp->sl_locked = 1;
+       }
        lck_mtx_unlock(lp->sl_mtx);
-       
-       return (res);
+
+       return res;
 }
 
 /*
@@ -524,7 +523,6 @@ _audit_slck_lock(struct slck *lp, int intr)
 void
 _audit_slck_unlock(struct slck *lp)
 {
-       
        lck_mtx_lock(lp->sl_mtx);
        lp->sl_locked = 0;
        if (lp->sl_waiting) {
@@ -537,7 +535,7 @@ _audit_slck_unlock(struct slck *lp)
 }
 
 /*
- * Sleep lock try.  Don't sleep if it doesn't get the lock. 
+ * Sleep lock try.  Don't sleep if it doesn't get the lock.
  */
 int
 _audit_slck_trylock(struct slck *lp)
@@ -546,11 +544,12 @@ _audit_slck_trylock(struct slck *lp)
 
        lck_mtx_lock(lp->sl_mtx);
        result = !lp->sl_locked;
-       if (result)
+       if (result) {
                lp->sl_locked = 1;
+       }
        lck_mtx_unlock(lp->sl_mtx);
 
-       return (result);
+       return result;
 }
 
 /*
@@ -559,19 +558,19 @@ _audit_slck_trylock(struct slck *lp)
 void
 _audit_slck_assert(struct slck *lp, u_int assert)
 {
-
-       if (assert == LCK_MTX_ASSERT_OWNED && lp->sl_locked == 0)
+       if (assert == LCK_MTX_ASSERT_OWNED && lp->sl_locked == 0) {
                panic("sleep lock (%p) not held.", lp);
-       if (assert == LCK_MTX_ASSERT_NOTOWNED && lp->sl_locked == 1)
+       }
+       if (assert == LCK_MTX_ASSERT_NOTOWNED && lp->sl_locked == 1) {
                panic("sleep lock (%p) held.", lp);
+       }
 }
 
 void
 _audit_slck_destroy(struct slck *lp)
 {
-
        if (lp->sl_mtx) {
-               lck_mtx_free(lp->sl_mtx, audit_lck_grp);
+               lck_mtx_free(lp->sl_mtx, &audit_lck_grp);
                lp->sl_mtx = NULL;
        }
 }
@@ -582,14 +581,14 @@ _audit_slck_destroy(struct slck *lp)
  */
 #ifndef timersub
 #define timersub(tvp, uvp, vvp)                                         \
-        do {                                                            \
-                (vvp)->tv_sec = (tvp)->tv_sec - (uvp)->tv_sec;          \
-                (vvp)->tv_usec = (tvp)->tv_usec - (uvp)->tv_usec;       \
-                if ((vvp)->tv_usec < 0) {                               \
-                        (vvp)->tv_sec--;                                \
-                        (vvp)->tv_usec += 1000000;                      \
-                }                                                       \
-        } while (0)
+       do {                                                            \
+               (vvp)->tv_sec = (tvp)->tv_sec - (uvp)->tv_sec;          \
+               (vvp)->tv_usec = (tvp)->tv_usec - (uvp)->tv_usec;       \
+               if ((vvp)->tv_usec < 0) {                               \
+                       (vvp)->tv_sec--;                                \
+                       (vvp)->tv_usec += 1000000;                      \
+               }                                                       \
+       } while (0)
 #endif
 
 /*
@@ -618,43 +617,52 @@ _audit_ppsratecheck(struct timeval *lasttime, int *curpps, int maxpps)
                *lasttime = tv;
                *curpps = 0;
                rv = 1;
-       } else if (maxpps < 0)
+       } else if (maxpps < 0) {
                rv = 1;
-       else if (*curpps < maxpps)
+       } else if (*curpps < maxpps) {
                rv = 1;
-       else
+       } else {
                rv = 0;
-       if (*curpps + 1 > 0)
+       }
+       if (*curpps + 1 > 0) {
                *curpps = *curpps + 1;
+       }
 
-       return (rv);    
+       return rv;
 }
 
-/*
- * Initialize lock group for audit related locks/mutexes.
- */
-void
-_audit_lck_grp_init(void)
+int
+audit_send_trigger(unsigned int trigger)
 {
-       audit_lck_grp = lck_grp_alloc_init("Audit", LCK_GRP_ATTR_NULL);
+       mach_port_t audit_port;
+       int error;
 
-       KASSERT(audit_lck_grp != NULL,
-           ("audit_get_lck_grp: Could not allocate the audit lock group."));
+       error = host_get_audit_control_port(host_priv_self(), &audit_port);
+       if (error == KERN_SUCCESS && audit_port != MACH_PORT_NULL) {
+               (void)audit_triggers(audit_port, trigger);
+               ipc_port_release_send(audit_port);
+               return 0;
+       } else {
+               printf("Cannot get audit control port\n");
+               return error;
+       }
 }
 
 int
-audit_send_trigger(unsigned int trigger)
+audit_send_analytics(char* signing_id, char* process_name)
 {
        mach_port_t audit_port;
        int error;
 
        error = host_get_audit_control_port(host_priv_self(), &audit_port);
        if (error == KERN_SUCCESS && audit_port != MACH_PORT_NULL) {
-               audit_triggers(audit_port, trigger);
-               return (0);
+               (void)audit_analytics(audit_port, signing_id, process_name);
+               ipc_port_release_send(audit_port);
+               return 0;
        } else {
-               printf("Cannot get audit control port\n");
-               return (error);
+               printf("Cannot get audit control port for analytics \n");
+               return error;
        }
 }
+
 #endif /* CONFIG_AUDIT */