Date: Wed, 12 Aug 2009 14:14:21 GMT From: Ilias Marinos <marinosi@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 167246 for review Message-ID: <200908121414.n7CEEL7N000932@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=167246 Change 167246 by marinosi@marinosi_redrum on 2009/08/12 14:13:59 - Created auditon_slice_internal() function that does all the actual work for manipulating auditing. - Modified auditon(2) and auditon_slice(2) to work as wrappers to the previous function. - Tested and works (at least with the base trail). Affected files ... .. //depot/projects/soc2009/marinosi_appaudit/src/sys/security/audit/audit.c#18 edit .. //depot/projects/soc2009/marinosi_appaudit/src/sys/security/audit/audit_slice.h#14 edit .. //depot/projects/soc2009/marinosi_appaudit/src/sys/security/audit/audit_syscalls.c#11 edit Differences ... ==== //depot/projects/soc2009/marinosi_appaudit/src/sys/security/audit/audit.c#18 (text) ==== @@ -817,17 +817,8 @@ * never be the base slice as it is not a slice queue element. */ int -audit_slice_destroy(char *as_name) +audit_slice_destroy(struct audit_slice *as) { - int error; - struct audit_slice *as = NULL; - - error = audit_slice_lookup(as_name, as); - if (error) - return (1); - - if ( as == audit_base_slice ) - return (1); /* Cannot destroy base slice */ AUDIT_SLICES_LOCK(); /* @@ -946,23 +937,17 @@ /* * audit_slice_lookup() performs a linear lookup in the audit slices queue - * bases on the slice name and sets up as to point to the actual slice - * instance. - * Returns '0' on success, error code on failure. + * based on the slice name. + * Returns a ptr to the actual slice on success, NULL if slice is not found. */ -int -audit_slice_lookup(char *as_name, struct audit_slice *as) +struct audit_slice +*audit_slice_lookup(char *as_name) { - int nbytes; + struct audit_slice *cur = NULL; - nbytes = strlen(as_name); - if ( nbytes <= 0 || nbytes > AUDIT_SLICE_NAME_LEN ) - return (EINVAL); - if ( strcmp(as_name, "audit_base_slice") == 0 ) { - as = audit_base_slice; - return (0); + return (audit_base_slice); } /* @@ -972,15 +957,478 @@ AUDIT_SLICES_LOCK(); TAILQ_FOREACH(cur, &audit_slice_q, as_q) { if ( strcmp(cur->as_name, as_name) == 0 ) { - as = cur; AUDIT_SLICES_UNLOCK(); - return (0); + return (cur); } } /* * On failure.(slice not found) */ - return (1); + return (NULL); + +} + +/* + * auditon_slice_internal() performs the actual work for auditon_slice(2) and + * auditon(2) system calls. + */ +int +auditon_slice_internal(struct thread *td, int cmd, char *as_name, + void *data, u_int length) +{ + + struct audit_slice *as = NULL; + struct ucred *cred, *newcred, *oldcred; + int error; + union auditon_udata udata; + struct proc *tp; + + /* + * Find the slice we should operate on. + */ + as = audit_slice_lookup(as_name); + + /* + * The only way for 'as' to be NULL is when we want to create a new + * slice. + */ + if ((as == NULL) && (cmd != A_CREATESLICE)) + return (EINVAL); + + memset((void *)&udata, 0, sizeof(udata)); + + /* + * Some of the GET commands use the arguments too. + */ + switch (cmd) { + case A_SETPOLICY: + case A_OLDSETPOLICY: + case A_SETKMASK: + case A_SETQCTRL: + case A_OLDSETQCTRL: + case A_SETSTAT: + case A_SETUMASK: + case A_SETSMASK: + case A_SETCOND: + case A_OLDSETCOND: + case A_SETCLASS: + case A_SETPMASK: + case A_SETFSIZE: + case A_SETKAUDIT: + case A_GETCLASS: + case A_GETPINFO: + case A_GETPINFO_ADDR: + case A_SENDTRIGGER: + error = copyin(data, (void *)&udata, length); + if (error) + return (error); + AUDIT_ARG_AUDITON(&udata); + break; + } + + /* + * XXXAUDIT: Locking? + */ + switch (cmd) { + case A_OLDGETPOLICY: + case A_GETPOLICY: + if (length == sizeof(udata.au_policy64)) { + if (!as->audit_fail_stop) + udata.au_policy64 |= AUDIT_CNT; + if (as->audit_panic_on_write_fail) + udata.au_policy64 |= AUDIT_AHLT; + if (as->audit_argv) + udata.au_policy64 |= AUDIT_ARGV; + if (as->audit_arge) + udata.au_policy64 |= AUDIT_ARGE; + break; + } + if (length != sizeof(udata.au_policy)) + return (EINVAL); + if (!as->audit_fail_stop) + udata.au_policy |= AUDIT_CNT; + if (as->audit_panic_on_write_fail) + udata.au_policy |= AUDIT_AHLT; + if (as->audit_argv) + udata.au_policy |= AUDIT_ARGV; + if (as->audit_arge) + udata.au_policy |= AUDIT_ARGE; + break; + + case A_OLDSETPOLICY: + case A_SETPOLICY: + if (length == sizeof(udata.au_policy64)) { + if (udata.au_policy & (~AUDIT_CNT|AUDIT_AHLT| + AUDIT_ARGV|AUDIT_ARGE)) + return (EINVAL); + as->audit_fail_stop = ((udata.au_policy64 + & AUDIT_CNT) == 0); + as->audit_panic_on_write_fail = + (udata.au_policy64 & AUDIT_AHLT); + as->audit_argv = (udata.au_policy64 + & AUDIT_ARGV); + as->audit_arge = (udata.au_policy64 + & AUDIT_ARGE); + break; + } + if (length != sizeof(udata.au_policy)) + return (EINVAL); + if (udata.au_policy & ~(AUDIT_CNT|AUDIT_AHLT|AUDIT_ARGV| + AUDIT_ARGE)) + return (EINVAL); + /* + * XXX - Need to wake up waiters if the policy relaxes? + */ + as->audit_fail_stop = + ((udata.au_policy & AUDIT_CNT) == 0); + as->audit_panic_on_write_fail = + (udata.au_policy & AUDIT_AHLT); + as->audit_argv = + (udata.au_policy & AUDIT_ARGV); + as->audit_arge = + (udata.au_policy & AUDIT_ARGE); + break; + + case A_GETKMASK: + if (length != sizeof(udata.au_mask)) + return (EINVAL); + udata.au_mask = as->audit_nae_mask; + break; + + case A_SETKMASK: + if (length != sizeof(udata.au_mask)) + return (EINVAL); + as->audit_nae_mask = udata.au_mask; + break; + + case A_OLDGETQCTRL: + case A_GETQCTRL: + if (length == sizeof(udata.au_qctrl64)) { + udata.au_qctrl64.aq64_hiwater = + (u_int64_t)as->audit_qctrl.aq_hiwater; + udata.au_qctrl64.aq64_lowater = + (u_int64_t)as->audit_qctrl.aq_lowater; + udata.au_qctrl64.aq64_bufsz = + (u_int64_t)as->audit_qctrl.aq_bufsz; + udata.au_qctrl64.aq64_minfree = + (u_int64_t)as->audit_qctrl.aq_minfree; + break; + } + if (length != sizeof(udata.au_qctrl)) + return (EINVAL); + udata.au_qctrl = as->audit_qctrl; + break; + + case A_OLDSETQCTRL: + case A_SETQCTRL: + if (length == sizeof(udata.au_qctrl64)) { + if ((udata.au_qctrl64.aq64_hiwater > AQ_MAXHIGH) || + (udata.au_qctrl64.aq64_lowater >= + udata.au_qctrl.aq_hiwater) || + (udata.au_qctrl64.aq64_bufsz > AQ_MAXBUFSZ) || + (udata.au_qctrl64.aq64_minfree < 0) || + (udata.au_qctrl64.aq64_minfree > 100)) + return (EINVAL); + as->audit_qctrl.aq_hiwater = + (int)udata.au_qctrl64.aq64_hiwater; + as->audit_qctrl.aq_lowater = + (int)udata.au_qctrl64.aq64_lowater; + as->audit_qctrl.aq_bufsz = + (int)udata.au_qctrl64.aq64_bufsz; + as->audit_qctrl.aq_minfree = + (int)udata.au_qctrl64.aq64_minfree; + /* Not used. */ + as->audit_qctrl.aq_delay = -1; + break; + } + if (length != sizeof(udata.au_qctrl)) + return (EINVAL); + if ((udata.au_qctrl.aq_hiwater > AQ_MAXHIGH) || + (udata.au_qctrl.aq_lowater >= udata.au_qctrl.aq_hiwater) || + (udata.au_qctrl.aq_bufsz > AQ_MAXBUFSZ) || + (udata.au_qctrl.aq_minfree < 0) || + (udata.au_qctrl.aq_minfree > 100)) + return (EINVAL); + + as->audit_qctrl = udata.au_qctrl; + /* XXX The queue delay value isn't used with the kernel. */ + as->audit_qctrl.aq_delay = -1; + break; + + case A_GETCWD: + return (ENOSYS); + break; + + case A_GETCAR: + return (ENOSYS); + break; + + case A_GETSTAT: + return (ENOSYS); + break; + + case A_SETSTAT: + return (ENOSYS); + break; + + case A_SETUMASK: + return (ENOSYS); + break; + + case A_SETSMASK: + return (ENOSYS); + break; + + case A_OLDGETCOND: + case A_GETCOND: + if (length == sizeof(udata.au_cond64)) { + if (as->audit_enabled + && !as->audit_suspended) + udata.au_cond64 = AUC_AUDITING; + else + udata.au_cond64 = AUC_NOAUDIT; + break; + } + if (length != sizeof(udata.au_cond)) + return (EINVAL); + if (as->audit_enabled + && !as->audit_suspended) + udata.au_cond = AUC_AUDITING; + else + udata.au_cond = AUC_NOAUDIT; + break; + + case A_OLDSETCOND: + case A_SETCOND: + if (length == sizeof(udata.au_cond64)) { + if (udata.au_cond64 == AUC_NOAUDIT) + as->audit_suspended = 1; + if (udata.au_cond64 == AUC_AUDITING) + as->audit_suspended = 0; + if (udata.au_cond64 == AUC_DISABLED) { + as->audit_suspended = 1; + audit_shutdown(NULL, 0); + } + audit_suspended = as->audit_suspended; + break; + } + if (length != sizeof(udata.au_cond)) + return (EINVAL); + if (udata.au_cond == AUC_NOAUDIT) + as->audit_suspended = 1; + if (udata.au_cond == AUC_AUDITING) + as->audit_suspended = 0; + if (udata.au_cond == AUC_DISABLED) { + as->audit_suspended = 1; + audit_shutdown(NULL, 0); + } + audit_suspended = as->audit_suspended; + break; + + case A_GETCLASS: + if (length != sizeof(udata.au_evclass)) + return (EINVAL); + udata.au_evclass.ec_class = au_event_class( + udata.au_evclass.ec_number); + break; + + case A_SETCLASS: + if (length != sizeof(udata.au_evclass)) + return (EINVAL); + au_evclassmap_insert(udata.au_evclass.ec_number, + udata.au_evclass.ec_class); + break; + + case A_GETPINFO: + if (length != sizeof(udata.au_aupinfo)) + return (EINVAL); + if (udata.au_aupinfo.ap_pid < 1) + return (ESRCH); + if ((tp = pfind(udata.au_aupinfo.ap_pid)) == NULL) + return (ESRCH); + if ((error = p_cansee(td, tp)) != 0) { + PROC_UNLOCK(tp); + return (error); + } + cred = tp->p_ucred; + if (cred->cr_audit.ai_termid.at_type == AU_IPv6) { + PROC_UNLOCK(tp); + return (EINVAL); + } + udata.au_aupinfo.ap_auid = cred->cr_audit.ai_auid; + udata.au_aupinfo.ap_mask.am_success = + cred->cr_audit.ai_mask.am_success; + udata.au_aupinfo.ap_mask.am_failure = + cred->cr_audit.ai_mask.am_failure; + udata.au_aupinfo.ap_termid.machine = + cred->cr_audit.ai_termid.at_addr[0]; + udata.au_aupinfo.ap_termid.port = + (dev_t)cred->cr_audit.ai_termid.at_port; + udata.au_aupinfo.ap_asid = cred->cr_audit.ai_asid; + PROC_UNLOCK(tp); + break; + + case A_SETPMASK: + if (length != sizeof(udata.au_aupinfo)) + return (EINVAL); + if (udata.au_aupinfo.ap_pid < 1) + return (ESRCH); + newcred = crget(); + if ((tp = pfind(udata.au_aupinfo.ap_pid)) == NULL) { + crfree(newcred); + return (ESRCH); + } + if ((error = p_cansee(td, tp)) != 0) { + PROC_UNLOCK(tp); + crfree(newcred); + return (error); + } + oldcred = tp->p_ucred; + crcopy(newcred, oldcred); + newcred->cr_audit.ai_mask.am_success = + udata.au_aupinfo.ap_mask.am_success; + newcred->cr_audit.ai_mask.am_failure = + udata.au_aupinfo.ap_mask.am_failure; + td->td_proc->p_ucred = newcred; + PROC_UNLOCK(tp); + crfree(oldcred); + break; + + case A_SETFSIZE: + if (length != sizeof(udata.au_fstat)) + return (EINVAL); + if ((udata.au_fstat.af_filesz != 0) && + (udata.au_fstat.af_filesz < MIN_AUDIT_FILE_SIZE)) + return (EINVAL); + as->audit_fstat.af_filesz + = udata.au_fstat.af_filesz; + break; + + case A_GETFSIZE: + if (length != sizeof(udata.au_fstat)) + return (EINVAL); + udata.au_fstat.af_filesz + = as->audit_fstat.af_filesz; + udata.au_fstat.af_currsz + = as->audit_fstat.af_currsz; + break; + + case A_GETPINFO_ADDR: + if (length != sizeof(udata.au_aupinfo_addr)) + return (EINVAL); + if (udata.au_aupinfo_addr.ap_pid < 1) + return (ESRCH); + if ((tp = pfind(udata.au_aupinfo_addr.ap_pid)) == NULL) + return (ESRCH); + cred = tp->p_ucred; + udata.au_aupinfo_addr.ap_auid = cred->cr_audit.ai_auid; + udata.au_aupinfo_addr.ap_mask.am_success = + cred->cr_audit.ai_mask.am_success; + udata.au_aupinfo_addr.ap_mask.am_failure = + cred->cr_audit.ai_mask.am_failure; + udata.au_aupinfo_addr.ap_termid = cred->cr_audit.ai_termid; + udata.au_aupinfo_addr.ap_asid = cred->cr_audit.ai_asid; + PROC_UNLOCK(tp); + break; + + case A_GETKAUDIT: + if (length != sizeof(udata.au_kau_info)) + return (EINVAL); + audit_get_kinfo(&udata.au_kau_info); + break; + + case A_SETKAUDIT: + if (length != sizeof(udata.au_kau_info)) + return (EINVAL); + if (udata.au_kau_info.ai_termid.at_type != AU_IPv4 && + udata.au_kau_info.ai_termid.at_type != AU_IPv6) + return (EINVAL); + audit_set_kinfo(&udata.au_kau_info); + break; + + case A_SENDTRIGGER: + if (length != sizeof(udata.au_trigger)) + return (EINVAL); + if ((udata.au_trigger < AUDIT_TRIGGER_MIN) || + (udata.au_trigger > AUDIT_TRIGGER_MAX)) + return (EINVAL); + return (audit_send_trigger(udata.au_trigger)); + + /* + * XXXRW: as_name use a userspace character array, not a kernel space + * string pointer. We need to copyinstr() to a kernel character + * array for the purposes of looking it up, etc. + * FIXED. Note: Look at auditon_slice(2). + * + * XXXRW: Possibly audit_slice_*() should be able to return errors-- + * for example, if there's a name collision on creating slices, or i + * a slice can't be found for removal. + * FIXED. + * With the current implementation, it is not possible to reach to + * this point. An error will be returned at the start of this + * function. + */ + case A_CREATESLICE: + if (length != sizeof(udata.au_slice)) + return (EINVAL); + /* We shouldn't call this command for base slice! */ + if (as == audit_base_slice) + return (EINVAL); + /* If slice already exists return an error */ + if ( as != NULL ) + return (EEXIST); + audit_slice_create(as_name); + break; + + case A_UPDATESLICE: + if (length != sizeof(udata.au_slice)) + return (EINVAL); + return (0); + + case A_GETSLICE: + if (length != sizeof(udata.au_slice)) + return (EINVAL); + return (0); + + case A_REMOVESLICE: + if (length != sizeof(udata.au_slice)) + return (EINVAL); + /* We cannot remove base slice! */ + if (as == audit_base_slice) + return (EINVAL); + /* Destroy slice */ + audit_slice_destroy(as); + break; + + default: + return (EINVAL); + } + + /* + * Copy data back to userspace for the GET comands. + */ + switch (cmd) { + case A_GETPOLICY: + case A_OLDGETPOLICY: + case A_GETKMASK: + case A_GETQCTRL: + case A_OLDGETQCTRL: + case A_GETCWD: + case A_GETCAR: + case A_GETSTAT: + case A_GETCOND: + case A_OLDGETCOND: + case A_GETCLASS: + case A_GETPINFO: + case A_GETFSIZE: + case A_GETPINFO_ADDR: + case A_GETKAUDIT: + error = copyout((void *)&udata, data, length); + if (error) + return (error); + break; + } + return (0); } ==== //depot/projects/soc2009/marinosi_appaudit/src/sys/security/audit/audit_slice.h#14 (text+ko) ==== @@ -190,9 +190,11 @@ void audit_worker_start(struct audit_slice *as); void audit_slice_init(struct audit_slice *as, char *name); void audit_slice_create(char *name); -int audit_slice_destroy(char *as_name); +int audit_slice_destroy(struct audit_slice *as); void audit_slice_cdev_init(struct audit_slice *as); int audit_slice_commit_rec(void *rec, struct audit_slice *as); -int audit_slice_lookup(char *as_name, struct audit_slice *as); +struct audit_slice *audit_slice_lookup(char *as_name); +int auditon_slice_internal(struct thread *td, int cmd, char *as_name, void *data, + u_int length); #endif /* ! _SECURITY_AUDIT_SLICE_H_ */ ==== //depot/projects/soc2009/marinosi_appaudit/src/sys/security/audit/audit_syscalls.c#11 (text) ==== @@ -161,8 +161,31 @@ auditon(struct thread *td, struct auditon_args *uap) { - /* Dummy syscall -- to be changed */ - return (ENOSYS); + int error, ret; + + if (jailed(td->td_ucred)) + return (ENOSYS); + AUDIT_ARG_CMD(uap->cmd); + +#ifdef MAC + error = mac_system_check_auditon(td->td_ucred, uap->cmd); + if (error) + return (error); +#endif + + error = priv_check(td, PRIV_AUDIT_CONTROL); + if (error) + return (error); + + if ((uap->length <= 0) || (uap->length > sizeof(union auditon_udata))) + return (EINVAL); + + /* + * auditon(2) always selects audit_base_slice to operate on. + */ + ret = auditon_slice_internal(td, uap->cmd, "audit_base_slice", + uap->data, uap->length); + return (ret); } /* @@ -172,11 +195,8 @@ int auditon_slice(struct thread *td, struct auditon_slice_args *uap) { - struct ucred *cred, *newcred, *oldcred; - struct audit_slice *as = NULL; - int error; - union auditon_udata udata; - struct proc *tp; + + int error, ret, nbytes; char as_name[AUDIT_SLICE_NAME_LEN]; if (jailed(td->td_ucred)) @@ -198,443 +218,23 @@ return (EINVAL); /* - * Copyin the name of the slice we need to operate on. + * Check slice name. */ - error = copyinstr(uap->name, as_name, AUDIT_SLICE_NAME_LEN, NULL); - if (error) + nbytes = strlen(uap->name); + if ( nbytes <= 0 || nbytes > AUDIT_SLICE_NAME_LEN ) return (EINVAL); /* - * Find the slice we should operate on. + * Copyin the name of the slice we need to operate on. */ - error = audit_slice_lookup(as_name, as); + error = copyinstr(uap->name, as_name, AUDIT_SLICE_NAME_LEN, NULL); if (error) - return (error); - - memset((void *)&udata, 0, sizeof(udata)); - - /* - * Some of the GET commands use the arguments too. - */ - switch (uap->cmd) { - case A_SETPOLICY: - case A_OLDSETPOLICY: - case A_SETKMASK: - case A_SETQCTRL: - case A_OLDSETQCTRL: - case A_SETSTAT: - case A_SETUMASK: - case A_SETSMASK: - case A_SETCOND: - case A_OLDSETCOND: - case A_SETCLASS: - case A_SETPMASK: - case A_SETFSIZE: - case A_SETKAUDIT: - case A_GETCLASS: - case A_GETPINFO: - case A_GETPINFO_ADDR: - case A_SENDTRIGGER: - error = copyin(uap->data, (void *)&udata, uap->length); - if (error) - return (error); - AUDIT_ARG_AUDITON(&udata); - break; - } - - /* - * XXXAUDIT: Locking? - */ - switch (uap->cmd) { - case A_OLDGETPOLICY: - case A_GETPOLICY: - if (uap->length == sizeof(udata.au_policy64)) { - if (!as->audit_fail_stop) - udata.au_policy64 |= AUDIT_CNT; - if (as->audit_panic_on_write_fail) - udata.au_policy64 |= AUDIT_AHLT; - if (as->audit_argv) - udata.au_policy64 |= AUDIT_ARGV; - if (as->audit_arge) - udata.au_policy64 |= AUDIT_ARGE; - break; - } - if (uap->length != sizeof(udata.au_policy)) - return (EINVAL); - if (!as->audit_fail_stop) - udata.au_policy |= AUDIT_CNT; - if (as->audit_panic_on_write_fail) - udata.au_policy |= AUDIT_AHLT; - if (as->audit_argv) - udata.au_policy |= AUDIT_ARGV; - if (as->audit_arge) - udata.au_policy |= AUDIT_ARGE; - break; - - case A_OLDSETPOLICY: - case A_SETPOLICY: - if (uap->length == sizeof(udata.au_policy64)) { - if (udata.au_policy & (~AUDIT_CNT|AUDIT_AHLT| - AUDIT_ARGV|AUDIT_ARGE)) - return (EINVAL); - as->audit_fail_stop = ((udata.au_policy64 - & AUDIT_CNT) == 0); - as->audit_panic_on_write_fail = - (udata.au_policy64 & AUDIT_AHLT); - as->audit_argv = (udata.au_policy64 - & AUDIT_ARGV); - as->audit_arge = (udata.au_policy64 - & AUDIT_ARGE); - break; - } - if (uap->length != sizeof(udata.au_policy)) - return (EINVAL); - if (udata.au_policy & ~(AUDIT_CNT|AUDIT_AHLT|AUDIT_ARGV| - AUDIT_ARGE)) - return (EINVAL); - /* - * XXX - Need to wake up waiters if the policy relaxes? - */ - as->audit_fail_stop = - ((udata.au_policy & AUDIT_CNT) == 0); - as->audit_panic_on_write_fail = - (udata.au_policy & AUDIT_AHLT); - as->audit_argv = - (udata.au_policy & AUDIT_ARGV); - as->audit_arge = - (udata.au_policy & AUDIT_ARGE); - break; - - case A_GETKMASK: - if (uap->length != sizeof(udata.au_mask)) - return (EINVAL); - udata.au_mask = as->audit_nae_mask; - break; - - case A_SETKMASK: - if (uap->length != sizeof(udata.au_mask)) - return (EINVAL); - as->audit_nae_mask = udata.au_mask; - break; - - case A_OLDGETQCTRL: - case A_GETQCTRL: - if (uap->length == sizeof(udata.au_qctrl64)) { - udata.au_qctrl64.aq64_hiwater = - (u_int64_t)as->audit_qctrl.aq_hiwater; - udata.au_qctrl64.aq64_lowater = - (u_int64_t)as->audit_qctrl.aq_lowater; - udata.au_qctrl64.aq64_bufsz = - (u_int64_t)as->audit_qctrl.aq_bufsz; - udata.au_qctrl64.aq64_minfree = - (u_int64_t)as->audit_qctrl.aq_minfree; - break; - } - if (uap->length != sizeof(udata.au_qctrl)) - return (EINVAL); - udata.au_qctrl = as->audit_qctrl; - break; - - case A_OLDSETQCTRL: - case A_SETQCTRL: - if (uap->length == sizeof(udata.au_qctrl64)) { - if ((udata.au_qctrl64.aq64_hiwater > AQ_MAXHIGH) || - (udata.au_qctrl64.aq64_lowater >= - udata.au_qctrl.aq_hiwater) || - (udata.au_qctrl64.aq64_bufsz > AQ_MAXBUFSZ) || - (udata.au_qctrl64.aq64_minfree < 0) || - (udata.au_qctrl64.aq64_minfree > 100)) - return (EINVAL); - as->audit_qctrl.aq_hiwater = - (int)udata.au_qctrl64.aq64_hiwater; - as->audit_qctrl.aq_lowater = - (int)udata.au_qctrl64.aq64_lowater; - as->audit_qctrl.aq_bufsz = - (int)udata.au_qctrl64.aq64_bufsz; - as->audit_qctrl.aq_minfree = - (int)udata.au_qctrl64.aq64_minfree; - /* Not used. */ - as->audit_qctrl.aq_delay = -1; - break; - } - if (uap->length != sizeof(udata.au_qctrl)) - return (EINVAL); - if ((udata.au_qctrl.aq_hiwater > AQ_MAXHIGH) || - (udata.au_qctrl.aq_lowater >= udata.au_qctrl.aq_hiwater) || - (udata.au_qctrl.aq_bufsz > AQ_MAXBUFSZ) || - (udata.au_qctrl.aq_minfree < 0) || - (udata.au_qctrl.aq_minfree > 100)) - return (EINVAL); - - as->audit_qctrl = udata.au_qctrl; - /* XXX The queue delay value isn't used with the kernel. */ - as->audit_qctrl.aq_delay = -1; - break; - - case A_GETCWD: - return (ENOSYS); - break; - - case A_GETCAR: - return (ENOSYS); - break; - - case A_GETSTAT: - return (ENOSYS); - break; - - case A_SETSTAT: - return (ENOSYS); - break; - - case A_SETUMASK: - return (ENOSYS); - break; - - case A_SETSMASK: - return (ENOSYS); - break; - - case A_OLDGETCOND: - case A_GETCOND: - if (uap->length == sizeof(udata.au_cond64)) { - if (as->audit_enabled - && !as->audit_suspended) - udata.au_cond64 = AUC_AUDITING; - else - udata.au_cond64 = AUC_NOAUDIT; - break; - } - if (uap->length != sizeof(udata.au_cond)) - return (EINVAL); - if (as->audit_enabled - && !as->audit_suspended) - udata.au_cond = AUC_AUDITING; - else - udata.au_cond = AUC_NOAUDIT; - break; - - case A_OLDSETCOND: - case A_SETCOND: - if (uap->length == sizeof(udata.au_cond64)) { - if (udata.au_cond64 == AUC_NOAUDIT) - as->audit_suspended = 1; - if (udata.au_cond64 == AUC_AUDITING) - as->audit_suspended = 0; - if (udata.au_cond64 == AUC_DISABLED) { - as->audit_suspended = 1; - audit_shutdown(NULL, 0); - } - audit_suspended = as->audit_suspended; - break; - } - if (uap->length != sizeof(udata.au_cond)) - return (EINVAL); - if (udata.au_cond == AUC_NOAUDIT) - as->audit_suspended = 1; - if (udata.au_cond == AUC_AUDITING) - as->audit_suspended = 0; - if (udata.au_cond == AUC_DISABLED) { - as->audit_suspended = 1; - audit_shutdown(NULL, 0); - } - audit_suspended = as->audit_suspended; - break; - - case A_GETCLASS: - if (uap->length != sizeof(udata.au_evclass)) - return (EINVAL); - udata.au_evclass.ec_class = au_event_class( - udata.au_evclass.ec_number); - break; - - case A_SETCLASS: - if (uap->length != sizeof(udata.au_evclass)) - return (EINVAL); - au_evclassmap_insert(udata.au_evclass.ec_number, - udata.au_evclass.ec_class); - break; - - case A_GETPINFO: - if (uap->length != sizeof(udata.au_aupinfo)) - return (EINVAL); - if (udata.au_aupinfo.ap_pid < 1) - return (ESRCH); - if ((tp = pfind(udata.au_aupinfo.ap_pid)) == NULL) - return (ESRCH); - if ((error = p_cansee(td, tp)) != 0) { - PROC_UNLOCK(tp); - return (error); - } - cred = tp->p_ucred; - if (cred->cr_audit.ai_termid.at_type == AU_IPv6) { - PROC_UNLOCK(tp); - return (EINVAL); - } - udata.au_aupinfo.ap_auid = cred->cr_audit.ai_auid; - udata.au_aupinfo.ap_mask.am_success = - cred->cr_audit.ai_mask.am_success; - udata.au_aupinfo.ap_mask.am_failure = - cred->cr_audit.ai_mask.am_failure; - udata.au_aupinfo.ap_termid.machine = - cred->cr_audit.ai_termid.at_addr[0]; - udata.au_aupinfo.ap_termid.port = - (dev_t)cred->cr_audit.ai_termid.at_port; - udata.au_aupinfo.ap_asid = cred->cr_audit.ai_asid; - PROC_UNLOCK(tp); - break; - - case A_SETPMASK: - if (uap->length != sizeof(udata.au_aupinfo)) - return (EINVAL); - if (udata.au_aupinfo.ap_pid < 1) - return (ESRCH); - newcred = crget(); - if ((tp = pfind(udata.au_aupinfo.ap_pid)) == NULL) { - crfree(newcred); - return (ESRCH); - } - if ((error = p_cansee(td, tp)) != 0) { - PROC_UNLOCK(tp); - crfree(newcred); - return (error); - } - oldcred = tp->p_ucred; - crcopy(newcred, oldcred); - newcred->cr_audit.ai_mask.am_success = - udata.au_aupinfo.ap_mask.am_success; - newcred->cr_audit.ai_mask.am_failure = - udata.au_aupinfo.ap_mask.am_failure; - td->td_proc->p_ucred = newcred; - PROC_UNLOCK(tp); - crfree(oldcred); - break; - - case A_SETFSIZE: - if (uap->length != sizeof(udata.au_fstat)) - return (EINVAL); - if ((udata.au_fstat.af_filesz != 0) && - (udata.au_fstat.af_filesz < MIN_AUDIT_FILE_SIZE)) - return (EINVAL); - as->audit_fstat.af_filesz - = udata.au_fstat.af_filesz; - break; - - case A_GETFSIZE: - if (uap->length != sizeof(udata.au_fstat)) - return (EINVAL); - udata.au_fstat.af_filesz - = as->audit_fstat.af_filesz; - udata.au_fstat.af_currsz - = as->audit_fstat.af_currsz; - break; - - case A_GETPINFO_ADDR: - if (uap->length != sizeof(udata.au_aupinfo_addr)) - return (EINVAL); - if (udata.au_aupinfo_addr.ap_pid < 1) - return (ESRCH); - if ((tp = pfind(udata.au_aupinfo_addr.ap_pid)) == NULL) - return (ESRCH); - cred = tp->p_ucred; - udata.au_aupinfo_addr.ap_auid = cred->cr_audit.ai_auid; - udata.au_aupinfo_addr.ap_mask.am_success = - cred->cr_audit.ai_mask.am_success; - udata.au_aupinfo_addr.ap_mask.am_failure = - cred->cr_audit.ai_mask.am_failure; - udata.au_aupinfo_addr.ap_termid = cred->cr_audit.ai_termid; - udata.au_aupinfo_addr.ap_asid = cred->cr_audit.ai_asid; - PROC_UNLOCK(tp); - break; - - case A_GETKAUDIT: - if (uap->length != sizeof(udata.au_kau_info)) - return (EINVAL); - audit_get_kinfo(&udata.au_kau_info); - break; - - case A_SETKAUDIT: - if (uap->length != sizeof(udata.au_kau_info)) - return (EINVAL); - if (udata.au_kau_info.ai_termid.at_type != AU_IPv4 && - udata.au_kau_info.ai_termid.at_type != AU_IPv6) - return (EINVAL); - audit_set_kinfo(&udata.au_kau_info); - break; - - case A_SENDTRIGGER: - if (uap->length != sizeof(udata.au_trigger)) - return (EINVAL); - if ((udata.au_trigger < AUDIT_TRIGGER_MIN) || - (udata.au_trigger > AUDIT_TRIGGER_MAX)) - return (EINVAL); - return (audit_send_trigger(udata.au_trigger)); - - /* - * XXXRW: as_name use a userspace character array, not a kernel space >>> TRUNCATED FOR MAIL (1000 lines) <<<
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200908121414.n7CEEL7N000932>