/*
- * 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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
AUE_LSTAT, /* 190 = lstat */
AUE_PATHCONF, /* 191 = pathconf */
AUE_FPATHCONF, /* 192 = fpathconf */
-
#if COMPAT_GETFSSTAT
AUE_GETFSSTAT, /* 193 = getfsstat */
#else
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*/
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 */
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 */
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 */
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 */
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);
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);
/* 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:
}
/* 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:
}
}
+/* 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);
}