]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/kern/kern_bsm_klib.c
xnu-1228.7.58.tar.gz
[apple/xnu.git] / bsd / kern / kern_bsm_klib.c
index ee69ec02efff102959904806015df1ea633d4d7a..f88f5bd38a7b6ab27ca73cacfc8b34038bdd76d2 100644 (file)
@@ -1,16 +1,19 @@
 /*
- * Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2004-2007 Apple Inc. All rights reserved.
  *
- * @APPLE_LICENSE_HEADER_START@
- * 
- * Copyright (c) 1999-2003 Apple Computer, Inc.  All Rights Reserved.
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  * 
  * This file contains Original Code and/or Modifications of Original Code
  * as defined in and that are subject to the Apple Public Source License
  * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ * 
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
  * 
  * The Original Code and all software distributed under the License are
  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  * Please see the License for the specific language governing rights and
  * limitations under the License.
  * 
- * @APPLE_LICENSE_HEADER_END@
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
+ */
+/*
+ * NOTICE: This file was modified by SPARTA, Inc. in 2005 to introduce
+ * support for mandatory and extensible security protections.  This notice
+ * is included in support of clause 2.2 (b) of the Apple Public License,
+ * Version 2.0.
  */
 
+#include <sys/systm.h>
+#include <sys/sysent.h>
 #include <sys/types.h>
-#include <sys/vnode.h>
+#include <sys/proc_internal.h>
+#include <sys/vnode_internal.h>
 #include <sys/fcntl.h>
 #include <sys/filedesc.h>
 #include <sys/sem.h>
-#include <sys/audit.h>
-#include <sys/kern_audit.h>
-#include <sys/bsm_kevents.h>
-#include <sys/bsm_klib.h>
+
+#include <bsm/audit.h>
+#include <bsm/audit_kernel.h>
+#include <bsm/audit_kevents.h>
+#include <bsm/audit_klib.h>
+
+#include <kern/kalloc.h>
 
 /*
  * Initialize the system call to audit event mapping table. This table 
 au_event_t sys_au_event[] = {
        AUE_NULL,                       /*   0 = indir */
        AUE_EXIT,                       /*   1 = exit */
-       AUE_NULL,                       /*   2 = fork */
+       AUE_FORK,                       /*   2 = fork */
        AUE_NULL,                       /*   3 = read */
        AUE_NULL,                       /*   4 = write */
-       AUE_OPEN_R,                     /*   5 = open */
-       AUE_NULL,                       /*   6 = close */
+       AUE_OPEN_RWTC,                  /*   5 = open */
+       AUE_CLOSE,                      /*   6 = close */
        AUE_NULL,                       /*   7 = wait4 */
-       AUE_NULL,                       /*   8 = old creat */
+       AUE_O_CREAT,                    /*   8 = old creat */
        AUE_LINK,                       /*   9 = link */
        AUE_UNLINK,                     /*  10 = unlink */
        AUE_NULL,                       /*  11 was obsolete execv */
@@ -62,9 +77,9 @@ au_event_t sys_au_event[] = {
        AUE_CHOWN,                      /*  16 = chown; now 3 args */
        AUE_NULL,                       /*  17 = old break */
 #if COMPAT_GETFSSTAT
-       AUE_NULL,                       /*  18 = ogetfsstat */
-#else
        AUE_GETFSSTAT,                  /*  18 = getfsstat */
+#else
+       AUE_NULL,                       /*  18 = ogetfsstat */
 #endif
        AUE_NULL,                       /*  19 = old lseek */
        AUE_NULL,                       /*  20 = getpid */
@@ -73,7 +88,7 @@ au_event_t sys_au_event[] = {
        AUE_SETUID,                     /*  23 = setuid */
        AUE_NULL,                       /*  24 = getuid */
        AUE_NULL,                       /*  25 = geteuid */
-       AUE_NULL,                       /*  26 = ptrace */
+       AUE_PTRACE,                     /*  26 = ptrace */
        AUE_RECVMSG,                    /*  27 = recvmsg */
        AUE_SENDMSG,                    /*  28 = sendmsg */
        AUE_RECVFROM,                   /*  29 = recvfrom */
@@ -84,44 +99,44 @@ au_event_t sys_au_event[] = {
        AUE_CHFLAGS,                    /* 34 = chflags */
        AUE_FCHFLAGS,                   /* 35 = fchflags */
        AUE_NULL,                       /*  36 = sync */
-       AUE_NULL,                       /*  37 = kill */
-       AUE_NULL,                       /*  38 = old stat */
+       AUE_KILL,                       /*  37 = kill */
+       AUE_O_STAT,                     /*  38 = old stat */
        AUE_NULL,                       /*  39 = getppid */
-       AUE_NULL,                       /*  40 = old lstat */
+       AUE_O_LSTAT,                    /*  40 = old lstat */
        AUE_NULL,                       /*  41 = dup */
        AUE_PIPE,                       /*  42 = pipe */
        AUE_NULL,                       /*  43 = getegid */
        AUE_NULL,                       /*  44 = profil */
-       AUE_NULL,                       /*  45 = ktrace */
+       AUE_NULL,                       /*  45 = old ktrace */
        AUE_NULL,                       /*  46 = sigaction */
        AUE_NULL,                       /*  47 = getgid */
        AUE_NULL,                       /*  48 = sigprocmask */
        AUE_NULL,                       /*  49 = getlogin */
-       AUE_NULL,                       /*  50 = setlogin */
-       AUE_NULL,                       /*  51 = turn acct off/on */
+       AUE_SETLOGIN,                   /*  50 = setlogin */
+       AUE_ACCT,                       /*  51 = turn acct off/on */
        AUE_NULL,                       /*  52 = sigpending */
        AUE_NULL,                       /*  53 = sigaltstack */
-       AUE_NULL,                       /*  54 = ioctl */
-       AUE_NULL,                       /*  55 = reboot */
+       AUE_IOCTL,                      /*  54 = ioctl */
+       AUE_REBOOT,                     /*  55 = reboot */
        AUE_REVOKE,                     /*  56 = revoke */
        AUE_SYMLINK,                    /*  57 = symlink */
        AUE_READLINK,                   /*  58 = readlink */
        AUE_EXECVE,                     /*  59 = execve */
        AUE_UMASK,                      /*  60 = umask */
        AUE_CHROOT,                     /*  61 = chroot */
-       AUE_NULL,                       /*  62 = old fstat */
+       AUE_O_FSTAT,                    /*  62 = old fstat */
        AUE_NULL,                       /*  63 = used internally, reserved */
        AUE_NULL,                       /*  64 = old getpagesize */
        AUE_NULL,                       /*  65 = msync */
-       AUE_NULL,                       /*  66 = vfork */
+       AUE_VFORK,                      /*  66 = vfork */
        AUE_NULL,                       /*  67 was obsolete vread */
        AUE_NULL,                       /*  68 was obsolete vwrite */
        AUE_NULL,                       /*  69 = sbrk */
        AUE_NULL,                       /*  70 = sstk */
-       AUE_NULL,                       /*  71 = old mmap */
+       AUE_O_MMAP,                     /*  71 = old mmap */
        AUE_NULL,                       /*  72 = old vadvise */
-       AUE_NULL,                       /*  73 = munmap */
-       AUE_NULL,                       /*  74 = mprotect */
+       AUE_MUNMAP,                     /*  73 = munmap */
+       AUE_MPROTECT,                   /*  74 = mprotect */
        AUE_NULL,                       /*  75 = madvise */
        AUE_NULL,                       /*  76 was obsolete vhangup */
        AUE_NULL,                       /*  77 was obsolete vlimit */
@@ -135,7 +150,7 @@ au_event_t sys_au_event[] = {
        AUE_NULL,                       /*  85 = swapon */
        AUE_NULL,                       /*  86 = getitimer */
        AUE_NULL,                       /*  87 = old gethostname */
-       AUE_NULL,                       /*  88 = old sethostname */
+       AUE_O_SETHOSTNAME,              /*  88 = old sethostname */
        AUE_NULL,                       /* 89 getdtablesize */
        AUE_NULL,                       /*  90 = dup2 */
        AUE_NULL,                       /*  91 was obsolete getdopt */
@@ -143,13 +158,13 @@ au_event_t sys_au_event[] = {
        AUE_NULL,                       /*  93 = select */
        AUE_NULL,                       /*  94 was obsolete setdopt */
        AUE_NULL,                       /*  95 = fsync */
-       AUE_NULL,                       /*  96 = setpriority */
+       AUE_SETPRIORITY,                /*  96 = setpriority */
        AUE_SOCKET,                     /*  97 = socket */
        AUE_CONNECT,                    /*  98 = connect */
        AUE_NULL,                       /*  99 = accept */
        AUE_NULL,                       /* 100 = getpriority */
-       AUE_NULL,                       /* 101 = old send */
-       AUE_NULL,                       /* 102 = old recv */
+       AUE_O_SEND,                     /* 101 = old send */
+       AUE_O_RECV,                     /* 102 = old recv */
        AUE_NULL,                       /* 103 = sigreturn */
        AUE_BIND,                       /* 104 = bind */
        AUE_SETSOCKOPT,                 /* 105 = setsockopt */
@@ -160,8 +175,8 @@ au_event_t sys_au_event[] = {
        AUE_NULL,                       /* 110 = sigsetmask */
        AUE_NULL,                       /* 111 = sigpause */
        AUE_NULL,                       /* 112 = sigstack */
-       AUE_NULL,                       /* 113 = recvmsg */
-       AUE_NULL,                       /* 114 = sendmsg */
+       AUE_O_RECVMSG,                  /* 113 = recvmsg */
+       AUE_O_SENDMSG,                  /* 114 = sendmsg */
        AUE_NULL,                       /* 115 = old vtrace */
        AUE_NULL,                       /* 116 = gettimeofday */
        AUE_NULL,                       /* 117 = getrusage */
@@ -169,15 +184,15 @@ au_event_t sys_au_event[] = {
        AUE_NULL,                       /* 119 = old resuba */
        AUE_NULL,                       /* 120 = readv */
        AUE_NULL,                       /* 121 = writev */
-       AUE_NULL,                       /* 122 = settimeofday */
+       AUE_SETTIMEOFDAY,               /* 122 = settimeofday */
        AUE_FCHOWN,                     /* 123 = fchown */
        AUE_FCHMOD,                     /* 124 = fchmod */
-       AUE_NULL,                       /* 125 = recvfrom */
+       AUE_O_RECVFROM,                 /* 125 = recvfrom */
        AUE_NULL,                       /* 126 = setreuid */
        AUE_NULL,                       /* 127 = setregid */
        AUE_RENAME,                     /* 128 = rename */
-       AUE_NULL,                       /* 129 = old truncate */
-       AUE_NULL,                       /* 130 = old ftruncate */
+       AUE_O_TRUNCATE,                 /* 129 = old truncate */
+       AUE_O_FTRUNCATE,                /* 130 = old ftruncate */
        AUE_FLOCK,                      /* 131 = flock */
        AUE_MKFIFO,                     /* 132 = mkfifo */
        AUE_SENDTO,                     /* 133 = sendto */
@@ -192,25 +207,25 @@ au_event_t sys_au_event[] = {
        AUE_NULL,                       /* 142 = old gethostid */
        AUE_NULL,                       /* 143 = old sethostid */
        AUE_NULL,                       /* 144 = old getrlimit */
-       AUE_NULL,                       /* 145 = old setrlimit */
-       AUE_NULL,                       /* 146 = old killpg */
-       AUE_NULL,                       /* 147 = setsid */
+       AUE_O_SETRLIMIT,                /* 145 = old setrlimit */
+       AUE_O_KILLPG,                   /* 146 = old killpg */
+       AUE_SETSID,                     /* 147 = setsid */
        AUE_NULL,                       /* 148 was setquota */
        AUE_NULL,                       /* 149 was qquota */
        AUE_NULL,                       /* 150 = getsockname */
        AUE_NULL,                       /* 151 = getpgid */
-       AUE_NULL,                       /* 152 = setprivexec */
+       AUE_SETPRIVEXEC,                /* 152 = setprivexec */
        AUE_NULL,                       /* 153 = pread */
        AUE_NULL,                       /* 154 = pwrite */
-       AUE_NULL,                       /* 155 = nfs_svc */
-       AUE_NULL,                       /* 156 = old getdirentries */
+       AUE_NFSSVC,                     /* 155 = nfs_svc */
+       AUE_O_GETDIRENTRIES,            /* 156 = old getdirentries */
        AUE_STATFS,                     /* 157 = statfs */
        AUE_FSTATFS,                    /* 158 = fstatfs */
-       AUE_UMOUNT,                     /* 159 = unmount */
+       AUE_UNMOUNT,                    /* 159 = unmount */
        AUE_NULL,                       /* 160 was async_daemon */
        AUE_GETFH,                      /* 161 = get file handle */
        AUE_NULL,                       /* 162 = getdomainname */
-       AUE_NULL,                       /* 163 = setdomainname */
+       AUE_O_SETDOMAINNAME,            /* 163 = setdomainname */
        AUE_NULL,                       /* 164 */
 #if    QUOTA
        AUE_QUOTACTL,                   /* 165 = quotactl */
@@ -244,7 +259,6 @@ au_event_t sys_au_event[] = {
        AUE_LSTAT,                      /* 190 = lstat */
        AUE_PATHCONF,                   /* 191 = pathconf */
        AUE_FPATHCONF,                  /* 192 = fpathconf */
-
 #if COMPAT_GETFSSTAT
        AUE_GETFSSTAT,                  /* 193 = getfsstat */
 #else
@@ -253,14 +267,14 @@ au_event_t sys_au_event[] = {
        AUE_NULL,                       /* 194 = getrlimit */
        AUE_SETRLIMIT,                  /* 195 = setrlimit */
        AUE_GETDIRENTRIES,              /* 196 = getdirentries */
-       AUE_NULL,                       /* 197 = mmap */
+       AUE_MMAP,                       /* 197 = mmap */
        AUE_NULL,                       /* 198 = __syscall */
        AUE_NULL,                       /* 199 = lseek */
        AUE_TRUNCATE,                   /* 200 = truncate */
        AUE_FTRUNCATE,                  /* 201 = ftruncate */
-       AUE_NULL,                       /* 202 = __sysctl */
-       AUE_NULL,                       /* 203 = mlock */
-       AUE_NULL,                       /* 204 = munlock */
+       AUE_SYSCTL,                     /* 202 = __sysctl */
+       AUE_MLOCK,                      /* 203 = mlock */
+       AUE_MUNLOCK,                    /* 204 = munlock */
        AUE_UNDELETE,                   /* 205 = undelete */
        AUE_NULL,                       /* 206 = ATsocket */
        AUE_NULL,                       /* 207 = ATgetmsg*/
@@ -281,9 +295,9 @@ au_event_t sys_au_event[] = {
        AUE_SETATTRLIST,/* 221 = HFS setattrlist set attribute list */
        AUE_GETDIRENTRIESATTR,/* 222 = HFS getdirentriesattr get directory attributes */
        AUE_EXCHANGEDATA,/* 223 = HFS exchangedata exchange file contents */
-       AUE_NULL,/* 224 = HFS checkuseraccess check access to a file */
+       AUE_CHECKUSERACCESS,/* 224 = HFS checkuseraccess check access to file */
        AUE_SEARCHFS,   /* 225 = HFS searchfs to implement catalog searching */
-       AUE_NULL,       /* 226 = private delete (Carbon semantics) */
+       AUE_DELETE,     /* 226 = private delete (Carbon semantics) */
        AUE_NULL,       /* 227 = copyfile - orignally for AFP */
        AUE_NULL,                       /* 228 */
        AUE_NULL,                       /* 229 */
@@ -307,14 +321,14 @@ au_event_t sys_au_event[] = {
        AUE_NULL,                       /* 247 = nfsclnt*/
        AUE_NULL,                       /* 248 = fhopen */
        AUE_NULL,                       /* 249 */
-       AUE_NULL,                       /* 250 = minherit */
+       AUE_MINHERIT,                   /* 250 = minherit */
        AUE_NULL,                       /* 251 = semsys */
        AUE_NULL,                       /* 252 = msgsys */
        AUE_NULL,                       /* 253 = shmsys */
        AUE_SEMCTL,                     /* 254 = semctl */
        AUE_SEMGET,                     /* 255 = semget */
        AUE_SEMOP,                      /* 256 = semop */
-       AUE_NULL,                       /* 257 = semconfig */
+       AUE_NULL,                       /* 257 = */
        AUE_MSGCTL,                     /* 258 = msgctl */
        AUE_MSGGET,                     /* 259 = msgget */
        AUE_MSGSND,                     /* 260 = msgsnd */
@@ -323,11 +337,11 @@ au_event_t sys_au_event[] = {
        AUE_SHMCTL,                     /* 263 = shmctl */
        AUE_SHMDT,                      /* 264 = shmdt */
        AUE_SHMGET,                     /* 265 = shmget */
-       AUE_NULL,                       /* 266 = shm_open */
-       AUE_NULL,                       /* 267 = shm_unlink */
-       AUE_NULL,                       /* 268 = sem_open */
-       AUE_NULL,                       /* 269 = sem_close */
-       AUE_NULL,                       /* 270 = sem_unlink */
+       AUE_SHMOPEN,                    /* 266 = shm_open */
+       AUE_SHMUNLINK,                  /* 267 = shm_unlink */
+       AUE_SEMOPEN,                    /* 268 = sem_open */
+       AUE_SEMCLOSE,                   /* 269 = sem_close */
+       AUE_SEMUNLINK,                  /* 270 = sem_unlink */
        AUE_NULL,                       /* 271 = sem_wait */
        AUE_NULL,                       /* 272 = sem_trywait */
        AUE_NULL,                       /* 273 = sem_post */
@@ -353,9 +367,9 @@ au_event_t sys_au_event[] = {
        AUE_NULL,                       /* 293 */
        AUE_NULL,                       /* 294 */
        AUE_NULL,                       /* 295 */
-       AUE_NULL,                       /* 296 = load_shared_file */
-       AUE_NULL,                       /* 297 = reset_shared_file */
-       AUE_NULL,                       /* 298 = new_system_shared_regions */
+       AUE_NULL,                       /* 296 */
+       AUE_NULL,                       /* 297 */
+       AUE_NULL,                       /* 298 */
        AUE_NULL,                       /* 299 */
        AUE_NULL,                       /* 300 */
        AUE_NULL,                       /* 301 */
@@ -408,189 +422,204 @@ au_event_t sys_au_event[] = {
        AUE_NULL,                       /* 348 */
        AUE_NULL,                       /* 349 */
        AUE_AUDIT,                      /* 350 */
-       AUE_NULL,                       /* 351 */
+       AUE_AUDITON,                    /* 351 */
        AUE_NULL,                       /* 352 */
        AUE_GETAUID,                    /* 353 */
        AUE_SETAUID,                    /* 354 */
-       AUE_NULL,                       /* 355 */
-       AUE_NULL,                       /* 356 */
-       AUE_NULL,                       /* 357 */
-       AUE_NULL,                       /* 358 */
-       AUE_NULL,                       /* 359 */
+       AUE_GETAUDIT,                   /* 355 */
+       AUE_SETAUDIT,                   /* 356 */
+       AUE_GETAUDIT_ADDR,              /* 357 */
+       AUE_SETAUDIT_ADDR,              /* 358 */
+       AUE_AUDITCTL,                   /* 359 */
        AUE_NULL,                       /* 360 */
        AUE_NULL,                       /* 361 */
        AUE_NULL,                       /* 362 = kqueue */
        AUE_NULL,                       /* 363 = kevent */
-       AUE_NULL,                       /* 364 */
+       AUE_LCHOWN,                     /* 364 = lchown */
        AUE_NULL,                       /* 365 */
        AUE_NULL,                       /* 366 */
        AUE_NULL,                       /* 367 */
        AUE_NULL,                       /* 368 */
-       AUE_NULL                        /* 369 */
+       AUE_NULL,                       /* 369 */
+       AUE_NULL,                       /* 370 */
+       AUE_NULL,                       /* 371 */
+       AUE_NULL,                       /* 372 */
+       AUE_NULL,                       /* 373 */
+       AUE_NULL,                       /* 374 */
+       AUE_NULL,                       /* 375 */
+       AUE_NULL,                       /* 376 */
+       AUE_NULL,                       /* 377 */
+       AUE_NULL,                       /* 378 */
+       AUE_NULL,                       /* 379 */
+       AUE_MAC_EXECVE,                 /* 380 = __mac_execve */
+       AUE_MAC_SYSCALL,                /* 381 = __mac_syscall */
+       AUE_MAC_GET_FILE,               /* 382 = __mac_get_file */
+       AUE_MAC_SET_FILE,               /* 383 = __mac_set_file */
+       AUE_MAC_GET_LINK,               /* 384 = __mac_get_link */
+       AUE_MAC_SET_LINK,               /* 385 = __mac_set_link */
+       AUE_MAC_GET_PROC,                       /* 386 = __mac_get_proc */
+       AUE_MAC_SET_PROC,               /* 387 = __mac_set_proc */
+       AUE_MAC_GET_FD,                 /* 388 = __mac_get_fd */
+       AUE_MAC_SET_FD,                 /* 389 = __mac_set_fd */
+       AUE_MAC_GET_PID,                /* 390 = __mac_get_pid */
+       AUE_MAC_GET_LCID,               /* 391 = __mac_get_lcid */
+       AUE_MAC_GET_LCTX,               /* 392 = __mac_get_lctx */
+       AUE_MAC_SET_LCTX,               /* 393 = __mac_set_lctx */
+       AUE_SETLCID,                    /* 394 = setlcid */
+       AUE_GETLCID,                    /* 395 = getlcid */
+       AUE_NULL,                       /* 396 = read_nocancel */
+       AUE_NULL,                       /* 397 = write_nocancel */
+       AUE_OPEN_RWTC,                  /* 398 = open_nocancel */
+       AUE_CLOSE,                      /* 399 = close_nocancel */
+       AUE_NULL,                       /* 400 = wait4_nocancel */
+       AUE_RECVMSG,                    /* 401 = recvmsg_nocancel */
+       AUE_SENDMSG,                    /* 402 = sendmsg_nocancel */
+       AUE_RECVFROM,                   /* 403 = recvfrom_nocancel */
+       AUE_ACCEPT,                     /* 404 = accept_nocancel */
+       AUE_NULL,                       /* 405 = msync_nocancel */
+       AUE_FCNTL,                      /* 406 = fcntl_nocancel */
+       AUE_NULL,                       /* 407 = select_nocancel */
+       AUE_NULL,                       /* 408 = fsync_nocancel */
+       AUE_CONNECT,                    /* 409 = connect_nocancel */
+       AUE_NULL,                       /* 410 = sigsuspend_nocancel */
+       AUE_NULL,                       /* 411 = readv_nocancel */
+       AUE_NULL,                       /* 412 = writev_nocancel */
+       AUE_SENDTO,                     /* 413 = sendto_nocancel */
+       AUE_NULL,                       /* 414 = pread_nocancel */
+       AUE_NULL,                       /* 415 = pwrite_nocancel */
+       AUE_NULL,                       /* 416 = waitid_nocancel */
+       AUE_NULL,                       /* 417 = poll_nocancel */
+       AUE_MSGSND,                     /* 418 = msgsnd_nocancel */
+       AUE_MSGRCV,                     /* 419 = msgrcv_nocancel */
+       AUE_NULL,                       /* 420 = sem_wait_nocancel */
+       AUE_NULL,                       /* 421 = aio_suspend_nocancel */
+       AUE_NULL,                       /* 422 = __sigwait_nocancel */
+       AUE_NULL,                       /* 423 = __semwait_signal_nocancel */
+       AUE_MAC_MOUNT,                  /* 424 = __mac_mount */
+       AUE_MAC_GET_MOUNT,              /* 425 = __mac_get_mount */
+       AUE_MAC_GETFSSTAT,              /* 426 = __mac_getfsstat */
+
 };
-int    nsys_au_event = sizeof(sys_au_event) / sizeof(sys_au_event[0]);
 
 /*
- * Check whether an event is aditable by comparing the mask of classes this
- * event is part of against the kernel's preselection mask the given mask
- * which will be the process event mask.
- *
- * XXX This needs to eventually implement the selection based on the 
- *     event->class mapping that is controlled by a configuration file.
+ * Verify that sys_au_event has an entry for every syscall.
  */
-int au_preselect(au_event_t event, au_mask_t *mask_p, int sorf)
+int    audit_sys_table_size_check[(
+               (sizeof(sys_au_event) / sizeof(sys_au_event[0])) == NUM_SYSENT)?
+                       1 : -1] __unused;
+
+/*
+ * Hash table functions for the audit event number to event class mask mapping.
+ */
+
+#define EVCLASSMAP_HASH_TABLE_SIZE 251
+struct evclass_elem {
+       au_event_t event;
+       au_class_t class;
+       LIST_ENTRY(evclass_elem) entry;
+};
+struct evclass_list {
+       LIST_HEAD(, evclass_elem) head;
+};
+
+struct evclass_list evclass_hash[EVCLASSMAP_HASH_TABLE_SIZE];
+
+au_class_t au_event_class(au_event_t event)
 {
-       au_class_t ae_class;
-       au_class_t effmask = 0;
 
-       if(mask_p == NULL)
-               return (-1);
+       struct evclass_list *evcl;
+       struct evclass_elem *evc;
+
+       evcl = &evclass_hash[event % EVCLASSMAP_HASH_TABLE_SIZE];
+
+       /* If an entry at our hash location matches the event, just return */
+       LIST_FOREACH(evc, &evcl->head, entry) {
+               if (evc->event == event)
+                       return (evc->class);
+       }
+       return (AU_NULL);
+}
 
        /*
-        * XXX Set the event class using a big ugly switch statement. This      
-        * will change to use the mapping defined by a configuration file.
-        */
-       switch (event) {
-       case AUE_MMAP:
-       case AUE_PIPE:
-               /* mmap() and pipe() are AU_NULL in some systems; we'll
-                * place them in AU_IPC for now.
+ * Insert a event to class mapping. If the event already exists in the
+ * mapping, then replace the mapping with the new one.
+ * XXX There is currently no constraints placed on the number of mappings.
+ *     May want to either limit to a number, or in terms of memory usage.
                 */
-               ae_class = AU_IPC; break;
-       case AUE_READLINK:
-       case AUE_GETDIRENTRIES:
-               ae_class = AU_FREAD; break;
-       case AUE_ACCESS:
-       case AUE_FSTAT:
-       case AUE_FSTATFS:
-       case AUE_GETFH:
-       case AUE_LSTAT:
-       case AUE_FPATHCONF:
-       case AUE_PATHCONF:
-       case AUE_STAT:
-       case AUE_STATFS:
-       case AUE_GETATTRLIST:
-       case AUE_GETFSSTAT:
-       case AUE_GETDIRENTRIESATTR:
-       case AUE_SEARCHFS:
-               ae_class = AU_FACCESS; break;
-       case AUE_CHMOD:
-       case AUE_CHOWN:
-       case AUE_FCHMOD:
-       case AUE_FCHOWN:
-       case AUE_FCNTL:
-       case AUE_FLOCK:
-       case AUE_UTIMES:
-       case AUE_CHFLAGS:
-       case AUE_FCHFLAGS:
-       case AUE_FUTIMES:
-       case AUE_SETATTRLIST:
-       case AUE_TRUNCATE:
-       case AUE_FTRUNCATE:
-       case AUE_UNDELETE:
-       case AUE_EXCHANGEDATA:
-               ae_class = AU_FMODIFY; break;
-       case AUE_LINK:
-       case AUE_MKDIR:
-       case AUE_MKNOD:
-       case AUE_SYMLINK:
-       case AUE_MKFIFO:
-               ae_class = AU_FCREATE; break;
-       case AUE_RMDIR:
-       case AUE_UNLINK:
-               ae_class = AU_FDELETE; break;
-       case AUE_CLOSE:
-       case AUE_MUNMAP:
-       case AUE_REVOKE:
-               ae_class = AU_CLOSE; break;
-       case AUE_CHDIR:
-       case AUE_CHROOT:
-       case AUE_EXIT:
-       case AUE_FCHDIR:
-       case AUE_FORK:
-       case AUE_KILL:
-       case AUE_SETEGID:
-       case AUE_SETEUID:
-       case AUE_SETGID:
-       case AUE_SETGROUPS:
-       case AUE_SETPGRP:
-       case AUE_SETUID:
-       case AUE_VFORK:
-       case AUE_UMASK:
-               ae_class = AU_PROCESS; break;
-       case AUE_ACCEPT:
-       case AUE_BIND:
-       case AUE_CONNECT:
-       case AUE_RECVFROM:
-       case AUE_RECVMSG:
-       case AUE_SENDMSG:
-       case AUE_SENDTO:
-       case AUE_SETSOCKOPT:
-       case AUE_SHUTDOWN:
-       case AUE_SOCKET:
-       case AUE_SOCKETPAIR:
-               ae_class = AU_NET; break;
-       case AUE_MSGCTL:
-       case AUE_MSGGET:
-       case AUE_MSGRCV:
-       case AUE_MSGSND:
-       case AUE_SEMCTL:
-       case AUE_SEMGET:
-       case AUE_SEMOP:
-       case AUE_SHMAT:
-       case AUE_SHMCTL:
-       case AUE_SHMDT:
-       case AUE_SHMGET:
-               ae_class = AU_IPC; break;
-       case AUE_ACCT:
-       case AUE_ADJTIME:
-       case AUE_GETAUID:
-       case AUE_MOUNT:
-       case AUE_SETAUID:
-       case AUE_SETRLIMIT:
-       case AUE_UMOUNT:
-               ae_class = AU_ADMIN; break;
-       case AUE_IOCTL:
-               ae_class = AU_IOCTL; break;
-       case AUE_EXECVE:
-               ae_class = AU_PROCESS|AU_EXEC; break;
-       case AUE_OPEN_R:
-               ae_class = AU_FREAD; break;
-        case AUE_OPEN_RC:
-               ae_class = AU_FREAD|AU_FCREATE; break;
-        case AUE_OPEN_RTC:
-               ae_class = AU_FREAD|AU_FCREATE|AU_FDELETE; break;
-        case AUE_OPEN_RT:
-               ae_class = AU_FREAD|AU_FDELETE; break;
-        case AUE_OPEN_RW:
-               ae_class = AU_FREAD|AU_FWRITE; break;
-        case AUE_OPEN_RWC:
-               ae_class = AU_FREAD|AU_FWRITE|AU_FCREATE; break;
-        case AUE_OPEN_RWTC:
-               ae_class = AU_FREAD|AU_FWRITE|AU_FCREATE|AU_FDELETE; break;
-        case AUE_OPEN_RWT:
-               ae_class = AU_FREAD|AU_FWRITE|AU_FDELETE; break;
-        case AUE_OPEN_W:
-               ae_class = AU_FWRITE; break;
-        case AUE_OPEN_WC:
-               ae_class = AU_FWRITE|AU_FCREATE; break;
-        case AUE_OPEN_WTC:
-               ae_class = AU_FWRITE|AU_FCREATE|AU_FDELETE; break;
-        case AUE_OPEN_WT:
-               ae_class = AU_FWRITE|AU_FDELETE; break;
-       case AUE_RENAME:
-               ae_class = AU_FCREATE|AU_FDELETE; break;
-       default:        /* Assign the event to all classes */
-               ae_class = AU_ALL; break;
+void au_evclassmap_insert(au_event_t event, au_class_t class) 
+{
+       struct evclass_list *evcl;
+       struct evclass_elem *evc;
+
+       evcl = &evclass_hash[event % EVCLASSMAP_HASH_TABLE_SIZE];
+
+       LIST_FOREACH(evc, &evcl->head, entry) {
+               if (evc->event == event) {
+                       evc->class = class;
+                       return;
+               }
+       }
+       evc = (struct evclass_elem *)kalloc(sizeof (*evc));
+       if (evc == NULL) {
+               return;
+       }
+       evc->event = event;
+       evc->class = class;
+       LIST_INSERT_HEAD(&evcl->head, evc, entry);
+}
+
+void
+au_evclassmap_init(void)
+{
+       int i;
+       for (i = 0; i < EVCLASSMAP_HASH_TABLE_SIZE; i++) {
+               LIST_INIT(&evclass_hash[i].head);
        }
 
+       /* Set up the initial event to class mapping for system calls.  */ 
+       for (i = 0; i < NUM_SYSENT; i++) {
+               if (sys_au_event[i] != AUE_NULL) {
+                       au_evclassmap_insert(sys_au_event[i], AU_NULL);
+       }
+       }
+       /* Add the Mach system call events */
+       au_evclassmap_insert(AUE_TASKFORPID, AU_NULL);
+       au_evclassmap_insert(AUE_PIDFORTASK, AU_NULL);
+       au_evclassmap_insert(AUE_SWAPON, AU_NULL);
+       au_evclassmap_insert(AUE_SWAPOFF, AU_NULL);
+       au_evclassmap_insert(AUE_MAPFD, AU_NULL);
+       au_evclassmap_insert(AUE_INITPROCESS, AU_NULL);
+
+       /* Add the specific open events to the mapping. */
+       au_evclassmap_insert(AUE_OPEN_R, AU_FREAD);
+       au_evclassmap_insert(AUE_OPEN_RC, AU_FREAD|AU_FCREATE);
+       au_evclassmap_insert(AUE_OPEN_RTC, AU_FREAD|AU_FCREATE|AU_FDELETE);
+       au_evclassmap_insert(AUE_OPEN_RT, AU_FREAD|AU_FDELETE);
+       au_evclassmap_insert(AUE_OPEN_RW, AU_FREAD|AU_FWRITE);
+       au_evclassmap_insert(AUE_OPEN_RWC, AU_FREAD|AU_FWRITE|AU_FCREATE);
+       au_evclassmap_insert(AUE_OPEN_RWTC, AU_FREAD|AU_FWRITE|AU_FCREATE|AU_FDELETE);
+       au_evclassmap_insert(AUE_OPEN_RWT, AU_FREAD|AU_FWRITE|AU_FDELETE);
+       au_evclassmap_insert(AUE_OPEN_W, AU_FWRITE);
+       au_evclassmap_insert(AUE_OPEN_WC, AU_FWRITE|AU_FCREATE);
+       au_evclassmap_insert(AUE_OPEN_WTC, AU_FWRITE|AU_FCREATE|AU_FDELETE);
+       au_evclassmap_insert(AUE_OPEN_WT, AU_FWRITE|AU_FDELETE);
+}
+
        /* 
-        * Perform the actual check of the masks against the event.
+ * Check whether an event is aditable by comparing the mask of classes this
+ * event is part of against the given mask.
         */
+int au_preselect(au_event_t event, au_mask_t *mask_p, int sorf)
+{
+       au_class_t effmask = 0;
+       au_class_t ae_class;
+
+       if(mask_p == NULL)
+               return (-1);
+
+       ae_class = au_event_class(event);
        /*
-        * XXX Need to compare against the kernel mask??? Or do we not do
-        * that by default and let the client code just call this function
-        * with the kernel preselection mask as the mask parameter?
+        * Perform the actual check of the masks against the event.
         */
        if(sorf & AU_PRS_SUCCESS) {
                effmask |= (mask_p->am_success & ae_class);
@@ -606,11 +635,61 @@ int au_preselect(au_event_t event, au_mask_t *mask_p, int sorf)
                return (0);
 }
 
+/*
+ * Convert sysctl names and present arguments to events
+ */
+au_event_t ctlname_to_sysctlevent(int name[], uint64_t valid_arg) {
+
+       /* can't parse it - so return the worst case */
+       if ((valid_arg & (ARG_CTLNAME | ARG_LEN)) != 
+                        (ARG_CTLNAME | ARG_LEN))
+               return AUE_SYSCTL;
+
+       switch (name[0]) {
+       /* non-admin "lookups" treat them special */
+       case KERN_OSTYPE:
+       case KERN_OSRELEASE:
+       case KERN_OSREV:
+       case KERN_VERSION:
+       case KERN_ARGMAX:
+       case KERN_CLOCKRATE:
+       case KERN_BOOTTIME:
+       case KERN_POSIX1:
+       case KERN_NGROUPS:
+       case KERN_JOB_CONTROL:
+       case KERN_SAVED_IDS:
+       case KERN_NETBOOT:
+       case KERN_SYMFILE:
+       case KERN_SHREG_PRIVATIZABLE:
+               return AUE_SYSCTL_NONADMIN;
+
+       /* only treat the sets as admin */
+       case KERN_MAXVNODES:
+       case KERN_MAXPROC:
+       case KERN_MAXFILES:
+       case KERN_MAXPROCPERUID:
+       case KERN_MAXFILESPERPROC:
+       case KERN_HOSTID:
+       case KERN_AIOMAX:
+       case KERN_AIOPROCMAX:
+       case KERN_AIOTHREADS:
+       case KERN_COREDUMP:
+       case KERN_SUGID_COREDUMP:
+               return (valid_arg & ARG_VALUE) ?
+                       AUE_SYSCTL : AUE_SYSCTL_NONADMIN;
+
+       default:
+               return AUE_SYSCTL;
+       }
+       /* NOTREACHED */
+}
+
 /*
  * Convert an open flags specifier into a specific type of open event for 
  * auditing purposes.
  */
-au_event_t flags_to_openevent(int oflags) {
+au_event_t flags_and_error_to_openevent(int oflags, int error) {
+       au_event_t aevent;
 
        /* Need to check only those flags we care about. */
        oflags = oflags & (O_RDONLY | O_CREAT | O_TRUNC | O_RDWR | O_WRONLY);
@@ -618,51 +697,68 @@ au_event_t flags_to_openevent(int oflags) {
        /* These checks determine what flags are on with the condition
         * that ONLY that combination is on, and no other flags are on.
         */
-       if (!(oflags ^ O_RDONLY))
-               return AUE_OPEN_R;
-       if (!(oflags ^ (O_RDONLY | O_CREAT)))
-               return AUE_OPEN_RC;
-       if (!(oflags ^ (O_RDONLY | O_CREAT | O_TRUNC)))
-               return AUE_OPEN_RTC;
-       if (!(oflags ^ (O_RDONLY | O_TRUNC)))
-               return AUE_OPEN_RT;
-       if (!(oflags ^ O_RDWR))
-               return AUE_OPEN_RW;
-       if (!(oflags ^ (O_RDWR | O_CREAT)))
-               return AUE_OPEN_RWC;
-       if (!(oflags ^ (O_RDWR | O_CREAT | O_TRUNC)))
-               return AUE_OPEN_RWTC;
-       if (!(oflags ^ (O_RDWR | O_TRUNC)))
-               return AUE_OPEN_RWT;
-       if (!(oflags ^ O_WRONLY))
-               return AUE_OPEN_W;
-       if (!(oflags ^ (O_WRONLY | O_CREAT)))
-               return AUE_OPEN_WC;
-       if (!(oflags ^ (O_WRONLY | O_CREAT | O_TRUNC)))
-               return AUE_OPEN_WTC;
-       if (!(oflags ^ (O_WRONLY | O_TRUNC)))
-               return AUE_OPEN_WT;
-
-       return AUE_OPEN_R;
+       switch (oflags) {
+       case O_RDONLY:
+               aevent = AUE_OPEN_R;
+               break;
+       case (O_RDONLY | O_CREAT):
+               aevent = AUE_OPEN_RC;
+               break;
+       case (O_RDONLY | O_CREAT | O_TRUNC):
+               aevent = AUE_OPEN_RTC;
+               break;
+       case (O_RDONLY | O_TRUNC):
+               aevent = AUE_OPEN_RT;
+               break;
+       case O_RDWR:
+               aevent = AUE_OPEN_RW;
+               break;
+       case (O_RDWR | O_CREAT):
+               aevent = AUE_OPEN_RWC;
+               break;
+       case (O_RDWR | O_CREAT | O_TRUNC):
+               aevent = AUE_OPEN_RWTC;
+               break;
+       case (O_RDWR | O_TRUNC):
+               aevent = AUE_OPEN_RWT;
+               break;
+       case O_WRONLY:
+               aevent = AUE_OPEN_W;
+               break;
+       case (O_WRONLY | O_CREAT):
+               aevent = AUE_OPEN_WC;
+               break;
+       case (O_WRONLY | O_CREAT | O_TRUNC):
+               aevent = AUE_OPEN_WTC;
+               break;
+       case (O_WRONLY | O_TRUNC):
+               aevent = AUE_OPEN_WT;
+               break;
+       default:
+               aevent = AUE_OPEN;
+               break;
 }
 
 /*
- * Fill in a vattr struct from kernel audit record fields. This function
- * would be unecessary if we store a vattr in the kernel audit record
* directly.
+        * Convert chatty errors to better matching events.
+        * Failures to find a file are really just attribute
       * events - so recast them as such.
 */
-void fill_vattr(struct vattr *v, struct vnode_au_info *vn_info)
-{
-       v->va_mode = vn_info->vn_mode;
-       v->va_uid = vn_info->vn_uid;
-       v->va_gid = vn_info->vn_gid;
-       v->va_fsid = vn_info->vn_fsid;
-       v->va_fileid = vn_info->vn_fileid;
-       v->va_rdev = vn_info->vn_dev;
+       switch (aevent) {
+       case AUE_OPEN_R:
+       case AUE_OPEN_RT:
+       case AUE_OPEN_RW:
+       case AUE_OPEN_RWT:
+       case AUE_OPEN_W:
+       case AUE_OPEN_WT:
+               if (error == ENOENT)
+                       aevent = AUE_OPEN;
+}
+       return aevent;
 }
 
 /* Convert a MSGCTL command to a specific event. */
-int msgctl_to_event(int cmd)
+au_event_t msgctl_to_event(int cmd)
 {
        switch (cmd) {
        case IPC_RMID:
@@ -678,7 +774,7 @@ int msgctl_to_event(int cmd)
 }
 
 /* Convert a SEMCTL command to a specific event. */
-int semctl_to_event(int cmd)
+au_event_t semctl_to_event(int cmd)
 {
        switch (cmd) {
        case GETALL:
@@ -707,50 +803,109 @@ int semctl_to_event(int cmd)
        }
 }
 
+/* Convert a command for the auditon() system call to a audit event. */
+int auditon_command_event(int cmd)
+{
+       switch(cmd) {
+       case A_GETPOLICY:
+               return AUE_AUDITON_GPOLICY;
+               break;
+       case A_SETPOLICY:
+               return AUE_AUDITON_SPOLICY;
+               break;
+       case A_GETKMASK:
+               return AUE_AUDITON_GETKMASK;
+               break;
+       case A_SETKMASK:
+               return AUE_AUDITON_SETKMASK;
+               break;
+       case A_GETQCTRL:
+               return AUE_AUDITON_GQCTRL;
+               break;
+       case A_SETQCTRL:
+               return AUE_AUDITON_SQCTRL;
+               break;
+       case A_GETCWD:
+               return AUE_AUDITON_GETCWD;
+               break;
+       case A_GETCAR:
+               return AUE_AUDITON_GETCAR;
+               break;
+       case A_GETSTAT:
+               return AUE_AUDITON_GETSTAT;
+               break;
+       case A_SETSTAT:
+               return AUE_AUDITON_SETSTAT;
+               break;
+       case A_SETUMASK:
+               return AUE_AUDITON_SETUMASK;
+               break;
+       case A_SETSMASK:
+               return AUE_AUDITON_SETSMASK;
+               break;
+       case A_GETCOND:
+               return AUE_AUDITON_GETCOND;
+               break;
+       case A_SETCOND:
+               return AUE_AUDITON_SETCOND;
+               break;
+       case A_GETCLASS:
+               return AUE_AUDITON_GETCLASS;
+               break;
+       case A_SETCLASS:
+               return AUE_AUDITON_SETCLASS;
+               break;
+       case A_GETPINFO:
+       case A_SETPMASK:
+       case A_SETFSIZE:
+       case A_GETFSIZE:
+       case A_GETPINFO_ADDR:
+       case A_GETKAUDIT:
+       case A_SETKAUDIT:
+       default:
+               return AUE_AUDITON;     /* No special record */
+               break;
+       }
+}
+
 /* 
- * Create a canonical path from given path by prefixing either the
- * root directory, or the current working directory.
- * If the process working directory is NULL, we could use 'rootvnode'
- * to obtain the root directoty, but this results in a volfs name
- * written to the audit log. So we will leave the filename starting
- * with '/' in the audit log in this case.
+ * Create a canonical path from given path by prefixing the supplied
+ * current working directory, which may be the root directory.
  */
-void canon_path(struct proc *p, char *path, char *cpath)
+int
+canon_path(struct vnode *cwd_vp, char *path, char *cpath)
 {
-       char *bufp;
        int len;
-       struct vnode *vnp;
-       struct filedesc *fdp;
+       int ret;
+       char *bufp = path;
 
-       fdp = p->p_fd;
-       bufp = path;
+       /*
+        * convert multiple leading '/' into a single '/' if the cwd_vp is
+        * NULL (i.e. an absolute path), and strip them entirely if the
+        * cwd_vp represents a chroot directory (i.e. the caller checked for
+        * an initial '/' character itself, saw one, and passed fdp->fd_rdir).
+        * Somewhat complicated, but it places the onus for locking structs
+        * involved on the caller, and makes proxy operations explicit rather
+        * than implicit.
+        */
        if (*(path) == '/') {
                while (*(bufp) == '/') 
                        bufp++;                 /* skip leading '/'s         */
-               /* If no process root, or it is the same as the system root,
-                * audit the path as passed in with a single '/'.
-                */
-               if ((fdp->fd_rdir == NULL) ||
-                   (fdp->fd_rdir == rootvnode)) {      
-                       vnp = NULL;
+               if (cwd_vp == NULL)
                        bufp--;                 /* restore one '/'           */
-               } else {
-                       vnp = fdp->fd_rdir;     /* use process root          */
-               }
-       } else {
-               vnp = fdp->fd_cdir;     /* prepend the current dir  */
-               bufp = path;
        }
-       if (vnp != NULL) {
+       if (cwd_vp != NULL) {
                len = MAXPATHLEN;
-               vn_getpath(vnp, cpath, &len);
-               /* The length returned by vn_getpath() is two greater than the 
-                * number of characters in the string.
-                */
+               ret = vn_getpath(cwd_vp, cpath, &len);
+               if (ret != 0) {
+                       cpath[0] = '\0';
+                       return (ret);
+               }
                if (len < MAXPATHLEN)
-                       cpath[len-2] = '/';     
-               strncpy(cpath + len-1, bufp, MAXPATHLEN - len);
+                       cpath[len-1] = '/';     
+               strlcpy(cpath + len, bufp, MAXPATHLEN - len);
        } else {
-               strncpy(cpath, bufp, MAXPATHLEN);
+               strlcpy(cpath, bufp, MAXPATHLEN);
        }
+       return (0);
 }