xref: /freebsd/sys/security/audit/audit_syscalls.c (revision fdafd315ad0d0f28a11b9fb4476a9ab059c62b92)
1f6d4a8a7SRobert Watson /*-
251369649SPedro F. Giffuni  * SPDX-License-Identifier: BSD-3-Clause
351369649SPedro F. Giffuni  *
44df4e335SRobert Watson  * Copyright (c) 1999-2009 Apple Inc.
52ddefb6dSRobert Watson  * Copyright (c) 2016, 2018 Robert N. M. Watson
6718c8510SRobert Watson  * All rights reserved.
7718c8510SRobert Watson  *
8759c8caaSRobert Watson  * Portions of this software were developed by BAE Systems, the University of
9759c8caaSRobert Watson  * Cambridge Computer Laboratory, and Memorial University under DARPA/AFRL
10759c8caaSRobert Watson  * contract FA8650-15-C-7558 ("CADETS"), as part of the DARPA Transparent
11759c8caaSRobert Watson  * Computing (TC) research program.
12759c8caaSRobert Watson  *
13718c8510SRobert Watson  * Redistribution and use in source and binary forms, with or without
14718c8510SRobert Watson  * modification, are permitted provided that the following conditions
15718c8510SRobert Watson  * are met:
16718c8510SRobert Watson  * 1.  Redistributions of source code must retain the above copyright
17718c8510SRobert Watson  *     notice, this list of conditions and the following disclaimer.
18718c8510SRobert Watson  * 2.  Redistributions in binary form must reproduce the above copyright
19718c8510SRobert Watson  *     notice, this list of conditions and the following disclaimer in the
20718c8510SRobert Watson  *     documentation and/or other materials provided with the distribution.
21bc9a43d6SRobert Watson  * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
22718c8510SRobert Watson  *     its contributors may be used to endorse or promote products derived
23718c8510SRobert Watson  *     from this software without specific prior written permission.
24718c8510SRobert Watson  *
25718c8510SRobert Watson  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND
26718c8510SRobert Watson  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27718c8510SRobert Watson  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28718c8510SRobert Watson  * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR
29718c8510SRobert Watson  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30718c8510SRobert Watson  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31718c8510SRobert Watson  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32718c8510SRobert Watson  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
33718c8510SRobert Watson  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
34718c8510SRobert Watson  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35718c8510SRobert Watson  * POSSIBILITY OF SUCH DAMAGE.
36718c8510SRobert Watson  */
37718c8510SRobert Watson 
38718c8510SRobert Watson #include <sys/param.h>
39714e68b8SRobert Watson #include <sys/mount.h>
40718c8510SRobert Watson #include <sys/namei.h>
41acd3428bSRobert Watson #include <sys/priv.h>
42718c8510SRobert Watson #include <sys/proc.h>
43718c8510SRobert Watson #include <sys/sysproto.h>
44718c8510SRobert Watson #include <sys/systm.h>
45718c8510SRobert Watson #include <sys/vnode.h>
4606399e90SChristian S.J. Peron #include <sys/jail.h>
47718c8510SRobert Watson 
48718c8510SRobert Watson #include <bsm/audit.h>
49718c8510SRobert Watson #include <bsm/audit_kevents.h>
5018717f69SRobert Watson 
51718c8510SRobert Watson #include <security/audit/audit.h>
52718c8510SRobert Watson #include <security/audit/audit_private.h>
5318717f69SRobert Watson #include <security/mac/mac_framework.h>
54718c8510SRobert Watson 
55718c8510SRobert Watson #ifdef AUDIT
56718c8510SRobert Watson 
57718c8510SRobert Watson /*
58871499feSRobert Watson  * System call to allow a user space application to submit a BSM audit record
59871499feSRobert Watson  * to the kernel for inclusion in the audit log.  This function does little
60871499feSRobert Watson  * verification on the audit record that is submitted.
61718c8510SRobert Watson  *
62871499feSRobert Watson  * XXXAUDIT: Audit preselection for user records does not currently work,
63871499feSRobert Watson  * since we pre-select only based on the AUE_audit event type, not the event
64871499feSRobert Watson  * type submitted as part of the user audit data.
65718c8510SRobert Watson  */
66718c8510SRobert Watson /* ARGSUSED */
67718c8510SRobert Watson int
sys_audit(struct thread * td,struct audit_args * uap)688451d0ddSKip Macy sys_audit(struct thread *td, struct audit_args *uap)
69718c8510SRobert Watson {
70718c8510SRobert Watson 	int error;
71718c8510SRobert Watson 	void * rec;
72718c8510SRobert Watson 	struct kaudit_record *ar;
73718c8510SRobert Watson 
7406399e90SChristian S.J. Peron 	if (jailed(td->td_ucred))
7506399e90SChristian S.J. Peron 		return (ENOSYS);
76acd3428bSRobert Watson 	error = priv_check(td, PRIV_AUDIT_SUBMIT);
77718c8510SRobert Watson 	if (error)
78718c8510SRobert Watson 		return (error);
79718c8510SRobert Watson 
80718c8510SRobert Watson 	if ((uap->length <= 0) || (uap->length > audit_qctrl.aq_bufsz))
81718c8510SRobert Watson 		return (EINVAL);
82718c8510SRobert Watson 
83718c8510SRobert Watson 	ar = currecord();
84718c8510SRobert Watson 
85871499feSRobert Watson 	/*
86871499feSRobert Watson 	 * If there's no current audit record (audit() itself not audited)
87718c8510SRobert Watson 	 * commit the user audit record.
88718c8510SRobert Watson 	 */
89718c8510SRobert Watson 	if (ar == NULL) {
90871499feSRobert Watson 		/*
91871499feSRobert Watson 		 * This is not very efficient; we're required to allocate a
92871499feSRobert Watson 		 * complete kernel audit record just so the user record can
93871499feSRobert Watson 		 * tag along.
94718c8510SRobert Watson 		 *
95718c8510SRobert Watson 		 * XXXAUDIT: Maybe AUE_AUDIT in the system call context and
96718c8510SRobert Watson 		 * special pre-select handling?
97718c8510SRobert Watson 		 */
98718c8510SRobert Watson 		td->td_ar = audit_new(AUE_NULL, td);
99718c8510SRobert Watson 		if (td->td_ar == NULL)
100718c8510SRobert Watson 			return (ENOTSUP);
101b3f468e2SRobert Watson 		td->td_pflags |= TDP_AUDITREC;
102718c8510SRobert Watson 		ar = td->td_ar;
103718c8510SRobert Watson 	}
104718c8510SRobert Watson 
105718c8510SRobert Watson 	if (uap->length > MAX_AUDIT_RECORD_SIZE)
106718c8510SRobert Watson 		return (EINVAL);
107718c8510SRobert Watson 
108718c8510SRobert Watson 	rec = malloc(uap->length, M_AUDITDATA, M_WAITOK);
109718c8510SRobert Watson 
110718c8510SRobert Watson 	error = copyin(uap->record, rec, uap->length);
111718c8510SRobert Watson 	if (error)
112718c8510SRobert Watson 		goto free_out;
113718c8510SRobert Watson 
114871499feSRobert Watson 	/* Verify the record. */
115718c8510SRobert Watson 	if (bsm_rec_verify(rec) == 0) {
116718c8510SRobert Watson 		error = EINVAL;
117718c8510SRobert Watson 		goto free_out;
118718c8510SRobert Watson 	}
119718c8510SRobert Watson 
12018717f69SRobert Watson #ifdef MAC
12130d239bcSRobert Watson 	error = mac_system_check_audit(td->td_ucred, rec, uap->length);
12218717f69SRobert Watson 	if (error)
12318717f69SRobert Watson 		goto free_out;
12418717f69SRobert Watson #endif
12518717f69SRobert Watson 
126871499feSRobert Watson 	/*
127871499feSRobert Watson 	 * Attach the user audit record to the kernel audit record.  Because
128718c8510SRobert Watson 	 * this system call is an auditable event, we will write the user
129718c8510SRobert Watson 	 * record along with the record for this audit event.
130718c8510SRobert Watson 	 *
131718c8510SRobert Watson 	 * XXXAUDIT: KASSERT appropriate starting values of k_udata, k_ulen,
132718c8510SRobert Watson 	 * k_ar_commit & AR_COMMIT_USER?
133718c8510SRobert Watson 	 */
134718c8510SRobert Watson 	ar->k_udata = rec;
135718c8510SRobert Watson 	ar->k_ulen  = uap->length;
136718c8510SRobert Watson 	ar->k_ar_commit |= AR_COMMIT_USER;
137f07b8369SChristian S.J. Peron 
138f07b8369SChristian S.J. Peron 	/*
139f07b8369SChristian S.J. Peron 	 * Currently we assume that all preselection has been performed in
140f07b8369SChristian S.J. Peron 	 * userspace.  We unconditionally set these masks so that the records
141f07b8369SChristian S.J. Peron 	 * get committed both to the trail and pipe.  In the future we will
142f07b8369SChristian S.J. Peron 	 * want to setup kernel based preselection.
143f07b8369SChristian S.J. Peron 	 */
144f07b8369SChristian S.J. Peron 	ar->k_ar_commit |= (AR_PRESELECT_USER_TRAIL | AR_PRESELECT_USER_PIPE);
145718c8510SRobert Watson 	return (0);
146718c8510SRobert Watson 
147718c8510SRobert Watson free_out:
148871499feSRobert Watson 	/*
149871499feSRobert Watson 	 * audit_syscall_exit() will free the audit record on the thread even
150871499feSRobert Watson 	 * if we allocated it above.
151718c8510SRobert Watson 	 */
152718c8510SRobert Watson 	free(rec, M_AUDITDATA);
153718c8510SRobert Watson 	return (error);
154718c8510SRobert Watson }
155718c8510SRobert Watson 
156718c8510SRobert Watson /*
157718c8510SRobert Watson  *  System call to manipulate auditing.
158718c8510SRobert Watson  */
159718c8510SRobert Watson /* ARGSUSED */
160718c8510SRobert Watson int
sys_auditon(struct thread * td,struct auditon_args * uap)1618451d0ddSKip Macy sys_auditon(struct thread *td, struct auditon_args *uap)
162718c8510SRobert Watson {
163e6870c95SRobert Watson 	struct ucred *cred, *newcred, *oldcred;
164718c8510SRobert Watson 	int error;
165718c8510SRobert Watson 	union auditon_udata udata;
166718c8510SRobert Watson 	struct proc *tp;
167718c8510SRobert Watson 
16806399e90SChristian S.J. Peron 	if (jailed(td->td_ucred))
16906399e90SChristian S.J. Peron 		return (ENOSYS);
17014961ba7SRobert Watson 	AUDIT_ARG_CMD(uap->cmd);
17118717f69SRobert Watson 
17218717f69SRobert Watson #ifdef MAC
17330d239bcSRobert Watson 	error = mac_system_check_auditon(td->td_ucred, uap->cmd);
17418717f69SRobert Watson 	if (error)
17518717f69SRobert Watson 		return (error);
17618717f69SRobert Watson #endif
17718717f69SRobert Watson 
178acd3428bSRobert Watson 	error = priv_check(td, PRIV_AUDIT_CONTROL);
179718c8510SRobert Watson 	if (error)
180718c8510SRobert Watson 		return (error);
181718c8510SRobert Watson 
182718c8510SRobert Watson 	if ((uap->length <= 0) || (uap->length > sizeof(union auditon_udata)))
183718c8510SRobert Watson 		return (EINVAL);
184718c8510SRobert Watson 
185718c8510SRobert Watson 	memset((void *)&udata, 0, sizeof(udata));
186718c8510SRobert Watson 
187871499feSRobert Watson 	/*
188871499feSRobert Watson 	 * Some of the GET commands use the arguments too.
189871499feSRobert Watson 	 */
190718c8510SRobert Watson 	switch (uap->cmd) {
191718c8510SRobert Watson 	case A_SETPOLICY:
1924df4e335SRobert Watson 	case A_OLDSETPOLICY:
193718c8510SRobert Watson 	case A_SETKMASK:
194718c8510SRobert Watson 	case A_SETQCTRL:
1954df4e335SRobert Watson 	case A_OLDSETQCTRL:
196718c8510SRobert Watson 	case A_SETSTAT:
197718c8510SRobert Watson 	case A_SETUMASK:
198718c8510SRobert Watson 	case A_SETSMASK:
199718c8510SRobert Watson 	case A_SETCOND:
2004df4e335SRobert Watson 	case A_OLDSETCOND:
201718c8510SRobert Watson 	case A_SETCLASS:
202759c8caaSRobert Watson 	case A_SETEVENT:
203718c8510SRobert Watson 	case A_SETPMASK:
204718c8510SRobert Watson 	case A_SETFSIZE:
205718c8510SRobert Watson 	case A_SETKAUDIT:
206718c8510SRobert Watson 	case A_GETCLASS:
207759c8caaSRobert Watson 	case A_GETEVENT:
208718c8510SRobert Watson 	case A_GETPINFO:
209718c8510SRobert Watson 	case A_GETPINFO_ADDR:
210718c8510SRobert Watson 	case A_SENDTRIGGER:
211718c8510SRobert Watson 		error = copyin(uap->data, (void *)&udata, uap->length);
212718c8510SRobert Watson 		if (error)
213718c8510SRobert Watson 			return (error);
21414961ba7SRobert Watson 		AUDIT_ARG_AUDITON(&udata);
215718c8510SRobert Watson 		break;
216718c8510SRobert Watson 	}
217718c8510SRobert Watson 
218871499feSRobert Watson 	/*
219718c8510SRobert Watson 	 * XXXAUDIT: Locking?
220718c8510SRobert Watson 	 */
221718c8510SRobert Watson 	switch (uap->cmd) {
2224df4e335SRobert Watson 	case A_OLDGETPOLICY:
2232a5058a3SRobert Watson 	case A_GETPOLICY:
2244df4e335SRobert Watson 		if (uap->length == sizeof(udata.au_policy64)) {
2254df4e335SRobert Watson 			if (!audit_fail_stop)
2264df4e335SRobert Watson 				udata.au_policy64 |= AUDIT_CNT;
2274df4e335SRobert Watson 			if (audit_panic_on_write_fail)
2284df4e335SRobert Watson 				udata.au_policy64 |= AUDIT_AHLT;
2294df4e335SRobert Watson 			if (audit_argv)
2304df4e335SRobert Watson 				udata.au_policy64 |= AUDIT_ARGV;
2314df4e335SRobert Watson 			if (audit_arge)
2324df4e335SRobert Watson 				udata.au_policy64 |= AUDIT_ARGE;
2334df4e335SRobert Watson 			break;
2344df4e335SRobert Watson 		}
2354df4e335SRobert Watson 		if (uap->length != sizeof(udata.au_policy))
2364df4e335SRobert Watson 			return (EINVAL);
237718c8510SRobert Watson 		if (!audit_fail_stop)
238718c8510SRobert Watson 			udata.au_policy |= AUDIT_CNT;
239718c8510SRobert Watson 		if (audit_panic_on_write_fail)
240718c8510SRobert Watson 			udata.au_policy |= AUDIT_AHLT;
241ae1078d6SWayne Salamon 		if (audit_argv)
242ae1078d6SWayne Salamon 			udata.au_policy |= AUDIT_ARGV;
243ae1078d6SWayne Salamon 		if (audit_arge)
244ae1078d6SWayne Salamon 			udata.au_policy |= AUDIT_ARGE;
245718c8510SRobert Watson 		break;
246718c8510SRobert Watson 
2474df4e335SRobert Watson 	case A_OLDSETPOLICY:
2482a5058a3SRobert Watson 	case A_SETPOLICY:
2494df4e335SRobert Watson 		if (uap->length == sizeof(udata.au_policy64)) {
250f7c188aeSAlan Somers 			if (udata.au_policy & ~(AUDIT_CNT|AUDIT_AHLT|
2514df4e335SRobert Watson 			    AUDIT_ARGV|AUDIT_ARGE))
2524df4e335SRobert Watson 				return (EINVAL);
2534df4e335SRobert Watson 			audit_fail_stop = ((udata.au_policy64 & AUDIT_CNT) ==
2544df4e335SRobert Watson 			    0);
2554df4e335SRobert Watson 			audit_panic_on_write_fail = (udata.au_policy64 &
2564df4e335SRobert Watson 			    AUDIT_AHLT);
2574df4e335SRobert Watson 			audit_argv = (udata.au_policy64 & AUDIT_ARGV);
2584df4e335SRobert Watson 			audit_arge = (udata.au_policy64 & AUDIT_ARGE);
2594df4e335SRobert Watson 			break;
2604df4e335SRobert Watson 		}
2614df4e335SRobert Watson 		if (uap->length != sizeof(udata.au_policy))
2624df4e335SRobert Watson 			return (EINVAL);
263ae1078d6SWayne Salamon 		if (udata.au_policy & ~(AUDIT_CNT|AUDIT_AHLT|AUDIT_ARGV|
264ae1078d6SWayne Salamon 		    AUDIT_ARGE))
265718c8510SRobert Watson 			return (EINVAL);
266718c8510SRobert Watson 		/*
267718c8510SRobert Watson 		 * XXX - Need to wake up waiters if the policy relaxes?
268718c8510SRobert Watson 		 */
269718c8510SRobert Watson 		audit_fail_stop = ((udata.au_policy & AUDIT_CNT) == 0);
270718c8510SRobert Watson 		audit_panic_on_write_fail = (udata.au_policy & AUDIT_AHLT);
271ae1078d6SWayne Salamon 		audit_argv = (udata.au_policy & AUDIT_ARGV);
272ae1078d6SWayne Salamon 		audit_arge = (udata.au_policy & AUDIT_ARGE);
273718c8510SRobert Watson 		break;
274718c8510SRobert Watson 
275718c8510SRobert Watson 	case A_GETKMASK:
2764df4e335SRobert Watson 		if (uap->length != sizeof(udata.au_mask))
2774df4e335SRobert Watson 			return (EINVAL);
278718c8510SRobert Watson 		udata.au_mask = audit_nae_mask;
279718c8510SRobert Watson 		break;
280718c8510SRobert Watson 
281718c8510SRobert Watson 	case A_SETKMASK:
2824df4e335SRobert Watson 		if (uap->length != sizeof(udata.au_mask))
2834df4e335SRobert Watson 			return (EINVAL);
284718c8510SRobert Watson 		audit_nae_mask = udata.au_mask;
285718c8510SRobert Watson 		break;
286718c8510SRobert Watson 
2874df4e335SRobert Watson 	case A_OLDGETQCTRL:
2882a5058a3SRobert Watson 	case A_GETQCTRL:
2894df4e335SRobert Watson 		if (uap->length == sizeof(udata.au_qctrl64)) {
2904df4e335SRobert Watson 			udata.au_qctrl64.aq64_hiwater =
2914df4e335SRobert Watson 			    (u_int64_t)audit_qctrl.aq_hiwater;
2924df4e335SRobert Watson 			udata.au_qctrl64.aq64_lowater =
2934df4e335SRobert Watson 			    (u_int64_t)audit_qctrl.aq_lowater;
2944df4e335SRobert Watson 			udata.au_qctrl64.aq64_bufsz =
2954df4e335SRobert Watson 			    (u_int64_t)audit_qctrl.aq_bufsz;
2964df4e335SRobert Watson 			udata.au_qctrl64.aq64_minfree =
2974df4e335SRobert Watson 			    (u_int64_t)audit_qctrl.aq_minfree;
2984df4e335SRobert Watson 			break;
2994df4e335SRobert Watson 		}
3004df4e335SRobert Watson 		if (uap->length != sizeof(udata.au_qctrl))
3014df4e335SRobert Watson 			return (EINVAL);
302718c8510SRobert Watson 		udata.au_qctrl = audit_qctrl;
303718c8510SRobert Watson 		break;
304718c8510SRobert Watson 
3054df4e335SRobert Watson 	case A_OLDSETQCTRL:
3062a5058a3SRobert Watson 	case A_SETQCTRL:
3074df4e335SRobert Watson 		if (uap->length == sizeof(udata.au_qctrl64)) {
308b3db2736SJohn Baldwin 			/* NB: aq64_minfree is unsigned unlike aq_minfree. */
3094df4e335SRobert Watson 			if ((udata.au_qctrl64.aq64_hiwater > AQ_MAXHIGH) ||
3104df4e335SRobert Watson 			    (udata.au_qctrl64.aq64_lowater >=
3114df4e335SRobert Watson 			    udata.au_qctrl.aq_hiwater) ||
3124df4e335SRobert Watson 			    (udata.au_qctrl64.aq64_bufsz > AQ_MAXBUFSZ) ||
313b3db2736SJohn Baldwin 			    (udata.au_qctrl64.aq64_minfree > 100))
3144df4e335SRobert Watson 				return (EINVAL);
3154df4e335SRobert Watson 			audit_qctrl.aq_hiwater =
3164df4e335SRobert Watson 			    (int)udata.au_qctrl64.aq64_hiwater;
3174df4e335SRobert Watson 			audit_qctrl.aq_lowater =
3184df4e335SRobert Watson 			    (int)udata.au_qctrl64.aq64_lowater;
3194df4e335SRobert Watson 			audit_qctrl.aq_bufsz =
3204df4e335SRobert Watson 			    (int)udata.au_qctrl64.aq64_bufsz;
3214df4e335SRobert Watson 			audit_qctrl.aq_minfree =
3224df4e335SRobert Watson 			    (int)udata.au_qctrl64.aq64_minfree;
3234df4e335SRobert Watson 			audit_qctrl.aq_delay = -1;	/* Not used. */
3244df4e335SRobert Watson 			break;
3254df4e335SRobert Watson 		}
3264df4e335SRobert Watson 		if (uap->length != sizeof(udata.au_qctrl))
3274df4e335SRobert Watson 			return (EINVAL);
328718c8510SRobert Watson 		if ((udata.au_qctrl.aq_hiwater > AQ_MAXHIGH) ||
329718c8510SRobert Watson 		    (udata.au_qctrl.aq_lowater >= udata.au_qctrl.aq_hiwater) ||
330718c8510SRobert Watson 		    (udata.au_qctrl.aq_bufsz > AQ_MAXBUFSZ) ||
331718c8510SRobert Watson 		    (udata.au_qctrl.aq_minfree < 0) ||
332718c8510SRobert Watson 		    (udata.au_qctrl.aq_minfree > 100))
333718c8510SRobert Watson 			return (EINVAL);
334718c8510SRobert Watson 
335718c8510SRobert Watson 		audit_qctrl = udata.au_qctrl;
336718c8510SRobert Watson 		/* XXX The queue delay value isn't used with the kernel. */
337718c8510SRobert Watson 		audit_qctrl.aq_delay = -1;
338718c8510SRobert Watson 		break;
339718c8510SRobert Watson 
340718c8510SRobert Watson 	case A_GETCWD:
341718c8510SRobert Watson 		return (ENOSYS);
342718c8510SRobert Watson 		break;
343718c8510SRobert Watson 
344718c8510SRobert Watson 	case A_GETCAR:
345718c8510SRobert Watson 		return (ENOSYS);
346718c8510SRobert Watson 		break;
347718c8510SRobert Watson 
348718c8510SRobert Watson 	case A_GETSTAT:
349718c8510SRobert Watson 		return (ENOSYS);
350718c8510SRobert Watson 		break;
351718c8510SRobert Watson 
352718c8510SRobert Watson 	case A_SETSTAT:
353718c8510SRobert Watson 		return (ENOSYS);
354718c8510SRobert Watson 		break;
355718c8510SRobert Watson 
356718c8510SRobert Watson 	case A_SETUMASK:
357718c8510SRobert Watson 		return (ENOSYS);
358718c8510SRobert Watson 		break;
359718c8510SRobert Watson 
360718c8510SRobert Watson 	case A_SETSMASK:
361718c8510SRobert Watson 		return (ENOSYS);
362718c8510SRobert Watson 		break;
363718c8510SRobert Watson 
3644df4e335SRobert Watson 	case A_OLDGETCOND:
3652a5058a3SRobert Watson 	case A_GETCOND:
3664df4e335SRobert Watson 		if (uap->length == sizeof(udata.au_cond64)) {
3672ddefb6dSRobert Watson 			if (audit_trail_enabled && !audit_trail_suspended)
3684df4e335SRobert Watson 				udata.au_cond64 = AUC_AUDITING;
3694df4e335SRobert Watson 			else
3704df4e335SRobert Watson 				udata.au_cond64 = AUC_NOAUDIT;
3714df4e335SRobert Watson 			break;
3724df4e335SRobert Watson 		}
3734df4e335SRobert Watson 		if (uap->length != sizeof(udata.au_cond))
3744df4e335SRobert Watson 			return (EINVAL);
3752ddefb6dSRobert Watson 		if (audit_trail_enabled && !audit_trail_suspended)
376718c8510SRobert Watson 			udata.au_cond = AUC_AUDITING;
377718c8510SRobert Watson 		else
378718c8510SRobert Watson 			udata.au_cond = AUC_NOAUDIT;
379718c8510SRobert Watson 		break;
380718c8510SRobert Watson 
3814df4e335SRobert Watson 	case A_OLDSETCOND:
3822a5058a3SRobert Watson 	case A_SETCOND:
3834df4e335SRobert Watson 		if (uap->length == sizeof(udata.au_cond64)) {
3844df4e335SRobert Watson 			if (udata.au_cond64 == AUC_NOAUDIT)
3852ddefb6dSRobert Watson 				audit_trail_suspended = 1;
3864df4e335SRobert Watson 			if (udata.au_cond64 == AUC_AUDITING)
3872ddefb6dSRobert Watson 				audit_trail_suspended = 0;
3884df4e335SRobert Watson 			if (udata.au_cond64 == AUC_DISABLED) {
3892ddefb6dSRobert Watson 				audit_trail_suspended = 1;
3904df4e335SRobert Watson 				audit_shutdown(NULL, 0);
3914df4e335SRobert Watson 			}
3922ddefb6dSRobert Watson 			audit_syscalls_enabled_update();
3934df4e335SRobert Watson 			break;
3944df4e335SRobert Watson 		}
3954df4e335SRobert Watson 		if (uap->length != sizeof(udata.au_cond))
3964df4e335SRobert Watson 			return (EINVAL);
397718c8510SRobert Watson 		if (udata.au_cond == AUC_NOAUDIT)
3982ddefb6dSRobert Watson 			audit_trail_suspended = 1;
399718c8510SRobert Watson 		if (udata.au_cond == AUC_AUDITING)
4002ddefb6dSRobert Watson 			audit_trail_suspended = 0;
401718c8510SRobert Watson 		if (udata.au_cond == AUC_DISABLED) {
4022ddefb6dSRobert Watson 			audit_trail_suspended = 1;
403718c8510SRobert Watson 			audit_shutdown(NULL, 0);
404718c8510SRobert Watson 		}
4052ddefb6dSRobert Watson 		audit_syscalls_enabled_update();
406718c8510SRobert Watson 		break;
407718c8510SRobert Watson 
408718c8510SRobert Watson 	case A_GETCLASS:
4094df4e335SRobert Watson 		if (uap->length != sizeof(udata.au_evclass))
4104df4e335SRobert Watson 			return (EINVAL);
411871499feSRobert Watson 		udata.au_evclass.ec_class = au_event_class(
412871499feSRobert Watson 		    udata.au_evclass.ec_number);
413718c8510SRobert Watson 		break;
414718c8510SRobert Watson 
415759c8caaSRobert Watson 	case A_GETEVENT:
416759c8caaSRobert Watson 		if (uap->length != sizeof(udata.au_evname))
417759c8caaSRobert Watson 			return (EINVAL);
418759c8caaSRobert Watson 		error = au_event_name(udata.au_evname.en_number,
419759c8caaSRobert Watson 		    udata.au_evname.en_name);
420759c8caaSRobert Watson 		if (error != 0)
421759c8caaSRobert Watson 			return (error);
422759c8caaSRobert Watson 		break;
423759c8caaSRobert Watson 
424718c8510SRobert Watson 	case A_SETCLASS:
4254df4e335SRobert Watson 		if (uap->length != sizeof(udata.au_evclass))
4264df4e335SRobert Watson 			return (EINVAL);
427718c8510SRobert Watson 		au_evclassmap_insert(udata.au_evclass.ec_number,
428718c8510SRobert Watson 		    udata.au_evclass.ec_class);
429718c8510SRobert Watson 		break;
430718c8510SRobert Watson 
431759c8caaSRobert Watson 	case A_SETEVENT:
432759c8caaSRobert Watson 		if (uap->length != sizeof(udata.au_evname))
433759c8caaSRobert Watson 			return (EINVAL);
434759c8caaSRobert Watson 
435759c8caaSRobert Watson 		/* Ensure nul termination from userspace. */
436759c8caaSRobert Watson 		udata.au_evname.en_name[sizeof(udata.au_evname.en_name) - 1]
437759c8caaSRobert Watson 		    = 0;
438759c8caaSRobert Watson 		au_evnamemap_insert(udata.au_evname.en_number,
439759c8caaSRobert Watson 		    udata.au_evname.en_name);
440759c8caaSRobert Watson 		break;
441759c8caaSRobert Watson 
442718c8510SRobert Watson 	case A_GETPINFO:
4434df4e335SRobert Watson 		if (uap->length != sizeof(udata.au_aupinfo))
4444df4e335SRobert Watson 			return (EINVAL);
445718c8510SRobert Watson 		if (udata.au_aupinfo.ap_pid < 1)
446f308bdddSKevin Lo 			return (ESRCH);
447718c8510SRobert Watson 		if ((tp = pfind(udata.au_aupinfo.ap_pid)) == NULL)
448f308bdddSKevin Lo 			return (ESRCH);
44919de3e90SDag-Erling Smørgrav 		if ((error = p_cansee(td, tp)) != 0) {
450aa6fe97cSRobert Watson 			PROC_UNLOCK(tp);
451f308bdddSKevin Lo 			return (error);
452aa6fe97cSRobert Watson 		}
453e6870c95SRobert Watson 		cred = tp->p_ucred;
454e6870c95SRobert Watson 		if (cred->cr_audit.ai_termid.at_type == AU_IPv6) {
455f0cbfcc4SChristian S.J. Peron 			PROC_UNLOCK(tp);
456f0cbfcc4SChristian S.J. Peron 			return (EINVAL);
457f0cbfcc4SChristian S.J. Peron 		}
458e6870c95SRobert Watson 		udata.au_aupinfo.ap_auid = cred->cr_audit.ai_auid;
459718c8510SRobert Watson 		udata.au_aupinfo.ap_mask.am_success =
460e6870c95SRobert Watson 		    cred->cr_audit.ai_mask.am_success;
461718c8510SRobert Watson 		udata.au_aupinfo.ap_mask.am_failure =
462e6870c95SRobert Watson 		    cred->cr_audit.ai_mask.am_failure;
463718c8510SRobert Watson 		udata.au_aupinfo.ap_termid.machine =
464e6870c95SRobert Watson 		    cred->cr_audit.ai_termid.at_addr[0];
465f0cbfcc4SChristian S.J. Peron 		udata.au_aupinfo.ap_termid.port =
466e6870c95SRobert Watson 		    (dev_t)cred->cr_audit.ai_termid.at_port;
467e6870c95SRobert Watson 		udata.au_aupinfo.ap_asid = cred->cr_audit.ai_asid;
468718c8510SRobert Watson 		PROC_UNLOCK(tp);
469718c8510SRobert Watson 		break;
470718c8510SRobert Watson 
471718c8510SRobert Watson 	case A_SETPMASK:
4724df4e335SRobert Watson 		if (uap->length != sizeof(udata.au_aupinfo))
4734df4e335SRobert Watson 			return (EINVAL);
474718c8510SRobert Watson 		if (udata.au_aupinfo.ap_pid < 1)
475f308bdddSKevin Lo 			return (ESRCH);
476faef5371SRobert Watson 		newcred = crget();
477faef5371SRobert Watson 		if ((tp = pfind(udata.au_aupinfo.ap_pid)) == NULL) {
478faef5371SRobert Watson 			crfree(newcred);
479f308bdddSKevin Lo 			return (ESRCH);
480aa6fe97cSRobert Watson 		}
48119de3e90SDag-Erling Smørgrav 		if ((error = p_cansee(td, tp)) != 0) {
482718c8510SRobert Watson 			PROC_UNLOCK(tp);
483faef5371SRobert Watson 			crfree(newcred);
484f308bdddSKevin Lo 			return (error);
485faef5371SRobert Watson 		}
486faef5371SRobert Watson 		oldcred = tp->p_ucred;
487faef5371SRobert Watson 		crcopy(newcred, oldcred);
488faef5371SRobert Watson 		newcred->cr_audit.ai_mask.am_success =
489faef5371SRobert Watson 		    udata.au_aupinfo.ap_mask.am_success;
490faef5371SRobert Watson 		newcred->cr_audit.ai_mask.am_failure =
491faef5371SRobert Watson 		    udata.au_aupinfo.ap_mask.am_failure;
492daf63fd2SMateusz Guzik 		proc_set_cred(tp, newcred);
493faef5371SRobert Watson 		PROC_UNLOCK(tp);
494faef5371SRobert Watson 		crfree(oldcred);
495718c8510SRobert Watson 		break;
496718c8510SRobert Watson 
497718c8510SRobert Watson 	case A_SETFSIZE:
4984df4e335SRobert Watson 		if (uap->length != sizeof(udata.au_fstat))
4994df4e335SRobert Watson 			return (EINVAL);
500718c8510SRobert Watson 		if ((udata.au_fstat.af_filesz != 0) &&
501718c8510SRobert Watson 		   (udata.au_fstat.af_filesz < MIN_AUDIT_FILE_SIZE))
502718c8510SRobert Watson 			return (EINVAL);
503718c8510SRobert Watson 		audit_fstat.af_filesz = udata.au_fstat.af_filesz;
504718c8510SRobert Watson 		break;
505718c8510SRobert Watson 
506718c8510SRobert Watson 	case A_GETFSIZE:
5074df4e335SRobert Watson 		if (uap->length != sizeof(udata.au_fstat))
5084df4e335SRobert Watson 			return (EINVAL);
509718c8510SRobert Watson 		udata.au_fstat.af_filesz = audit_fstat.af_filesz;
510718c8510SRobert Watson 		udata.au_fstat.af_currsz = audit_fstat.af_currsz;
511718c8510SRobert Watson 		break;
512718c8510SRobert Watson 
513718c8510SRobert Watson 	case A_GETPINFO_ADDR:
5144df4e335SRobert Watson 		if (uap->length != sizeof(udata.au_aupinfo_addr))
5154df4e335SRobert Watson 			return (EINVAL);
516f0cbfcc4SChristian S.J. Peron 		if (udata.au_aupinfo_addr.ap_pid < 1)
517f308bdddSKevin Lo 			return (ESRCH);
518f0cbfcc4SChristian S.J. Peron 		if ((tp = pfind(udata.au_aupinfo_addr.ap_pid)) == NULL)
519f308bdddSKevin Lo 			return (ESRCH);
520e6870c95SRobert Watson 		cred = tp->p_ucred;
521e6870c95SRobert Watson 		udata.au_aupinfo_addr.ap_auid = cred->cr_audit.ai_auid;
522f0cbfcc4SChristian S.J. Peron 		udata.au_aupinfo_addr.ap_mask.am_success =
523e6870c95SRobert Watson 		    cred->cr_audit.ai_mask.am_success;
524f0cbfcc4SChristian S.J. Peron 		udata.au_aupinfo_addr.ap_mask.am_failure =
525e6870c95SRobert Watson 		    cred->cr_audit.ai_mask.am_failure;
526e6870c95SRobert Watson 		udata.au_aupinfo_addr.ap_termid = cred->cr_audit.ai_termid;
527e6870c95SRobert Watson 		udata.au_aupinfo_addr.ap_asid = cred->cr_audit.ai_asid;
528f0cbfcc4SChristian S.J. Peron 		PROC_UNLOCK(tp);
529718c8510SRobert Watson 		break;
530718c8510SRobert Watson 
531718c8510SRobert Watson 	case A_GETKAUDIT:
5324df4e335SRobert Watson 		if (uap->length != sizeof(udata.au_kau_info))
5334df4e335SRobert Watson 			return (EINVAL);
534ffbcef5aSChristian S.J. Peron 		audit_get_kinfo(&udata.au_kau_info);
535718c8510SRobert Watson 		break;
536718c8510SRobert Watson 
537718c8510SRobert Watson 	case A_SETKAUDIT:
5384df4e335SRobert Watson 		if (uap->length != sizeof(udata.au_kau_info))
5394df4e335SRobert Watson 			return (EINVAL);
540ffbcef5aSChristian S.J. Peron 		if (udata.au_kau_info.ai_termid.at_type != AU_IPv4 &&
541ffbcef5aSChristian S.J. Peron 		    udata.au_kau_info.ai_termid.at_type != AU_IPv6)
542ffbcef5aSChristian S.J. Peron 			return (EINVAL);
543ffbcef5aSChristian S.J. Peron 		audit_set_kinfo(&udata.au_kau_info);
544718c8510SRobert Watson 		break;
545718c8510SRobert Watson 
546718c8510SRobert Watson 	case A_SENDTRIGGER:
5474df4e335SRobert Watson 		if (uap->length != sizeof(udata.au_trigger))
5484df4e335SRobert Watson 			return (EINVAL);
549718c8510SRobert Watson 		if ((udata.au_trigger < AUDIT_TRIGGER_MIN) ||
550718c8510SRobert Watson 		    (udata.au_trigger > AUDIT_TRIGGER_MAX))
551718c8510SRobert Watson 			return (EINVAL);
552fb4ed8c9SRobert Watson 		return (audit_send_trigger(udata.au_trigger));
553e5ad5f4dSChristian S.J. Peron 
554e5ad5f4dSChristian S.J. Peron 	default:
555e5ad5f4dSChristian S.J. Peron 		return (EINVAL);
556718c8510SRobert Watson 	}
557871499feSRobert Watson 
558871499feSRobert Watson 	/*
559871499feSRobert Watson 	 * Copy data back to userspace for the GET comands.
560871499feSRobert Watson 	 */
561718c8510SRobert Watson 	switch (uap->cmd) {
562718c8510SRobert Watson 	case A_GETPOLICY:
5634df4e335SRobert Watson 	case A_OLDGETPOLICY:
564718c8510SRobert Watson 	case A_GETKMASK:
565718c8510SRobert Watson 	case A_GETQCTRL:
5664df4e335SRobert Watson 	case A_OLDGETQCTRL:
567718c8510SRobert Watson 	case A_GETCWD:
568718c8510SRobert Watson 	case A_GETCAR:
569718c8510SRobert Watson 	case A_GETSTAT:
570718c8510SRobert Watson 	case A_GETCOND:
5714df4e335SRobert Watson 	case A_OLDGETCOND:
572718c8510SRobert Watson 	case A_GETCLASS:
573718c8510SRobert Watson 	case A_GETPINFO:
574718c8510SRobert Watson 	case A_GETFSIZE:
575718c8510SRobert Watson 	case A_GETPINFO_ADDR:
576718c8510SRobert Watson 	case A_GETKAUDIT:
577718c8510SRobert Watson 		error = copyout((void *)&udata, uap->data, uap->length);
578718c8510SRobert Watson 		if (error)
579718c8510SRobert Watson 			return (error);
580718c8510SRobert Watson 		break;
581718c8510SRobert Watson 	}
582718c8510SRobert Watson 
583718c8510SRobert Watson 	return (0);
584718c8510SRobert Watson }
585718c8510SRobert Watson 
586718c8510SRobert Watson /*
587718c8510SRobert Watson  * System calls to manage the user audit information.
588718c8510SRobert Watson  */
589718c8510SRobert Watson /* ARGSUSED */
590718c8510SRobert Watson int
sys_getauid(struct thread * td,struct getauid_args * uap)5918451d0ddSKip Macy sys_getauid(struct thread *td, struct getauid_args *uap)
592718c8510SRobert Watson {
593718c8510SRobert Watson 	int error;
594718c8510SRobert Watson 
59506399e90SChristian S.J. Peron 	if (jailed(td->td_ucred))
59606399e90SChristian S.J. Peron 		return (ENOSYS);
597acd3428bSRobert Watson 	error = priv_check(td, PRIV_AUDIT_GETAUDIT);
598718c8510SRobert Watson 	if (error)
599718c8510SRobert Watson 		return (error);
600faef5371SRobert Watson 	return (copyout(&td->td_ucred->cr_audit.ai_auid, uap->auid,
601faef5371SRobert Watson 	    sizeof(td->td_ucred->cr_audit.ai_auid)));
602718c8510SRobert Watson }
603718c8510SRobert Watson 
604718c8510SRobert Watson /* ARGSUSED */
605718c8510SRobert Watson int
sys_setauid(struct thread * td,struct setauid_args * uap)6068451d0ddSKip Macy sys_setauid(struct thread *td, struct setauid_args *uap)
607718c8510SRobert Watson {
608faef5371SRobert Watson 	struct ucred *newcred, *oldcred;
609718c8510SRobert Watson 	au_id_t id;
610faef5371SRobert Watson 	int error;
611718c8510SRobert Watson 
61206399e90SChristian S.J. Peron 	if (jailed(td->td_ucred))
61306399e90SChristian S.J. Peron 		return (ENOSYS);
614718c8510SRobert Watson 	error = copyin(uap->auid, &id, sizeof(id));
615718c8510SRobert Watson 	if (error)
616718c8510SRobert Watson 		return (error);
617718c8510SRobert Watson 	audit_arg_auid(id);
618faef5371SRobert Watson 	newcred = crget();
619718c8510SRobert Watson 	PROC_LOCK(td->td_proc);
620faef5371SRobert Watson 	oldcred = td->td_proc->p_ucred;
621faef5371SRobert Watson 	crcopy(newcred, oldcred);
622faef5371SRobert Watson #ifdef MAC
6236f6174a7SRobert Watson 	error = mac_cred_check_setauid(oldcred, id);
624faef5371SRobert Watson 	if (error)
625faef5371SRobert Watson 		goto fail;
626faef5371SRobert Watson #endif
627cc426dd3SMateusz Guzik 	error = priv_check_cred(oldcred, PRIV_AUDIT_SETAUDIT);
628faef5371SRobert Watson 	if (error)
629faef5371SRobert Watson 		goto fail;
630faef5371SRobert Watson 	newcred->cr_audit.ai_auid = id;
631daf63fd2SMateusz Guzik 	proc_set_cred(td->td_proc, newcred);
632718c8510SRobert Watson 	PROC_UNLOCK(td->td_proc);
633faef5371SRobert Watson 	crfree(oldcred);
634718c8510SRobert Watson 	return (0);
635faef5371SRobert Watson fail:
636faef5371SRobert Watson 	PROC_UNLOCK(td->td_proc);
637faef5371SRobert Watson 	crfree(newcred);
638faef5371SRobert Watson 	return (error);
639718c8510SRobert Watson }
640718c8510SRobert Watson 
641718c8510SRobert Watson /*
642718c8510SRobert Watson  * System calls to get and set process audit information.
643718c8510SRobert Watson  */
644718c8510SRobert Watson /* ARGSUSED */
645718c8510SRobert Watson int
sys_getaudit(struct thread * td,struct getaudit_args * uap)6468451d0ddSKip Macy sys_getaudit(struct thread *td, struct getaudit_args *uap)
647718c8510SRobert Watson {
648718c8510SRobert Watson 	struct auditinfo ai;
649e6870c95SRobert Watson 	struct ucred *cred;
650718c8510SRobert Watson 	int error;
651718c8510SRobert Watson 
652e6870c95SRobert Watson 	cred = td->td_ucred;
653e6870c95SRobert Watson 	if (jailed(cred))
65406399e90SChristian S.J. Peron 		return (ENOSYS);
655acd3428bSRobert Watson 	error = priv_check(td, PRIV_AUDIT_GETAUDIT);
656718c8510SRobert Watson 	if (error)
657718c8510SRobert Watson 		return (error);
658e6870c95SRobert Watson 	if (cred->cr_audit.ai_termid.at_type == AU_IPv6)
6595ac14ef1SChristian S.J. Peron 		return (E2BIG);
660f0cbfcc4SChristian S.J. Peron 	bzero(&ai, sizeof(ai));
661e6870c95SRobert Watson 	ai.ai_auid = cred->cr_audit.ai_auid;
662e6870c95SRobert Watson 	ai.ai_mask = cred->cr_audit.ai_mask;
663e6870c95SRobert Watson 	ai.ai_asid = cred->cr_audit.ai_asid;
664e6870c95SRobert Watson 	ai.ai_termid.machine = cred->cr_audit.ai_termid.at_addr[0];
665e6870c95SRobert Watson 	ai.ai_termid.port = cred->cr_audit.ai_termid.at_port;
666cac465aaSChristian S.J. Peron 	return (copyout(&ai, uap->auditinfo, sizeof(ai)));
667718c8510SRobert Watson }
668718c8510SRobert Watson 
669718c8510SRobert Watson /* ARGSUSED */
670718c8510SRobert Watson int
sys_setaudit(struct thread * td,struct setaudit_args * uap)6718451d0ddSKip Macy sys_setaudit(struct thread *td, struct setaudit_args *uap)
672718c8510SRobert Watson {
673faef5371SRobert Watson 	struct ucred *newcred, *oldcred;
674718c8510SRobert Watson 	struct auditinfo ai;
675718c8510SRobert Watson 	int error;
676718c8510SRobert Watson 
67706399e90SChristian S.J. Peron 	if (jailed(td->td_ucred))
67806399e90SChristian S.J. Peron 		return (ENOSYS);
679718c8510SRobert Watson 	error = copyin(uap->auditinfo, &ai, sizeof(ai));
680718c8510SRobert Watson 	if (error)
681718c8510SRobert Watson 		return (error);
682718c8510SRobert Watson 	audit_arg_auditinfo(&ai);
683faef5371SRobert Watson 	newcred = crget();
684718c8510SRobert Watson 	PROC_LOCK(td->td_proc);
685faef5371SRobert Watson 	oldcred = td->td_proc->p_ucred;
686faef5371SRobert Watson 	crcopy(newcred, oldcred);
687faef5371SRobert Watson #ifdef MAC
6886f6174a7SRobert Watson 	error = mac_cred_check_setaudit(oldcred, &ai);
689faef5371SRobert Watson 	if (error)
690faef5371SRobert Watson 		goto fail;
691faef5371SRobert Watson #endif
692cc426dd3SMateusz Guzik 	error = priv_check_cred(oldcred, PRIV_AUDIT_SETAUDIT);
693faef5371SRobert Watson 	if (error)
694faef5371SRobert Watson 		goto fail;
695faef5371SRobert Watson 	bzero(&newcred->cr_audit, sizeof(newcred->cr_audit));
696faef5371SRobert Watson 	newcred->cr_audit.ai_auid = ai.ai_auid;
697faef5371SRobert Watson 	newcred->cr_audit.ai_mask = ai.ai_mask;
698faef5371SRobert Watson 	newcred->cr_audit.ai_asid = ai.ai_asid;
699faef5371SRobert Watson 	newcred->cr_audit.ai_termid.at_addr[0] = ai.ai_termid.machine;
700faef5371SRobert Watson 	newcred->cr_audit.ai_termid.at_port = ai.ai_termid.port;
701faef5371SRobert Watson 	newcred->cr_audit.ai_termid.at_type = AU_IPv4;
702daf63fd2SMateusz Guzik 	proc_set_cred(td->td_proc, newcred);
703718c8510SRobert Watson 	PROC_UNLOCK(td->td_proc);
704faef5371SRobert Watson 	crfree(oldcred);
705718c8510SRobert Watson 	return (0);
706faef5371SRobert Watson fail:
707faef5371SRobert Watson 	PROC_UNLOCK(td->td_proc);
708faef5371SRobert Watson 	crfree(newcred);
709faef5371SRobert Watson 	return (error);
710718c8510SRobert Watson }
711718c8510SRobert Watson 
712718c8510SRobert Watson /* ARGSUSED */
713718c8510SRobert Watson int
sys_getaudit_addr(struct thread * td,struct getaudit_addr_args * uap)7148451d0ddSKip Macy sys_getaudit_addr(struct thread *td, struct getaudit_addr_args *uap)
715718c8510SRobert Watson {
716718c8510SRobert Watson 	int error;
717718c8510SRobert Watson 
71806399e90SChristian S.J. Peron 	if (jailed(td->td_ucred))
71906399e90SChristian S.J. Peron 		return (ENOSYS);
720faef5371SRobert Watson 	if (uap->length < sizeof(*uap->auditinfo_addr))
721faef5371SRobert Watson 		return (EOVERFLOW);
722acd3428bSRobert Watson 	error = priv_check(td, PRIV_AUDIT_GETAUDIT);
723718c8510SRobert Watson 	if (error)
724718c8510SRobert Watson 		return (error);
725faef5371SRobert Watson 	return (copyout(&td->td_ucred->cr_audit, uap->auditinfo_addr,
726faef5371SRobert Watson 	    sizeof(*uap->auditinfo_addr)));
727718c8510SRobert Watson }
728718c8510SRobert Watson 
729718c8510SRobert Watson /* ARGSUSED */
730718c8510SRobert Watson int
sys_setaudit_addr(struct thread * td,struct setaudit_addr_args * uap)7318451d0ddSKip Macy sys_setaudit_addr(struct thread *td, struct setaudit_addr_args *uap)
732718c8510SRobert Watson {
733faef5371SRobert Watson 	struct ucred *newcred, *oldcred;
734f0cbfcc4SChristian S.J. Peron 	struct auditinfo_addr aia;
735718c8510SRobert Watson 	int error;
736718c8510SRobert Watson 
73706399e90SChristian S.J. Peron 	if (jailed(td->td_ucred))
73806399e90SChristian S.J. Peron 		return (ENOSYS);
739f0cbfcc4SChristian S.J. Peron 	error = copyin(uap->auditinfo_addr, &aia, sizeof(aia));
740f0cbfcc4SChristian S.J. Peron 	if (error)
741f0cbfcc4SChristian S.J. Peron 		return (error);
742cac465aaSChristian S.J. Peron 	audit_arg_auditinfo_addr(&aia);
743cac465aaSChristian S.J. Peron 	if (aia.ai_termid.at_type != AU_IPv6 &&
744cac465aaSChristian S.J. Peron 	    aia.ai_termid.at_type != AU_IPv4)
745cac465aaSChristian S.J. Peron 		return (EINVAL);
746faef5371SRobert Watson 	newcred = crget();
747f0cbfcc4SChristian S.J. Peron 	PROC_LOCK(td->td_proc);
748faef5371SRobert Watson 	oldcred = td->td_proc->p_ucred;
749faef5371SRobert Watson 	crcopy(newcred, oldcred);
750faef5371SRobert Watson #ifdef MAC
7516f6174a7SRobert Watson 	error = mac_cred_check_setaudit_addr(oldcred, &aia);
752faef5371SRobert Watson 	if (error)
753faef5371SRobert Watson 		goto fail;
754faef5371SRobert Watson #endif
755cc426dd3SMateusz Guzik 	error = priv_check_cred(oldcred, PRIV_AUDIT_SETAUDIT);
756faef5371SRobert Watson 	if (error)
757faef5371SRobert Watson 		goto fail;
758faef5371SRobert Watson 	newcred->cr_audit = aia;
759daf63fd2SMateusz Guzik 	proc_set_cred(td->td_proc, newcred);
760f0cbfcc4SChristian S.J. Peron 	PROC_UNLOCK(td->td_proc);
761faef5371SRobert Watson 	crfree(oldcred);
762faef5371SRobert Watson 	return (0);
763faef5371SRobert Watson fail:
764f640bf47SRobert Watson 	PROC_UNLOCK(td->td_proc);
765faef5371SRobert Watson 	crfree(newcred);
766f0cbfcc4SChristian S.J. Peron 	return (error);
767718c8510SRobert Watson }
768718c8510SRobert Watson 
769718c8510SRobert Watson /*
770718c8510SRobert Watson  * Syscall to manage audit files.
771718c8510SRobert Watson  */
772718c8510SRobert Watson /* ARGSUSED */
773718c8510SRobert Watson int
sys_auditctl(struct thread * td,struct auditctl_args * uap)7748451d0ddSKip Macy sys_auditctl(struct thread *td, struct auditctl_args *uap)
775718c8510SRobert Watson {
776718c8510SRobert Watson 	struct nameidata nd;
777718c8510SRobert Watson 	struct ucred *cred;
778718c8510SRobert Watson 	struct vnode *vp;
779718c8510SRobert Watson 	int error = 0;
7805050aa86SKonstantin Belousov 	int flags;
781718c8510SRobert Watson 
78206399e90SChristian S.J. Peron 	if (jailed(td->td_ucred))
78306399e90SChristian S.J. Peron 		return (ENOSYS);
784acd3428bSRobert Watson 	error = priv_check(td, PRIV_AUDIT_CONTROL);
785718c8510SRobert Watson 	if (error)
786718c8510SRobert Watson 		return (error);
787718c8510SRobert Watson 
788718c8510SRobert Watson 	vp = NULL;
789718c8510SRobert Watson 	cred = NULL;
790718c8510SRobert Watson 
791718c8510SRobert Watson 	/*
792718c8510SRobert Watson 	 * If a path is specified, open the replacement vnode, perform
793718c8510SRobert Watson 	 * validity checks, and grab another reference to the current
794718c8510SRobert Watson 	 * credential.
795718c8510SRobert Watson 	 *
796aa6fe97cSRobert Watson 	 * On Darwin, a NULL path argument is also used to disable audit.
797718c8510SRobert Watson 	 */
798718c8510SRobert Watson 	if (uap->path == NULL)
799718c8510SRobert Watson 		return (EINVAL);
800718c8510SRobert Watson 
8017e1d3eefSMateusz Guzik 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | AUDITVNODE1, UIO_USERSPACE,
8027e1d3eefSMateusz Guzik 	    uap->path);
803718c8510SRobert Watson 	flags = AUDIT_OPEN_FLAGS;
8047a31868eSKonstantin Belousov 	error = vn_open(&nd, &flags, 0, NULL);
805714e68b8SRobert Watson 	if (error)
806714e68b8SRobert Watson 		return (error);
807718c8510SRobert Watson 	vp = nd.ni_vp;
80818717f69SRobert Watson #ifdef MAC
80930d239bcSRobert Watson 	error = mac_system_check_auditctl(td->td_ucred, vp);
810b249ce48SMateusz Guzik 	VOP_UNLOCK(vp);
81118717f69SRobert Watson 	if (error) {
81218717f69SRobert Watson 		vn_close(vp, AUDIT_CLOSE_FLAGS, td->td_ucred, td);
81318717f69SRobert Watson 		return (error);
81418717f69SRobert Watson 	}
81518717f69SRobert Watson #else
816b249ce48SMateusz Guzik 	VOP_UNLOCK(vp);
81718717f69SRobert Watson #endif
818*bb92cd7bSMateusz Guzik 	NDFREE_PNBUF(&nd);
819718c8510SRobert Watson 	if (vp->v_type != VREG) {
820718c8510SRobert Watson 		vn_close(vp, AUDIT_CLOSE_FLAGS, td->td_ucred, td);
821714e68b8SRobert Watson 		return (EINVAL);
822718c8510SRobert Watson 	}
823718c8510SRobert Watson 	cred = td->td_ucred;
824718c8510SRobert Watson 	crhold(cred);
825718c8510SRobert Watson 
826718c8510SRobert Watson 	/*
8272ddefb6dSRobert Watson 	 * XXXAUDIT: Should audit_trail_suspended actually be cleared by
828718c8510SRobert Watson 	 * audit_worker?
829718c8510SRobert Watson 	 */
8302ddefb6dSRobert Watson 	audit_trail_suspended = 0;
8312ddefb6dSRobert Watson 	audit_syscalls_enabled_update();
832718c8510SRobert Watson 
833718c8510SRobert Watson 	audit_rotate_vnode(cred, vp);
834718c8510SRobert Watson 
835718c8510SRobert Watson 	return (error);
836718c8510SRobert Watson }
837718c8510SRobert Watson 
838718c8510SRobert Watson #else /* !AUDIT */
839718c8510SRobert Watson 
840718c8510SRobert Watson int
sys_audit(struct thread * td,struct audit_args * uap)8418451d0ddSKip Macy sys_audit(struct thread *td, struct audit_args *uap)
842718c8510SRobert Watson {
843718c8510SRobert Watson 
844718c8510SRobert Watson 	return (ENOSYS);
845718c8510SRobert Watson }
846718c8510SRobert Watson 
847718c8510SRobert Watson int
sys_auditon(struct thread * td,struct auditon_args * uap)8488451d0ddSKip Macy sys_auditon(struct thread *td, struct auditon_args *uap)
849718c8510SRobert Watson {
850718c8510SRobert Watson 
851718c8510SRobert Watson 	return (ENOSYS);
852718c8510SRobert Watson }
853718c8510SRobert Watson 
854718c8510SRobert Watson int
sys_getauid(struct thread * td,struct getauid_args * uap)8558451d0ddSKip Macy sys_getauid(struct thread *td, struct getauid_args *uap)
856718c8510SRobert Watson {
857718c8510SRobert Watson 
858718c8510SRobert Watson 	return (ENOSYS);
859718c8510SRobert Watson }
860718c8510SRobert Watson 
861718c8510SRobert Watson int
sys_setauid(struct thread * td,struct setauid_args * uap)8628451d0ddSKip Macy sys_setauid(struct thread *td, struct setauid_args *uap)
863718c8510SRobert Watson {
864718c8510SRobert Watson 
865718c8510SRobert Watson 	return (ENOSYS);
866718c8510SRobert Watson }
867718c8510SRobert Watson 
868718c8510SRobert Watson int
sys_getaudit(struct thread * td,struct getaudit_args * uap)8698451d0ddSKip Macy sys_getaudit(struct thread *td, struct getaudit_args *uap)
870718c8510SRobert Watson {
871718c8510SRobert Watson 
872718c8510SRobert Watson 	return (ENOSYS);
873718c8510SRobert Watson }
874718c8510SRobert Watson 
875718c8510SRobert Watson int
sys_setaudit(struct thread * td,struct setaudit_args * uap)8768451d0ddSKip Macy sys_setaudit(struct thread *td, struct setaudit_args *uap)
877718c8510SRobert Watson {
878718c8510SRobert Watson 
879718c8510SRobert Watson 	return (ENOSYS);
880718c8510SRobert Watson }
881718c8510SRobert Watson 
882718c8510SRobert Watson int
sys_getaudit_addr(struct thread * td,struct getaudit_addr_args * uap)8838451d0ddSKip Macy sys_getaudit_addr(struct thread *td, struct getaudit_addr_args *uap)
884718c8510SRobert Watson {
885718c8510SRobert Watson 
886718c8510SRobert Watson 	return (ENOSYS);
887718c8510SRobert Watson }
888718c8510SRobert Watson 
889718c8510SRobert Watson int
sys_setaudit_addr(struct thread * td,struct setaudit_addr_args * uap)8908451d0ddSKip Macy sys_setaudit_addr(struct thread *td, struct setaudit_addr_args *uap)
891718c8510SRobert Watson {
892718c8510SRobert Watson 
893718c8510SRobert Watson 	return (ENOSYS);
894718c8510SRobert Watson }
895718c8510SRobert Watson 
896718c8510SRobert Watson int
sys_auditctl(struct thread * td,struct auditctl_args * uap)8978451d0ddSKip Macy sys_auditctl(struct thread *td, struct auditctl_args *uap)
898718c8510SRobert Watson {
899718c8510SRobert Watson 
900718c8510SRobert Watson 	return (ENOSYS);
901718c8510SRobert Watson }
902718c8510SRobert Watson #endif /* AUDIT */
903