Date: Mon, 17 Oct 2005 08:27:49 GMT From: Robert Watson <rwatson@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 85419 for review Message-ID: <200510170827.j9H8RnOS039069@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=85419 Change 85419 by rwatson@rwatson_peppercorn on 2005/10/17 08:27:38 Lock down the event->class mapping table using a mutex. Staticize the table and mutex. Further annotate functions. This code may well now be safe on SMP. Cleanups -- style, remove unused code, whitespace, etc. Assert copyright. Affected files ... .. //depot/projects/trustedbsd/audit3/sys/security/audit/kern_bsm_klib.c#15 edit Differences ... ==== //depot/projects/trustedbsd/audit3/sys/security/audit/kern_bsm_klib.c#15 (text+ko) ==== @@ -1,5 +1,7 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2004 Apple Computer, Inc. + * Copyright (c) 2005 Robert N. M. Watson + * All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -41,10 +43,7 @@ /* * Hash table functions for the audit event number to event class mask * mapping. - * - * XXXAUDIT: Locking? */ - #define EVCLASSMAP_HASH_TABLE_SIZE 251 struct evclass_elem { au_event_t event; @@ -55,22 +54,31 @@ LIST_HEAD(, evclass_elem) head; }; -struct evclass_list evclass_hash[EVCLASSMAP_HASH_TABLE_SIZE]; +static struct mtx evclass_mtx; +static struct evclass_list evclass_hash[EVCLASSMAP_HASH_TABLE_SIZE]; -au_class_t au_event_class(au_event_t event) +/* + * Look up the class for an audit event in the class mapping table. + */ +au_class_t +au_event_class(au_event_t event) { - struct evclass_list *evcl; struct evclass_elem *evc; + au_class_t class; + mtx_lock(&evclass_mtx); evcl = &evclass_hash[event % EVCLASSMAP_HASH_TABLE_SIZE]; - - /* If an entry at our hash location matches the event, just return */ + class = AU_NULL; LIST_FOREACH(evc, &evcl->head, entry) { - if (evc->event == event) - return (evc->class); + if (evc->event == event) { + class = evc->class; + goto out; + } } - return (AU_NULL); +out: + mtx_unlock(&evclass_mtx); + return (class); } /* @@ -79,71 +87,83 @@ * 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. */ -void au_evclassmap_insert(au_event_t event, au_class_t class) +void +au_evclassmap_insert(au_event_t event, au_class_t class) { struct evclass_list *evcl; - struct evclass_elem *evc; + struct evclass_elem *evc, *evc_new; + + /* + * Pessimistically, always allocate storage before acquiring mutex. + * Free if there is already a mapping for this event. + */ + evc_new = malloc(sizeof(*evc), M_AUDIT, M_WAITOK); + mtx_lock(&evclass_mtx); evcl = &evclass_hash[event % EVCLASSMAP_HASH_TABLE_SIZE]; - LIST_FOREACH(evc, &evcl->head, entry) { if (evc->event == event) { evc->class = class; + mtx_unlock(&evclass_mtx); + free(evc_new, M_AUDIT); return; } } - evc = malloc(sizeof(*evc), M_AUDIT, M_WAITOK); - if (evc == NULL) { - return; - } + evc = evc_new; evc->event = event; evc->class = class; LIST_INSERT_HEAD(&evcl->head, evc, entry); - + mtx_unlock(&evclass_mtx); } -void au_evclassmap_init(void) +void +au_evclassmap_init(void) { int i; - for (i = 0; i < EVCLASSMAP_HASH_TABLE_SIZE; i++) { + + mtx_init(&evclass_mtx, "evclass_mtx", NULL, MTX_DEF); + 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. */ + /* + * Set up the initial event to class mapping for system calls. + * + * XXXRW: Really, this should walk all possible audit events, not all + * native ABI system calls, as there may be audit events reachable + * only through non-native system calls. It also seems a shame to + * frob the mutex this early. + */ for (i = 0; i < SYS_MAXSYSCALL; i++) { - if (sysent[i].sy_auevent != AUE_NULL) { + if (sysent[i].sy_auevent != AUE_NULL) au_evclassmap_insert(sysent[i].sy_auevent, AU_NULL); - } } - } /* * 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) +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) + if (mask_p == NULL) return (-1); ae_class = au_event_class(event); + /* * Perform the actual check of the masks against the event. */ - if(sorf & AU_PRS_SUCCESS) { + if (sorf & AU_PRS_SUCCESS) effmask |= (mask_p->am_success & ae_class); - } - if(sorf & AU_PRS_FAILURE) { + if (sorf & AU_PRS_FAILURE) effmask |= (mask_p->am_failure & ae_class); - } - if(effmask) + if (effmask) return (1); else return (0); @@ -152,12 +172,14 @@ /* * Convert sysctl names and present arguments to events */ -au_event_t ctlname_to_sysctlevent(int name[], uint64_t valid_arg) { +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; + return (AUE_SYSCTL); switch (name[0]) { /* non-admin "lookups" treat them special */ @@ -174,7 +196,7 @@ case KERN_SAVED_IDS: case KERN_OSRELDATE: case KERN_DUMMY: - return AUE_SYSCTL_NONADMIN; + return (AUE_SYSCTL_NONADMIN); /* only treat the changeable controls as admin */ case KERN_MAXVNODES: @@ -185,26 +207,26 @@ case KERN_HOSTID: case KERN_SECURELVL: case KERN_HOSTNAME: -case KERN_VNODE: -case KERN_PROC: -case KERN_FILE: -case KERN_PROF: -case KERN_NISDOMAINNAME: -case KERN_UPDATEINTERVAL: -case KERN_NTP_PLL: + case KERN_VNODE: + case KERN_PROC: + case KERN_FILE: + case KERN_PROF: + case KERN_NISDOMAINNAME: + case KERN_UPDATEINTERVAL: + case KERN_NTP_PLL: case KERN_BOOTFILE: case KERN_DUMPDEV: -case KERN_IPC: -case KERN_PS_STRINGS: -case KERN_USRSTACK: + case KERN_IPC: + case KERN_PS_STRINGS: + case KERN_USRSTACK: case KERN_LOGSIGEXIT: -case KERN_IOV_MAX: -case KERN_MAXID: - return (valid_arg & ARG_VALUE) ? - AUE_SYSCTL : AUE_SYSCTL_NONADMIN; + case KERN_IOV_MAX: + case KERN_MAXID: + return ((valid_arg & ARG_VALUE) ? + AUE_SYSCTL : AUE_SYSCTL_NONADMIN); default: - return AUE_SYSCTL; + return (AUE_SYSCTL); } /* NOTREACHED */ } @@ -213,52 +235,66 @@ * Convert an open flags specifier into a specific type of open event for * auditing purposes. */ -au_event_t flags_and_error_to_openevent(int oflags, int error) { +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. + /* + * These checks determine what flags are on with the condition that + * ONLY that combination is on, and no other flags are on. */ 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; @@ -279,107 +315,132 @@ if (error == ENOENT) aevent = AUE_OPEN; } - return aevent; + return (aevent); } -/* Convert a MSGCTL command to a specific event. */ -int msgctl_to_event(int cmd) +/* + * Convert a MSGCTL command to a specific event. + */ +int +msgctl_to_event(int cmd) { + switch (cmd) { case IPC_RMID: - return AUE_MSGCTL_RMID; + return (AUE_MSGCTL_RMID); + case IPC_SET: - return AUE_MSGCTL_SET; + return (AUE_MSGCTL_SET); + case IPC_STAT: - return AUE_MSGCTL_STAT; + return (AUE_MSGCTL_STAT); + default: - return AUE_MSGCTL; - /* We will audit a bad command */ + /* We will audit a bad command */ + return (AUE_MSGCTL); } } -/* Convert a SEMCTL command to a specific event. */ -int semctl_to_event(int cmd) +/* + * Convert a SEMCTL command to a specific event. + */ +int +semctl_to_event(int cmd) { + switch (cmd) { case GETALL: - return AUE_SEMCTL_GETALL; + return (AUE_SEMCTL_GETALL); + case GETNCNT: - return AUE_SEMCTL_GETNCNT; + return (AUE_SEMCTL_GETNCNT); + case GETPID: - return AUE_SEMCTL_GETPID; + return (AUE_SEMCTL_GETPID); + case GETVAL: - return AUE_SEMCTL_GETVAL; + return (AUE_SEMCTL_GETVAL); + case GETZCNT: - return AUE_SEMCTL_GETZCNT; + return (AUE_SEMCTL_GETZCNT); + case IPC_RMID: - return AUE_SEMCTL_RMID; + return (AUE_SEMCTL_RMID); + case IPC_SET: - return AUE_SEMCTL_SET; + return (AUE_SEMCTL_SET); + case SETALL: - return AUE_SEMCTL_SETALL; + return (AUE_SEMCTL_SETALL); + case SETVAL: - return AUE_SEMCTL_SETVAL; + return (AUE_SEMCTL_SETVAL); + case IPC_STAT: - return AUE_SEMCTL_STAT; + return (AUE_SEMCTL_STAT); + default: - return AUE_SEMCTL; - /* We will audit a bad command */ + /* We will audit a bad command */ + return (AUE_SEMCTL); } } -/* Convert a command for the auditon() system call to a audit event. */ -int auditon_command_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; + return (AUE_AUDITON_GPOLICY); + case A_SETPOLICY: - return AUE_AUDITON_SPOLICY; - break; + return (AUE_AUDITON_SPOLICY); + case A_GETKMASK: - return AUE_AUDITON_GETKMASK; - break; + return (AUE_AUDITON_GETKMASK); + case A_SETKMASK: - return AUE_AUDITON_SETKMASK; - break; + return (AUE_AUDITON_SETKMASK); + case A_GETQCTRL: - return AUE_AUDITON_GQCTRL; - break; + return (AUE_AUDITON_GQCTRL); + case A_SETQCTRL: - return AUE_AUDITON_SQCTRL; - break; + return (AUE_AUDITON_SQCTRL); + case A_GETCWD: - return AUE_AUDITON_GETCWD; - break; + return (AUE_AUDITON_GETCWD); + case A_GETCAR: - return AUE_AUDITON_GETCAR; - break; + return (AUE_AUDITON_GETCAR); + case A_GETSTAT: - return AUE_AUDITON_GETSTAT; - break; + return (AUE_AUDITON_GETSTAT); + case A_SETSTAT: - return AUE_AUDITON_SETSTAT; - break; + return (AUE_AUDITON_SETSTAT); + case A_SETUMASK: - return AUE_AUDITON_SETUMASK; - break; + return (AUE_AUDITON_SETUMASK); + case A_SETSMASK: - return AUE_AUDITON_SETSMASK; - break; + return (AUE_AUDITON_SETSMASK); + case A_GETCOND: - return AUE_AUDITON_GETCOND; - break; + return (AUE_AUDITON_GETCOND); + case A_SETCOND: - return AUE_AUDITON_SETCOND; - break; + return (AUE_AUDITON_SETCOND); + case A_GETCLASS: - return AUE_AUDITON_GETCLASS; - break; + return (AUE_AUDITON_GETCLASS); + case A_SETCLASS: - return AUE_AUDITON_SETCLASS; - break; + return (AUE_AUDITON_SETCLASS); + case A_GETPINFO: case A_SETPMASK: case A_SETFSIZE: @@ -388,8 +449,7 @@ case A_GETKAUDIT: case A_SETKAUDIT: default: - return AUE_AUDITON; /* No special record */ - break; + return (AUE_AUDITON); /* No special record */ } } @@ -407,12 +467,8 @@ void canon_path(struct thread *td, char *path, char *cpath) { - char *bufp; char *retbuf, *freebuf; -#if 0 - int len; -#endif struct vnode *vnp; struct filedesc *fdp; int error, vfslocked;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200510170827.j9H8RnOS039069>