Skip site navigation (1)Skip section navigation (2)
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>