xref: /xnu-10002.81.5/bsd/security/audit/audit_syscalls.c (revision 5e3eaea39dcf651e66cb99ba7d70e32cc4a99587)
1 /*-
2  * Copyright (c) 1999-2019 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1.  Redistributions of source code must retain the above copyright
8  *     notice, this list of conditions and the following disclaimer.
9  * 2.  Redistributions in binary form must reproduce the above copyright
10  *     notice, this list of conditions and the following disclaimer in the
11  *     documentation and/or other materials provided with the distribution.
12  * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
13  *     its contributors may be used to endorse or promote products derived
14  *     from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR
20  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
24  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
25  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  * POSSIBILITY OF SUCH DAMAGE.
27  */
28 /*
29  * NOTICE: This file was modified by McAfee Research in 2004 to introduce
30  * support for mandatory and extensible security protections.  This notice
31  * is included in support of clause 2.2 (b) of the Apple Public License,
32  * Version 2.0.
33  */
34 
35 #include <sys/param.h>
36 #include <sys/fcntl.h>
37 #include <sys/kernel.h>
38 #include <sys/lock.h>
39 #include <sys/namei.h>
40 #include <sys/proc_internal.h>
41 #include <sys/kauth.h>
42 #include <sys/queue.h>
43 #include <sys/systm.h>
44 #include <sys/time.h>
45 #include <sys/ucred.h>
46 #include <sys/uio.h>
47 #include <sys/unistd.h>
48 #include <sys/file_internal.h>
49 #include <sys/vnode_internal.h>
50 #include <sys/user.h>
51 #include <sys/syscall.h>
52 #include <sys/un.h>
53 #include <sys/sysent.h>
54 #include <sys/sysproto.h>
55 #include <sys/vfs_context.h>
56 #include <sys/domain.h>
57 #include <sys/protosw.h>
58 #include <sys/socketvar.h>
59 
60 #include <bsm/audit.h>
61 #include <bsm/audit_internal.h>
62 #include <bsm/audit_kevents.h>
63 
64 #include <security/audit/audit.h>
65 #include <security/audit/audit_bsd.h>
66 #include <security/audit/audit_private.h>
67 
68 #include <mach/host_priv.h>
69 #include <mach/host_special_ports.h>
70 #include <mach/audit_triggers_server.h>
71 
72 #include <kern/host.h>
73 #include <kern/sched_prim.h>
74 
75 #if CONFIG_MACF
76 #include <bsm/audit_record.h>
77 #include <security/mac.h>
78 #include <security/mac_framework.h>
79 #include <security/mac_policy.h>
80 #endif
81 
82 #include <net/route.h>
83 
84 #include <netinet/in.h>
85 #include <netinet/in_pcb.h>
86 
87 #include <IOKit/IOBSD.h>
88 
89 #if CONFIG_AUDIT
90 
91 #define IS_NOT_VALID_PID(p)     ((p) < 1 || (p) > PID_MAX)
92 
93 #ifdef AUDIT_API_WARNINGS
94 /*
95  * Macro to warn about auditinfo_addr_t/auditpinfo_addr_t changing sizes
96  * to encourage the userland code to be recompiled and updated.
97  */
98 #define WARN_IF_AINFO_ADDR_CHANGED(sz1, sz2, scall, tp) do {            \
99 	if ((size_t)(sz1) != (size_t)(sz2)) {                           \
100 	        char pn[MAXCOMLEN + 1];                                 \
101                                                                         \
102 	        proc_selfname(pn, MAXCOMLEN + 1);                       \
103 	        printf("Size of %s used by %s in %s is different from " \
104 	            "kernel's.  Please recompile %s.\n", (tp),          \
105 	            (scall), pn, pn);                                   \
106 	}                                                               \
107 } while (0)
108 
109 /*
110  * Macro to warn about using ASID's outside the range [1 to PID_MAX] to
111  * encourage userland code changes.
112  */
113 #define WARN_IF_BAD_ASID(asid, scall) do {                              \
114 	if (((asid) < 1 || (asid) > PID_MAX) &&                         \
115 	     (asid) != AU_ASSIGN_ASID) {                                \
116 	        char pn[MAXCOMLEN + 1];                                 \
117                                                                         \
118 	        proc_selfname(pn, MAXCOMLEN + 1);                       \
119 	        printf("%s in %s is using an ASID (%u) outside the "    \
120 	            "range [1 to %d].  Please change %s to use an ASID "\
121 	            "within this range or use AU_ASSIGN_ASID.\n",       \
122 	            (scall), pn, (uint32_t)(asid), PID_MAX, pn);        \
123 	}                                                               \
124 } while (0)
125 
126 #else /* ! AUDIT_API_WARNINGS */
127 
128 #define WARN_IF_AINFO_ADDR_CHANGED(sz1, sz2, scall, tp) do {            \
129 } while (0)
130 
131 #define WARN_IF_BAD_ASID(asid, scall) do {                              \
132 } while (0)
133 
134 #endif /* AUDIT_API_WARNINGS */
135 
136 /*
137  * System call to allow a user space application to submit a BSM audit record
138  * to the kernel for inclusion in the audit log.  This function does little
139  * verification on the audit record that is submitted.
140  *
141  * XXXAUDIT: Audit preselection for user records does not currently work,
142  * since we pre-select only based on the AUE_audit event type, not the event
143  * type submitted as part of the user audit data.
144  */
145 /* ARGSUSED */
146 int
audit(proc_t p,struct audit_args * uap,__unused int32_t * retval)147 audit(proc_t p, struct audit_args *uap, __unused int32_t *retval)
148 {
149 	int error = 0;
150 	void * rec = NULL;
151 	void * full_rec = NULL;
152 	struct kaudit_record *ar = NULL;
153 	struct uthread *uthr = NULL;
154 	int add_identity_token = 1;
155 	int max_record_length = MAX_AUDIT_RECORD_SIZE;
156 	void *udata = NULL;
157 	u_int ulen = 0;
158 	struct au_identity_info id_info = {
159 		.signer_type = 0,
160 		.signing_id = NULL,
161 		.signing_id_trunc = 0,
162 		.team_id = NULL,
163 		.team_id_trunc = 0,
164 		.cdhash = NULL,
165 		.cdhash_len = 0
166 	};
167 	token_t *id_tok = NULL;
168 	boolean_t kern_events_allowed = FALSE;
169 	char *signing_id = NULL;
170 	char process_name[MAXCOMLEN + 1] = {};
171 	int signer_type = 0;
172 
173 	error = suser(kauth_cred_get(), &p->p_acflag);
174 	if (error) {
175 		/*
176 		 * If a process is not running as root but is properly
177 		 * entitled, allow it to audit non-kernel events only.
178 		 */
179 		if (!IOCurrentTaskHasEntitlement(AU_AUDIT_USER_ENTITLEMENT)) {
180 			goto free_out;
181 		}
182 	} else {
183 		kern_events_allowed = TRUE;
184 	}
185 
186 	mtx_lock(&audit_mtx);
187 	max_record_length = MIN(audit_qctrl.aq_bufsz, MAX_AUDIT_RECORD_SIZE);
188 	mtx_unlock(&audit_mtx);
189 
190 	if (IOCurrentTaskHasEntitlement(AU_CLASS_RESERVED_ENTITLEMENT)) {
191 		/* Entitled tasks are trusted to add appropriate identity info */
192 		add_identity_token = 0;
193 	} else {
194 		/*
195 		 * If the caller is unentitled, an identity token will be added and
196 		 * the space must be accounted for
197 		 */
198 		max_record_length -= MAX_AUDIT_IDENTITY_SIZE;
199 	}
200 
201 	if ((uap->length <= 0) || (uap->length > max_record_length)) {
202 		error = EINVAL;
203 		goto free_out;
204 	}
205 
206 	ar = currecord();
207 
208 	/*
209 	 * If there's no current audit record (audit() itself not audited)
210 	 * commit the user audit record.
211 	 */
212 	if (ar == NULL) {
213 		uthr = curthread();
214 		if (uthr == NULL) {
215 			/* can this happen? */
216 			error = ENOTSUP;
217 			goto free_out;
218 		}
219 
220 		/*
221 		 * This is not very efficient; we're required to allocate a
222 		 * complete kernel audit record just so the user record can
223 		 * tag along.
224 		 */
225 		uthr->uu_ar = audit_new(AUE_NULL, p, uthr);
226 		if (uthr->uu_ar == NULL) {
227 			error = ENOTSUP;
228 			goto free_out;
229 		}
230 		ar = uthr->uu_ar;
231 	}
232 
233 	rec = kalloc_data(uap->length, Z_WAITOK);
234 	if (!rec) {
235 		error = ENOMEM;
236 		goto free_out;
237 	}
238 
239 	error = copyin(uap->record, rec, uap->length);
240 	if (error) {
241 		goto free_out;
242 	}
243 
244 #if CONFIG_MACF
245 	error = mac_system_check_audit(kauth_cred_get(), rec, uap->length);
246 	if (error) {
247 		goto free_out;
248 	}
249 #endif
250 
251 	/* Verify the record. */
252 	if (bsm_rec_verify(rec, uap->length, kern_events_allowed) == 0) {
253 		error = EINVAL;
254 		goto free_out;
255 	}
256 
257 	if (add_identity_token) {
258 		struct hdr_tok_partial *hdr;
259 		struct trl_tok_partial *trl;
260 		int bytes_copied = 0;
261 
262 		/* Create a new identity token for this buffer */
263 		audit_identity_info_construct(&id_info);
264 		id_tok = au_to_identity(id_info.signer_type, id_info.signing_id,
265 		    id_info.signing_id_trunc, id_info.team_id, id_info.team_id_trunc,
266 		    id_info.cdhash, id_info.cdhash_len);
267 		if (!id_tok) {
268 			error = ENOMEM;
269 			goto free_out;
270 		}
271 
272 		/* Splice the record together using a new buffer */
273 		full_rec = kalloc_data(uap->length + id_tok->len, Z_WAITOK);
274 		if (!full_rec) {
275 			error = ENOMEM;
276 			goto free_out;
277 		}
278 
279 		signing_id = id_info.signing_id;
280 		signer_type = id_info.signer_type;
281 
282 		/* Copy the original buffer up to but not including the trailer */
283 		memcpy(full_rec, rec, uap->length - AUDIT_TRAILER_SIZE);
284 		bytes_copied = uap->length - AUDIT_TRAILER_SIZE;
285 
286 		/* Copy the identity token */
287 		memcpy((void *)((uintptr_t)full_rec + bytes_copied), id_tok->t_data, id_tok->len);
288 		bytes_copied += id_tok->len;
289 
290 		/* Copy the old trailer */
291 		memcpy((void *)((uintptr_t)full_rec + bytes_copied),
292 		    (const void *)((uintptr_t)rec + (uap->length - AUDIT_TRAILER_SIZE)),
293 		    AUDIT_TRAILER_SIZE);
294 		bytes_copied += AUDIT_TRAILER_SIZE;
295 
296 		/* Fix the record size stored in the header token */
297 		hdr = (struct hdr_tok_partial*)full_rec;
298 		hdr->len = htonl(bytes_copied);
299 
300 		/* Fix the record size stored in the trailer token */
301 		trl = (struct trl_tok_partial*)
302 		    ((uintptr_t)full_rec + bytes_copied - AUDIT_TRAILER_SIZE);
303 		trl->len = htonl(bytes_copied);
304 
305 		udata = full_rec;
306 		ulen = bytes_copied;
307 	} else {
308 		udata = rec;
309 		ulen = uap->length;
310 	}
311 
312 	/*
313 	 * Attach the user audit record to the kernel audit record.  Because
314 	 * this system call is an auditable event, we will write the user
315 	 * record along with the record for this audit event.
316 	 *
317 	 * XXXAUDIT: KASSERT appropriate starting values of k_udata, k_ulen,
318 	 * k_ar_commit & AR_COMMIT_USER?
319 	 */
320 	ar->k_udata = udata;
321 	ar->k_ulen  = ulen;
322 	ar->k_ar_commit |= AR_COMMIT_USER;
323 
324 	/*
325 	 * Currently we assume that all preselection has been performed in
326 	 * userspace.  We unconditionally set these masks so that the records
327 	 * get committed both to the trail and pipe.  In the future we will
328 	 * want to setup kernel based preselection.
329 	 */
330 	ar->k_ar_commit |= (AR_PRESELECT_USER_TRAIL | AR_PRESELECT_USER_PIPE);
331 
332 	// Send data for analytics for non-platform binaries only
333 	if (signer_type == 0 && add_identity_token) {
334 		proc_name(proc_pid(p), process_name, sizeof(process_name));
335 		(void)audit_send_analytics(signing_id, process_name);
336 	}
337 
338 free_out:
339 	/*
340 	 * If rec was allocated, it must be freed if an identity token was added
341 	 * (since full_rec will be used) OR there was an error (since nothing
342 	 * will be attached to the kernel structure).
343 	 */
344 	if (rec && (add_identity_token || error)) {
345 		kfree_data_addr(rec);
346 	}
347 
348 	/* Only free full_rec if an error occurred */
349 	if (full_rec && error) {
350 		kfree_data_addr(full_rec);
351 	}
352 
353 	audit_identity_info_destruct(&id_info);
354 	if (id_tok) {
355 		kfree_data(id_tok->t_data, id_tok->len);
356 		kfree_type(struct au_token, id_tok);
357 	}
358 
359 	return error;
360 }
361 
362 /*
363  *  System call to manipulate auditing.
364  */
365 /* ARGSUSED */
366 int
auditon(proc_t p,struct auditon_args * uap,__unused int32_t * retval)367 auditon(proc_t p, struct auditon_args *uap, __unused int32_t *retval)
368 {
369 	kauth_cred_t scred;
370 	int error = 0;
371 	union auditon_udata udata;
372 	proc_t tp = PROC_NULL;
373 	struct auditinfo_addr aia;
374 
375 	AUDIT_ARG(cmd, uap->cmd);
376 
377 #if CONFIG_MACF
378 	error = mac_system_check_auditon(kauth_cred_get(), uap->cmd);
379 	if (error) {
380 		return error;
381 	}
382 #endif
383 
384 	if ((uap->length <= 0) || (uap->length >
385 	    (int)sizeof(union auditon_udata))) {
386 		return EINVAL;
387 	}
388 
389 	memset((void *)&udata, 0, sizeof(udata));
390 
391 	/*
392 	 * Some of the GET commands use the arguments too.
393 	 */
394 	switch (uap->cmd) {
395 	case A_SETPOLICY:
396 	case A_OLDSETPOLICY:
397 	case A_SETKMASK:
398 	case A_SETQCTRL:
399 	case A_OLDSETQCTRL:
400 	case A_SETSTAT:
401 	case A_SETUMASK:
402 	case A_SETSMASK:
403 	case A_SETCOND:
404 	case A_OLDSETCOND:
405 	case A_SETCLASS:
406 	case A_SETPMASK:
407 	case A_SETFSIZE:
408 	case A_SETKAUDIT:
409 	case A_GETCLASS:
410 	case A_GETPINFO:
411 	case A_GETPINFO_ADDR:
412 	case A_SENDTRIGGER:
413 	case A_GETSINFO_ADDR:
414 	case A_GETSFLAGS:
415 	case A_SETSFLAGS:
416 	case A_SETCTLMODE:
417 	case A_SETEXPAFTER:
418 		error = copyin(uap->data, (void *)&udata, uap->length);
419 		if (error) {
420 			return error;
421 		}
422 		AUDIT_ARG(auditon, &udata);
423 		AUDIT_ARG(len, uap->length);
424 		break;
425 	}
426 
427 	/* Check appropriate privilege. */
428 	switch (uap->cmd) {
429 	/*
430 	 * A_GETSINFO doesn't require priviledge but only superuser
431 	 * gets to see the audit masks.
432 	 */
433 	case A_GETSINFO_ADDR:
434 		if ((sizeof(udata.au_kau_info) != uap->length) ||
435 		    (audit_session_lookup(udata.au_kau_info.ai_asid,
436 		    &udata.au_kau_info) != 0)) {
437 			error = EINVAL;
438 		} else if (!kauth_cred_issuser(kauth_cred_get())) {
439 			udata.au_kau_info.ai_mask.am_success = ~0;
440 			udata.au_kau_info.ai_mask.am_failure = ~0;
441 		}
442 		break;
443 	case A_GETSFLAGS:
444 	case A_SETSFLAGS:
445 		/* Getting one's own audit session flags requires no
446 		 * privilege.  Setting the flags is subject to access
447 		 * control implemented in audit_session_setaia().
448 		 */
449 		break;
450 	case A_SETCTLMODE:
451 	case A_SETEXPAFTER:
452 		if (!IOCurrentTaskHasEntitlement(AU_CLASS_RESERVED_ENTITLEMENT)) {
453 			error = EPERM;
454 		}
455 		break;
456 	default:
457 		error = suser(kauth_cred_get(), &p->p_acflag);
458 		break;
459 	}
460 	if (error) {
461 		return error;
462 	}
463 
464 	/*
465 	 * If the audit subsytem is in external control mode, additional
466 	 * privilege checks are required for a subset of auditon commands
467 	 */
468 	if (audit_ctl_mode == AUDIT_CTLMODE_EXTERNAL) {
469 		switch (uap->cmd) {
470 		case A_SETCOND:
471 		case A_SETFSIZE:
472 		case A_SETPOLICY:
473 		case A_SETQCTRL:
474 			if (!IOCurrentTaskHasEntitlement(AU_CLASS_RESERVED_ENTITLEMENT)) {
475 				error = EPERM;
476 			}
477 			break;
478 		}
479 		if (error) {
480 			return error;
481 		}
482 	}
483 
484 	/*
485 	 * XXX Need to implement these commands by accessing the global
486 	 * values associated with the commands.
487 	 */
488 	switch (uap->cmd) {
489 	case A_OLDGETPOLICY:
490 	case A_GETPOLICY:
491 		if (sizeof(udata.au_policy64) == uap->length) {
492 			mtx_lock(&audit_mtx);
493 			if (!audit_fail_stop) {
494 				udata.au_policy64 |= AUDIT_CNT;
495 			}
496 			if (audit_panic_on_write_fail) {
497 				udata.au_policy64 |= AUDIT_AHLT;
498 			}
499 			if (audit_argv) {
500 				udata.au_policy64 |= AUDIT_ARGV;
501 			}
502 			if (audit_arge) {
503 				udata.au_policy64 |= AUDIT_ARGE;
504 			}
505 			mtx_unlock(&audit_mtx);
506 			break;
507 		}
508 		if (sizeof(udata.au_policy) != uap->length) {
509 			return EINVAL;
510 		}
511 		mtx_lock(&audit_mtx);
512 		if (!audit_fail_stop) {
513 			udata.au_policy |= AUDIT_CNT;
514 		}
515 		if (audit_panic_on_write_fail) {
516 			udata.au_policy |= AUDIT_AHLT;
517 		}
518 		if (audit_argv) {
519 			udata.au_policy |= AUDIT_ARGV;
520 		}
521 		if (audit_arge) {
522 			udata.au_policy |= AUDIT_ARGE;
523 		}
524 		mtx_unlock(&audit_mtx);
525 		break;
526 
527 	case A_OLDSETPOLICY:
528 	case A_SETPOLICY:
529 		if (sizeof(udata.au_policy64) == uap->length) {
530 			if (udata.au_policy64 & ~(AUDIT_CNT | AUDIT_AHLT |
531 			    AUDIT_ARGV | AUDIT_ARGE)) {
532 				return EINVAL;
533 			}
534 			mtx_lock(&audit_mtx);
535 			audit_fail_stop = ((udata.au_policy64 & AUDIT_CNT) ==
536 			    0);
537 			audit_panic_on_write_fail = (udata.au_policy64 &
538 			    AUDIT_AHLT);
539 			audit_argv = (udata.au_policy64 & AUDIT_ARGV);
540 			audit_arge = (udata.au_policy64 & AUDIT_ARGE);
541 			mtx_unlock(&audit_mtx);
542 			break;
543 		}
544 		if ((sizeof(udata.au_policy) != uap->length) ||
545 		    (udata.au_policy & ~(AUDIT_CNT | AUDIT_AHLT | AUDIT_ARGV |
546 		    AUDIT_ARGE))) {
547 			return EINVAL;
548 		}
549 		/*
550 		 * XXX - Need to wake up waiters if the policy relaxes?
551 		 */
552 		mtx_lock(&audit_mtx);
553 		audit_fail_stop = ((udata.au_policy & AUDIT_CNT) == 0);
554 		audit_panic_on_write_fail = (udata.au_policy & AUDIT_AHLT);
555 		audit_argv = (udata.au_policy & AUDIT_ARGV);
556 		audit_arge = (udata.au_policy & AUDIT_ARGE);
557 		mtx_unlock(&audit_mtx);
558 		break;
559 
560 	case A_GETKMASK:
561 		if (sizeof(udata.au_mask) != uap->length) {
562 			return EINVAL;
563 		}
564 		mtx_lock(&audit_mtx);
565 		udata.au_mask = audit_nae_mask;
566 		mtx_unlock(&audit_mtx);
567 		break;
568 
569 	case A_SETKMASK:
570 		if (sizeof(udata.au_mask) != uap->length) {
571 			return EINVAL;
572 		}
573 		mtx_lock(&audit_mtx);
574 		audit_nae_mask = udata.au_mask;
575 		AUDIT_CHECK_IF_KEVENTS_MASK(audit_nae_mask);
576 		mtx_unlock(&audit_mtx);
577 		break;
578 
579 	case A_OLDGETQCTRL:
580 	case A_GETQCTRL:
581 		if (sizeof(udata.au_qctrl64) == uap->length) {
582 			mtx_lock(&audit_mtx);
583 			udata.au_qctrl64.aq64_hiwater =
584 			    (u_int64_t)audit_qctrl.aq_hiwater;
585 			udata.au_qctrl64.aq64_lowater =
586 			    (u_int64_t)audit_qctrl.aq_lowater;
587 			udata.au_qctrl64.aq64_bufsz =
588 			    (u_int64_t)audit_qctrl.aq_bufsz;
589 			udata.au_qctrl64.aq64_delay =
590 			    (u_int64_t)audit_qctrl.aq_delay;
591 			udata.au_qctrl64.aq64_minfree =
592 			    (int64_t)audit_qctrl.aq_minfree;
593 			mtx_unlock(&audit_mtx);
594 			break;
595 		}
596 		if (sizeof(udata.au_qctrl) != uap->length) {
597 			return EINVAL;
598 		}
599 		mtx_lock(&audit_mtx);
600 		udata.au_qctrl = audit_qctrl;
601 		mtx_unlock(&audit_mtx);
602 		break;
603 
604 	case A_OLDSETQCTRL:
605 	case A_SETQCTRL:
606 		if (sizeof(udata.au_qctrl64) == uap->length) {
607 			if ((udata.au_qctrl64.aq64_hiwater > AQ_MAXHIGH) ||
608 			    (udata.au_qctrl64.aq64_lowater >=
609 			    udata.au_qctrl64.aq64_hiwater) ||
610 			    (udata.au_qctrl64.aq64_bufsz > AQ_MAXBUFSZ) ||
611 			    (udata.au_qctrl64.aq64_minfree < 0) ||
612 			    (udata.au_qctrl64.aq64_minfree > 100)) {
613 				return EINVAL;
614 			}
615 			mtx_lock(&audit_mtx);
616 			audit_qctrl.aq_hiwater =
617 			    (int)udata.au_qctrl64.aq64_hiwater;
618 			audit_qctrl.aq_lowater =
619 			    (int)udata.au_qctrl64.aq64_lowater;
620 			audit_qctrl.aq_bufsz =
621 			    (int)udata.au_qctrl64.aq64_bufsz;
622 			audit_qctrl.aq_minfree =
623 			    (int)udata.au_qctrl64.aq64_minfree;
624 			audit_qctrl.aq_delay = -1;  /* Not used. */
625 			mtx_unlock(&audit_mtx);
626 			break;
627 		}
628 		if ((sizeof(udata.au_qctrl) != uap->length) ||
629 		    (udata.au_qctrl.aq_hiwater > AQ_MAXHIGH) ||
630 		    (udata.au_qctrl.aq_lowater >= udata.au_qctrl.aq_hiwater) ||
631 		    (udata.au_qctrl.aq_bufsz > AQ_MAXBUFSZ) ||
632 		    (udata.au_qctrl.aq_minfree < 0) ||
633 		    (udata.au_qctrl.aq_minfree > 100)) {
634 			return EINVAL;
635 		}
636 
637 		mtx_lock(&audit_mtx);
638 		audit_qctrl = udata.au_qctrl;
639 		/* XXX The queue delay value isn't used with the kernel. */
640 		audit_qctrl.aq_delay = -1;
641 		mtx_unlock(&audit_mtx);
642 		break;
643 
644 	case A_GETCWD:
645 		return ENOSYS;
646 
647 	case A_GETCAR:
648 		return ENOSYS;
649 
650 	case A_GETSTAT:
651 		return ENOSYS;
652 
653 	case A_SETSTAT:
654 		return ENOSYS;
655 
656 	case A_SETUMASK:
657 		return ENOSYS;
658 
659 	case A_SETSMASK:
660 		return ENOSYS;
661 
662 	case A_OLDGETCOND:
663 	case A_GETCOND:
664 		if (sizeof(udata.au_cond64) == uap->length) {
665 			mtx_lock(&audit_mtx);
666 			if (audit_enabled && !audit_suspended) {
667 				udata.au_cond64 = AUC_AUDITING;
668 			} else {
669 				udata.au_cond64 = AUC_NOAUDIT;
670 			}
671 			mtx_unlock(&audit_mtx);
672 			break;
673 		}
674 		if (sizeof(udata.au_cond) != uap->length) {
675 			return EINVAL;
676 		}
677 		mtx_lock(&audit_mtx);
678 		if (audit_enabled && !audit_suspended) {
679 			udata.au_cond = AUC_AUDITING;
680 		} else {
681 			udata.au_cond = AUC_NOAUDIT;
682 		}
683 		mtx_unlock(&audit_mtx);
684 		break;
685 
686 	case A_OLDSETCOND:
687 	case A_SETCOND:
688 		if (sizeof(udata.au_cond64) == uap->length) {
689 			mtx_lock(&audit_mtx);
690 			if (udata.au_cond64 == AUC_NOAUDIT) {
691 				audit_suspended = 1;
692 			}
693 			if (udata.au_cond64 == AUC_AUDITING) {
694 				audit_suspended = 0;
695 			}
696 			if (udata.au_cond64 == AUC_DISABLED) {
697 				audit_suspended = 1;
698 				mtx_unlock(&audit_mtx);
699 				audit_shutdown();
700 				break;
701 			}
702 			mtx_unlock(&audit_mtx);
703 			break;
704 		}
705 		if (sizeof(udata.au_cond) != uap->length) {
706 			return EINVAL;
707 		}
708 		mtx_lock(&audit_mtx);
709 		if (udata.au_cond == AUC_NOAUDIT) {
710 			audit_suspended = 1;
711 		}
712 		if (udata.au_cond == AUC_AUDITING) {
713 			audit_suspended = 0;
714 		}
715 		if (udata.au_cond == AUC_DISABLED) {
716 			audit_suspended = 1;
717 			mtx_unlock(&audit_mtx);
718 			audit_shutdown();
719 			break;
720 		}
721 		mtx_unlock(&audit_mtx);
722 		break;
723 
724 	case A_GETCLASS:
725 		if (sizeof(udata.au_evclass) != uap->length) {
726 			return EINVAL;
727 		}
728 		udata.au_evclass.ec_class = au_event_class(
729 			udata.au_evclass.ec_number);
730 		break;
731 
732 	case A_SETCLASS:
733 		if (sizeof(udata.au_evclass) != uap->length) {
734 			return EINVAL;
735 		}
736 		au_evclassmap_insert(udata.au_evclass.ec_number,
737 		    udata.au_evclass.ec_class);
738 		break;
739 
740 	case A_GETPINFO:
741 		if ((sizeof(udata.au_aupinfo) != uap->length) ||
742 		    IS_NOT_VALID_PID(udata.au_aupinfo.ap_pid)) {
743 			return EINVAL;
744 		}
745 		if ((tp = proc_find(udata.au_aupinfo.ap_pid)) == NULL) {
746 			return ESRCH;
747 		}
748 
749 		scred = kauth_cred_proc_ref(tp);
750 		if (scred->cr_audit.as_aia_p->ai_termid.at_type == AU_IPv6) {
751 			kauth_cred_unref(&scred);
752 			proc_rele(tp);
753 			return EINVAL;
754 		}
755 
756 		udata.au_aupinfo.ap_auid =
757 		    scred->cr_audit.as_aia_p->ai_auid;
758 		udata.au_aupinfo.ap_mask.am_success =
759 		    scred->cr_audit.as_mask.am_success;
760 		udata.au_aupinfo.ap_mask.am_failure =
761 		    scred->cr_audit.as_mask.am_failure;
762 		udata.au_aupinfo.ap_termid.machine =
763 		    scred->cr_audit.as_aia_p->ai_termid.at_addr[0];
764 		udata.au_aupinfo.ap_termid.port =
765 		    scred->cr_audit.as_aia_p->ai_termid.at_port;
766 		udata.au_aupinfo.ap_asid =
767 		    scred->cr_audit.as_aia_p->ai_asid;
768 		kauth_cred_unref(&scred);
769 		proc_rele(tp);
770 		tp = PROC_NULL;
771 		break;
772 
773 	case A_SETPMASK:
774 		if ((sizeof(udata.au_aupinfo) != uap->length) ||
775 		    IS_NOT_VALID_PID(udata.au_aupinfo.ap_pid)) {
776 			return EINVAL;
777 		}
778 		if ((tp = proc_find(udata.au_aupinfo.ap_pid)) == NULL) {
779 			return ESRCH;
780 		}
781 		scred = kauth_cred_proc_ref(tp);
782 		bcopy(scred->cr_audit.as_aia_p, &aia, sizeof(aia));
783 		kauth_cred_unref(&scred);
784 		aia.ai_mask.am_success =
785 		    udata.au_aupinfo.ap_mask.am_success;
786 		aia.ai_mask.am_failure =
787 		    udata.au_aupinfo.ap_mask.am_failure;
788 		AUDIT_CHECK_IF_KEVENTS_MASK(aia.ai_mask);
789 		error = audit_session_setaia(tp, &aia);
790 		proc_rele(tp);
791 		tp = PROC_NULL;
792 		if (error) {
793 			return error;
794 		}
795 		break;
796 
797 	case A_SETFSIZE:
798 		if ((sizeof(udata.au_fstat) != uap->length) ||
799 		    ((udata.au_fstat.af_filesz != 0) &&
800 		    (udata.au_fstat.af_filesz < MIN_AUDIT_FILE_SIZE))) {
801 			return EINVAL;
802 		}
803 		mtx_lock(&audit_mtx);
804 		audit_fstat.af_filesz = udata.au_fstat.af_filesz;
805 		mtx_unlock(&audit_mtx);
806 		break;
807 
808 	case A_GETFSIZE:
809 		if (sizeof(udata.au_fstat) != uap->length) {
810 			return EINVAL;
811 		}
812 		mtx_lock(&audit_mtx);
813 		udata.au_fstat.af_filesz = audit_fstat.af_filesz;
814 		udata.au_fstat.af_currsz = audit_fstat.af_currsz;
815 		mtx_unlock(&audit_mtx);
816 		break;
817 
818 	case A_GETPINFO_ADDR:
819 		if ((sizeof(udata.au_aupinfo_addr) != uap->length) ||
820 		    IS_NOT_VALID_PID(udata.au_aupinfo_addr.ap_pid)) {
821 			return EINVAL;
822 		}
823 		if ((tp = proc_find(udata.au_aupinfo.ap_pid)) == NULL) {
824 			return ESRCH;
825 		}
826 		WARN_IF_AINFO_ADDR_CHANGED(uap->length,
827 		    sizeof(auditpinfo_addr_t), "auditon(A_GETPINFO_ADDR,...)",
828 		    "auditpinfo_addr_t");
829 		scred = kauth_cred_proc_ref(tp);
830 		udata.au_aupinfo_addr.ap_auid =
831 		    scred->cr_audit.as_aia_p->ai_auid;
832 		udata.au_aupinfo_addr.ap_asid =
833 		    scred->cr_audit.as_aia_p->ai_asid;
834 		udata.au_aupinfo_addr.ap_mask.am_success =
835 		    scred->cr_audit.as_mask.am_success;
836 		udata.au_aupinfo_addr.ap_mask.am_failure =
837 		    scred->cr_audit.as_mask.am_failure;
838 		bcopy(&scred->cr_audit.as_aia_p->ai_termid,
839 		    &udata.au_aupinfo_addr.ap_termid,
840 		    sizeof(au_tid_addr_t));
841 		udata.au_aupinfo_addr.ap_flags =
842 		    scred->cr_audit.as_aia_p->ai_flags;
843 		kauth_cred_unref(&scred);
844 		proc_rele(tp);
845 		tp = PROC_NULL;
846 		break;
847 
848 	case A_GETKAUDIT:
849 		if (sizeof(udata.au_kau_info) != uap->length) {
850 			return EINVAL;
851 		}
852 		audit_get_kinfo(&udata.au_kau_info);
853 		break;
854 
855 	case A_SETKAUDIT:
856 		if ((sizeof(udata.au_kau_info) != uap->length) ||
857 		    (udata.au_kau_info.ai_termid.at_type != AU_IPv4 &&
858 		    udata.au_kau_info.ai_termid.at_type != AU_IPv6)) {
859 			return EINVAL;
860 		}
861 		audit_set_kinfo(&udata.au_kau_info);
862 		break;
863 
864 	case A_SENDTRIGGER:
865 		if ((sizeof(udata.au_trigger) != uap->length) ||
866 		    (udata.au_trigger < AUDIT_TRIGGER_MIN) ||
867 		    (udata.au_trigger > AUDIT_TRIGGER_MAX)) {
868 			return EINVAL;
869 		}
870 		return audit_send_trigger(udata.au_trigger);
871 
872 	case A_GETSINFO_ADDR:
873 		/* Handled above before switch(). */
874 		break;
875 
876 	case A_GETSFLAGS:
877 		if (sizeof(udata.au_flags) != uap->length) {
878 			return EINVAL;
879 		}
880 		bcopy(&(kauth_cred_get()->cr_audit.as_aia_p->ai_flags),
881 		    &udata.au_flags, sizeof(udata.au_flags));
882 		break;
883 
884 	case A_SETSFLAGS:
885 		if (sizeof(udata.au_flags) != uap->length) {
886 			return EINVAL;
887 		}
888 		scred = kauth_cred_get();
889 		bcopy(scred->cr_audit.as_aia_p, &aia, sizeof(aia));
890 		bcopy(&scred->cr_audit.as_mask, &aia.ai_mask, sizeof(au_mask_t));
891 		aia.ai_flags = udata.au_flags;
892 		error = audit_session_setaia(p, &aia);
893 		if (error) {
894 			return error;
895 		}
896 		break;
897 
898 	case A_GETCTLMODE:
899 		if (sizeof(udata.au_ctl_mode) != uap->length) {
900 			return EINVAL;
901 		}
902 		mtx_lock(&audit_mtx);
903 		udata.au_ctl_mode = audit_ctl_mode;
904 		mtx_unlock(&audit_mtx);
905 		break;
906 
907 	case A_SETCTLMODE:
908 		if (sizeof(udata.au_ctl_mode) != uap->length) {
909 			return EINVAL;
910 		}
911 
912 		mtx_lock(&audit_mtx);
913 
914 		if (udata.au_ctl_mode == AUDIT_CTLMODE_NORMAL) {
915 			audit_ctl_mode = AUDIT_CTLMODE_NORMAL;
916 		} else if (udata.au_ctl_mode == AUDIT_CTLMODE_EXTERNAL) {
917 			audit_ctl_mode = AUDIT_CTLMODE_EXTERNAL;
918 		} else {
919 			mtx_unlock(&audit_mtx);
920 			return EINVAL;
921 		}
922 
923 		mtx_unlock(&audit_mtx);
924 		break;
925 
926 	case A_GETEXPAFTER:
927 		if (sizeof(udata.au_expire_after) != uap->length) {
928 			return EINVAL;
929 		}
930 		mtx_lock(&audit_mtx);
931 		udata.au_expire_after.age = audit_expire_after.age;
932 		udata.au_expire_after.size = audit_expire_after.size;
933 		udata.au_expire_after.op_type = audit_expire_after.op_type;
934 		mtx_unlock(&audit_mtx);
935 		break;
936 
937 	case A_SETEXPAFTER:
938 		if (sizeof(udata.au_expire_after) != uap->length) {
939 			return EINVAL;
940 		}
941 		mtx_lock(&audit_mtx);
942 		audit_expire_after.age = udata.au_expire_after.age;
943 		audit_expire_after.size = udata.au_expire_after.size;
944 		audit_expire_after.op_type = udata.au_expire_after.op_type;
945 		mtx_unlock(&audit_mtx);
946 		break;
947 
948 	default:
949 		return EINVAL;
950 	}
951 
952 	/*
953 	 * Copy data back to userspace for the GET comands.
954 	 */
955 	switch (uap->cmd) {
956 	case A_GETPOLICY:
957 	case A_OLDGETPOLICY:
958 	case A_GETKMASK:
959 	case A_GETQCTRL:
960 	case A_OLDGETQCTRL:
961 	case A_GETCWD:
962 	case A_GETCAR:
963 	case A_GETSTAT:
964 	case A_GETCOND:
965 	case A_OLDGETCOND:
966 	case A_GETCLASS:
967 	case A_GETPINFO:
968 	case A_GETFSIZE:
969 	case A_GETPINFO_ADDR:
970 	case A_GETKAUDIT:
971 	case A_GETSINFO_ADDR:
972 	case A_GETSFLAGS:
973 	case A_GETCTLMODE:
974 	case A_GETEXPAFTER:
975 		error = copyout((void *)&udata, uap->data, uap->length);
976 		if (error) {
977 			return ENOSYS;
978 		}
979 		break;
980 	}
981 
982 	return 0;
983 }
984 
985 /*
986  * System calls to manage the user audit information.
987  */
988 /* ARGSUSED */
989 int
getauid(proc_t p,struct getauid_args * uap,__unused int32_t * retval)990 getauid(proc_t p, struct getauid_args *uap, __unused int32_t *retval)
991 {
992 	au_id_t id;
993 	int error;
994 	kauth_cred_t scred;
995 
996 #if CONFIG_MACF
997 	error = mac_proc_check_getauid(p);
998 	if (error) {
999 		return error;
1000 	}
1001 #endif
1002 	scred = kauth_cred_proc_ref(p);
1003 	id = scred->cr_audit.as_aia_p->ai_auid;
1004 	kauth_cred_unref(&scred);
1005 
1006 	error = copyout((void *)&id, uap->auid, sizeof(id));
1007 	if (error) {
1008 		return error;
1009 	}
1010 
1011 	return 0;
1012 }
1013 
1014 /* ARGSUSED */
1015 int
setauid(proc_t p,struct setauid_args * uap,__unused int32_t * retval)1016 setauid(proc_t p, struct setauid_args *uap, __unused int32_t *retval)
1017 {
1018 	int error;
1019 	au_id_t id;
1020 	kauth_cred_t scred;
1021 	struct auditinfo_addr aia;
1022 
1023 	error = copyin(uap->auid, &id, sizeof(id));
1024 	if (error) {
1025 		return error;
1026 	}
1027 	AUDIT_ARG(auid, id);
1028 
1029 #if CONFIG_MACF
1030 	error = mac_proc_check_setauid(p, id);
1031 	if (error) {
1032 		return error;
1033 	}
1034 #endif
1035 
1036 	scred = kauth_cred_proc_ref(p);
1037 	error = suser(scred, &p->p_acflag);
1038 	if (error) {
1039 		kauth_cred_unref(&scred);
1040 		return error;
1041 	}
1042 
1043 	bcopy(scred->cr_audit.as_aia_p, &aia, sizeof(aia));
1044 	if (aia.ai_asid == AU_DEFAUDITSID) {
1045 		aia.ai_asid = AU_ASSIGN_ASID;
1046 	}
1047 	bcopy(&scred->cr_audit.as_mask, &aia.ai_mask, sizeof(au_mask_t));
1048 	kauth_cred_unref(&scred);
1049 	aia.ai_auid = id;
1050 	error = audit_session_setaia(p, &aia);
1051 
1052 	return error;
1053 }
1054 
1055 static int
getaudit_addr_internal(proc_t p,user_addr_t user_addr,size_t length)1056 getaudit_addr_internal(proc_t p, user_addr_t user_addr, size_t length)
1057 {
1058 	kauth_cred_t scred;
1059 	auditinfo_addr_t aia;
1060 
1061 	scred = kauth_cred_proc_ref(p);
1062 	bcopy(scred->cr_audit.as_aia_p, &aia, sizeof(auditinfo_addr_t));
1063 	/*
1064 	 * Only superuser gets to see the real mask.
1065 	 */
1066 	if (suser(scred, &p->p_acflag)) {
1067 		aia.ai_mask.am_success = ~0;
1068 		aia.ai_mask.am_failure = ~0;
1069 	} else {
1070 		bcopy(&scred->cr_audit.as_mask, &aia.ai_mask, sizeof(au_mask_t));
1071 	}
1072 	kauth_cred_unref(&scred);
1073 
1074 	return copyout(&aia, user_addr, min(sizeof(aia), length));
1075 }
1076 
1077 /* ARGSUSED */
1078 int
getaudit_addr(proc_t p,struct getaudit_addr_args * uap,__unused int32_t * retval)1079 getaudit_addr(proc_t p, struct getaudit_addr_args *uap,
1080     __unused int32_t *retval)
1081 {
1082 #if CONFIG_MACF
1083 	int error = mac_proc_check_getaudit(p);
1084 
1085 	if (error) {
1086 		return error;
1087 	}
1088 #endif /* CONFIG_MACF */
1089 	WARN_IF_AINFO_ADDR_CHANGED(uap->length, sizeof(auditinfo_addr_t),
1090 	    "getaudit_addr(2)", "auditinfo_addr_t");
1091 
1092 	return getaudit_addr_internal(p, uap->auditinfo_addr, uap->length);
1093 }
1094 
1095 /* ARGSUSED */
1096 int
setaudit_addr(proc_t p,struct setaudit_addr_args * uap,__unused int32_t * retval)1097 setaudit_addr(proc_t p, struct setaudit_addr_args *uap,
1098     __unused int32_t *retval)
1099 {
1100 	struct auditinfo_addr aia;
1101 	kauth_cred_t scred;
1102 	int error;
1103 
1104 	bzero(&aia, sizeof(auditinfo_addr_t));
1105 	error = copyin(uap->auditinfo_addr, &aia,
1106 	    min(sizeof(aia), uap->length));
1107 	if (error) {
1108 		return error;
1109 	}
1110 	AUDIT_ARG(auditinfo_addr, &aia);
1111 	if (aia.ai_termid.at_type != AU_IPv6 &&
1112 	    aia.ai_termid.at_type != AU_IPv4) {
1113 		return EINVAL;
1114 	}
1115 	if (aia.ai_asid != AU_ASSIGN_ASID &&
1116 	    (uint32_t)aia.ai_asid > ASSIGNED_ASID_MAX) {
1117 		return EINVAL;
1118 	}
1119 
1120 #if CONFIG_MACF
1121 	error = mac_proc_check_setaudit(p, &aia);
1122 	if (error) {
1123 		return error;
1124 	}
1125 #endif
1126 
1127 	scred = kauth_cred_proc_ref(p);
1128 	error = suser(scred, &p->p_acflag);
1129 	if (error) {
1130 		kauth_cred_unref(&scred);
1131 		return error;
1132 	}
1133 
1134 	WARN_IF_AINFO_ADDR_CHANGED(uap->length, sizeof(auditinfo_addr_t),
1135 	    "setaudit_addr(2)", "auditinfo_addr_t");
1136 	WARN_IF_BAD_ASID(aia.ai_asid, "setaudit_addr(2)");
1137 	kauth_cred_unref(&scred);
1138 
1139 	AUDIT_CHECK_IF_KEVENTS_MASK(aia.ai_mask);
1140 	if (aia.ai_asid == AU_DEFAUDITSID) {
1141 		aia.ai_asid = AU_ASSIGN_ASID;
1142 	}
1143 
1144 	error = audit_session_setaia(p, &aia);
1145 	if (error) {
1146 		return error;
1147 	}
1148 
1149 	/*
1150 	 * If asked to assign an ASID then let the user know what the ASID is
1151 	 * by copying the auditinfo_addr struct back out.
1152 	 */
1153 	if (aia.ai_asid == AU_ASSIGN_ASID) {
1154 		error = getaudit_addr_internal(p, uap->auditinfo_addr,
1155 		    uap->length);
1156 	}
1157 
1158 	return error;
1159 }
1160 
1161 /*
1162  * Syscall to manage audit files.
1163  *
1164  */
1165 /* ARGSUSED */
1166 int
auditctl(proc_t p,struct auditctl_args * uap,__unused int32_t * retval)1167 auditctl(proc_t p, struct auditctl_args *uap, __unused int32_t *retval)
1168 {
1169 	struct nameidata nd;
1170 	kauth_cred_t cred;
1171 	struct vnode *vp;
1172 	int error = 0;
1173 	au_ctlmode_t ctlmode;
1174 
1175 	error = suser(kauth_cred_get(), &p->p_acflag);
1176 	if (error) {
1177 		return error;
1178 	}
1179 
1180 	ctlmode = audit_ctl_mode;
1181 
1182 	/*
1183 	 * Do not allow setting of a path when auditing is in reserved mode
1184 	 */
1185 	if (ctlmode == AUDIT_CTLMODE_EXTERNAL &&
1186 	    !IOCurrentTaskHasEntitlement(AU_AUDITCTL_RESERVED_ENTITLEMENT)) {
1187 		return EPERM;
1188 	}
1189 
1190 	vp = NULL;
1191 	cred = NULL;
1192 
1193 	/*
1194 	 * If a path is specified, open the replacement vnode, perform
1195 	 * validity checks, and grab another reference to the current
1196 	 * credential.
1197 	 *
1198 	 * XXX Changes API slightly.  NULL path no longer disables audit but
1199 	 * returns EINVAL.
1200 	 */
1201 	if (uap->path == USER_ADDR_NULL) {
1202 		return EINVAL;
1203 	}
1204 
1205 	NDINIT(&nd, LOOKUP, OP_OPEN, FOLLOW | LOCKLEAF | AUDITVNPATH1,
1206 	    (IS_64BIT_PROCESS(p) ? UIO_USERSPACE64 :
1207 	    UIO_USERSPACE32), uap->path, vfs_context_current());
1208 	error = vn_open(&nd, AUDIT_OPEN_FLAGS, 0);
1209 	if (error) {
1210 		return error;
1211 	}
1212 	vp = nd.ni_vp;
1213 #if CONFIG_MACF
1214 	/*
1215 	 * Accessibility of the vnode was determined in vn_open; the
1216 	 * mac_system_check_auditctl should only determine whether that vnode
1217 	 * is appropriate for storing audit data, or that the caller was
1218 	 * permitted to control the auditing system at all.  For example, a
1219 	 * confidentiality policy may want to ensure that audit files are
1220 	 * always high sensitivity.
1221 	 */
1222 	error = mac_system_check_auditctl(kauth_cred_get(), vp);
1223 	if (error) {
1224 		vn_close(vp, AUDIT_CLOSE_FLAGS, vfs_context_current());
1225 		vnode_put(vp);
1226 		return error;
1227 	}
1228 #endif
1229 	if (vp->v_type != VREG) {
1230 		vn_close(vp, AUDIT_CLOSE_FLAGS, vfs_context_current());
1231 		vnode_put(vp);
1232 		return EINVAL;
1233 	}
1234 	mtx_lock(&audit_mtx);
1235 	/*
1236 	 * XXXAUDIT: Should audit_suspended actually be cleared by
1237 	 * audit_worker?
1238 	 */
1239 	audit_suspended = 0;
1240 	mtx_unlock(&audit_mtx);
1241 
1242 	/*
1243 	 * The following gets unreferenced in audit_rotate_vnode()
1244 	 * after the rotation and it is no longer needed.
1245 	 */
1246 	cred = kauth_cred_get_with_ref();
1247 	audit_rotate_vnode(cred, vp);
1248 	vnode_put(vp);
1249 
1250 	return error;
1251 }
1252 
1253 #else /* !CONFIG_AUDIT */
1254 
1255 int
audit(proc_t p,struct audit_args * uap,int32_t * retval)1256 audit(proc_t p, struct audit_args *uap, int32_t *retval)
1257 {
1258 #pragma unused(p, uap, retval)
1259 
1260 	return ENOSYS;
1261 }
1262 
1263 int
auditon(proc_t p,struct auditon_args * uap,int32_t * retval)1264 auditon(proc_t p, struct auditon_args *uap, int32_t *retval)
1265 {
1266 #pragma unused(p, uap, retval)
1267 
1268 	return ENOSYS;
1269 }
1270 
1271 int
getauid(proc_t p,struct getauid_args * uap,int32_t * retval)1272 getauid(proc_t p, struct getauid_args *uap, int32_t *retval)
1273 {
1274 #pragma unused(p, uap, retval)
1275 
1276 	return ENOSYS;
1277 }
1278 
1279 int
setauid(proc_t p,struct setauid_args * uap,int32_t * retval)1280 setauid(proc_t p, struct setauid_args *uap, int32_t *retval)
1281 {
1282 #pragma unused(p, uap, retval)
1283 
1284 	return ENOSYS;
1285 }
1286 
1287 int
getaudit_addr(proc_t p,struct getaudit_addr_args * uap,int32_t * retval)1288 getaudit_addr(proc_t p, struct getaudit_addr_args *uap, int32_t *retval)
1289 {
1290 #pragma unused(p, uap, retval)
1291 
1292 	return ENOSYS;
1293 }
1294 
1295 int
setaudit_addr(proc_t p,struct setaudit_addr_args * uap,int32_t * retval)1296 setaudit_addr(proc_t p, struct setaudit_addr_args *uap, int32_t *retval)
1297 {
1298 #pragma unused(p, uap, retval)
1299 
1300 	return ENOSYS;
1301 }
1302 
1303 int
auditctl(proc_t p,struct auditctl_args * uap,int32_t * retval)1304 auditctl(proc_t p, struct auditctl_args *uap, int32_t *retval)
1305 {
1306 #pragma unused(p, uap, retval)
1307 
1308 	return ENOSYS;
1309 }
1310 
1311 #endif /* CONFIG_AUDIT */
1312