xref: /freebsd/sys/security/audit/audit_syscalls.c (revision 94942af266ac119ede0ca836f9aa5a5ac0582938)
1 /*
2  * Copyright (c) 1999-2005 Apple Computer, Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1.  Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer.
10  * 2.  Redistributions in binary form must reproduce the above copyright
11  *     notice, this list of conditions and the following disclaimer in the
12  *     documentation and/or other materials provided with the distribution.
13  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14  *     its contributors may be used to endorse or promote products derived
15  *     from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR
21  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
25  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
26  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  *
29  * $FreeBSD$
30  */
31 
32 #include "opt_mac.h"
33 
34 #include <sys/param.h>
35 #include <sys/mount.h>
36 #include <sys/namei.h>
37 #include <sys/priv.h>
38 #include <sys/proc.h>
39 #include <sys/sysproto.h>
40 #include <sys/systm.h>
41 #include <sys/vnode.h>
42 #include <sys/jail.h>
43 
44 #include <bsm/audit.h>
45 #include <bsm/audit_kevents.h>
46 
47 #include <security/audit/audit.h>
48 #include <security/audit/audit_private.h>
49 #include <security/mac/mac_framework.h>
50 
51 #ifdef AUDIT
52 
53 /*
54  * System call to allow a user space application to submit a BSM audit record
55  * to the kernel for inclusion in the audit log. This function does little
56  * verification on the audit record that is submitted.
57  *
58  * XXXAUDIT: Audit preselection for user records does not currently work,
59  * since we pre-select only based on the AUE_audit event type, not the event
60  * type submitted as part of the user audit data.
61  */
62 /* ARGSUSED */
63 int
64 audit(struct thread *td, struct audit_args *uap)
65 {
66 	int error;
67 	void * rec;
68 	struct kaudit_record *ar;
69 
70 	if (jailed(td->td_ucred))
71 		return (ENOSYS);
72 	error = priv_check(td, PRIV_AUDIT_SUBMIT);
73 	if (error)
74 		return (error);
75 
76 	if ((uap->length <= 0) || (uap->length > audit_qctrl.aq_bufsz))
77 		return (EINVAL);
78 
79 	ar = currecord();
80 
81 	/*
82 	 * If there's no current audit record (audit() itself not audited)
83 	 * commit the user audit record.
84 	 */
85 	if (ar == NULL) {
86 
87 		/*
88 		 * This is not very efficient; we're required to allocate a
89 		 * complete kernel audit record just so the user record can
90 		 * tag along.
91 		 *
92 		 * XXXAUDIT: Maybe AUE_AUDIT in the system call context and
93 		 * special pre-select handling?
94 		 */
95 		td->td_ar = audit_new(AUE_NULL, td);
96 		if (td->td_ar == NULL)
97 			return (ENOTSUP);
98 		ar = td->td_ar;
99 	}
100 
101 	if (uap->length > MAX_AUDIT_RECORD_SIZE)
102 		return (EINVAL);
103 
104 	rec = malloc(uap->length, M_AUDITDATA, M_WAITOK);
105 
106 	error = copyin(uap->record, rec, uap->length);
107 	if (error)
108 		goto free_out;
109 
110 	/* Verify the record. */
111 	if (bsm_rec_verify(rec) == 0) {
112 		error = EINVAL;
113 		goto free_out;
114 	}
115 
116 #ifdef MAC
117 	error = mac_check_system_audit(td->td_ucred, rec, uap->length);
118 	if (error)
119 		goto free_out;
120 #endif
121 
122 	/*
123 	 * Attach the user audit record to the kernel audit record. Because
124 	 * this system call is an auditable event, we will write the user
125 	 * record along with the record for this audit event.
126 	 *
127 	 * XXXAUDIT: KASSERT appropriate starting values of k_udata, k_ulen,
128 	 * k_ar_commit & AR_COMMIT_USER?
129 	 */
130 	ar->k_udata = rec;
131 	ar->k_ulen  = uap->length;
132 	ar->k_ar_commit |= AR_COMMIT_USER;
133 
134 	/*
135 	 * Currently we assume that all preselection has been performed in
136 	 * userspace. We unconditionally set these masks so that the records
137 	 * get committed both to the trail and pipe.  In the future we will
138 	 * want to setup kernel based preselection.
139 	 */
140 	ar->k_ar_commit |= (AR_PRESELECT_USER_TRAIL | AR_PRESELECT_USER_PIPE);
141 	return (0);
142 
143 free_out:
144 	/*
145 	 * audit_syscall_exit() will free the audit record on the thread even
146 	 * if we allocated it above.
147 	 */
148 	free(rec, M_AUDITDATA);
149 	return (error);
150 }
151 
152 /*
153  *  System call to manipulate auditing.
154  */
155 /* ARGSUSED */
156 int
157 auditon(struct thread *td, struct auditon_args *uap)
158 {
159 	int error;
160 	union auditon_udata udata;
161 	struct proc *tp;
162 
163 	if (jailed(td->td_ucred))
164 		return (ENOSYS);
165 	AUDIT_ARG(cmd, uap->cmd);
166 
167 #ifdef MAC
168 	error = mac_check_system_auditon(td->td_ucred, uap->cmd);
169 	if (error)
170 		return (error);
171 #endif
172 
173 	error = priv_check(td, PRIV_AUDIT_CONTROL);
174 	if (error)
175 		return (error);
176 
177 	if ((uap->length <= 0) || (uap->length > sizeof(union auditon_udata)))
178 		return (EINVAL);
179 
180 	memset((void *)&udata, 0, sizeof(udata));
181 
182 	/*
183 	 * Some of the GET commands use the arguments too.
184 	 */
185 	switch (uap->cmd) {
186 	case A_SETPOLICY:
187 	case A_SETKMASK:
188 	case A_SETQCTRL:
189 	case A_SETSTAT:
190 	case A_SETUMASK:
191 	case A_SETSMASK:
192 	case A_SETCOND:
193 	case A_SETCLASS:
194 	case A_SETPMASK:
195 	case A_SETFSIZE:
196 	case A_SETKAUDIT:
197 	case A_GETCLASS:
198 	case A_GETPINFO:
199 	case A_GETPINFO_ADDR:
200 	case A_SENDTRIGGER:
201 		error = copyin(uap->data, (void *)&udata, uap->length);
202 		if (error)
203 			return (error);
204 		AUDIT_ARG(auditon, &udata);
205 		break;
206 	}
207 
208 	/*
209 	 * XXXAUDIT: Locking?
210 	 */
211 	switch (uap->cmd) {
212 	case A_GETPOLICY:
213 		if (!audit_fail_stop)
214 			udata.au_policy |= AUDIT_CNT;
215 		if (audit_panic_on_write_fail)
216 			udata.au_policy |= AUDIT_AHLT;
217 		if (audit_argv)
218 			udata.au_policy |= AUDIT_ARGV;
219 		if (audit_arge)
220 			udata.au_policy |= AUDIT_ARGE;
221 		break;
222 
223 	case A_SETPOLICY:
224 		if (udata.au_policy & ~(AUDIT_CNT|AUDIT_AHLT|AUDIT_ARGV|
225 		    AUDIT_ARGE))
226 			return (EINVAL);
227 		/*
228 		 * XXX - Need to wake up waiters if the policy relaxes?
229 		 */
230 		audit_fail_stop = ((udata.au_policy & AUDIT_CNT) == 0);
231 		audit_panic_on_write_fail = (udata.au_policy & AUDIT_AHLT);
232 		audit_argv = (udata.au_policy & AUDIT_ARGV);
233 		audit_arge = (udata.au_policy & AUDIT_ARGE);
234 		break;
235 
236 	case A_GETKMASK:
237 		udata.au_mask = audit_nae_mask;
238 		break;
239 
240 	case A_SETKMASK:
241 		audit_nae_mask = udata.au_mask;
242 		break;
243 
244 	case A_GETQCTRL:
245 		udata.au_qctrl = audit_qctrl;
246 		break;
247 
248 	case A_SETQCTRL:
249 		if ((udata.au_qctrl.aq_hiwater > AQ_MAXHIGH) ||
250 		    (udata.au_qctrl.aq_lowater >= udata.au_qctrl.aq_hiwater) ||
251 		    (udata.au_qctrl.aq_bufsz > AQ_MAXBUFSZ) ||
252 		    (udata.au_qctrl.aq_minfree < 0) ||
253 		    (udata.au_qctrl.aq_minfree > 100))
254 			return (EINVAL);
255 
256 		audit_qctrl = udata.au_qctrl;
257 		/* XXX The queue delay value isn't used with the kernel. */
258 		audit_qctrl.aq_delay = -1;
259 		break;
260 
261 	case A_GETCWD:
262 		return (ENOSYS);
263 		break;
264 
265 	case A_GETCAR:
266 		return (ENOSYS);
267 		break;
268 
269 	case A_GETSTAT:
270 		return (ENOSYS);
271 		break;
272 
273 	case A_SETSTAT:
274 		return (ENOSYS);
275 		break;
276 
277 	case A_SETUMASK:
278 		return (ENOSYS);
279 		break;
280 
281 	case A_SETSMASK:
282 		return (ENOSYS);
283 		break;
284 
285 	case A_GETCOND:
286 		if (audit_enabled && !audit_suspended)
287 			udata.au_cond = AUC_AUDITING;
288 		else
289 			udata.au_cond = AUC_NOAUDIT;
290 		break;
291 
292 	case A_SETCOND:
293 		if (udata.au_cond == AUC_NOAUDIT)
294 			audit_suspended = 1;
295 		if (udata.au_cond == AUC_AUDITING)
296 			audit_suspended = 0;
297 		if (udata.au_cond == AUC_DISABLED) {
298 			audit_suspended = 1;
299 			audit_shutdown(NULL, 0);
300 		}
301 		break;
302 
303 	case A_GETCLASS:
304 		udata.au_evclass.ec_class = au_event_class(
305 		    udata.au_evclass.ec_number);
306 		break;
307 
308 	case A_SETCLASS:
309 		au_evclassmap_insert(udata.au_evclass.ec_number,
310 		    udata.au_evclass.ec_class);
311 		break;
312 
313 	case A_GETPINFO:
314 		if (udata.au_aupinfo.ap_pid < 1)
315 			return (EINVAL);
316 
317 		if ((tp = pfind(udata.au_aupinfo.ap_pid)) == NULL)
318 			return (EINVAL);
319 		if (p_cansee(td, tp) != 0) {
320 			PROC_UNLOCK(tp);
321 			return (EINVAL);
322 		}
323 
324 		if (tp->p_au->ai_termid.at_type == AU_IPv6) {
325 			PROC_UNLOCK(tp);
326 			return (EINVAL);
327 		}
328 		udata.au_aupinfo.ap_auid = tp->p_au->ai_auid;
329 		udata.au_aupinfo.ap_mask.am_success =
330 		    tp->p_au->ai_mask.am_success;
331 		udata.au_aupinfo.ap_mask.am_failure =
332 		    tp->p_au->ai_mask.am_failure;
333 		udata.au_aupinfo.ap_termid.machine =
334 		    tp->p_au->ai_termid.at_addr[0];
335 		udata.au_aupinfo.ap_termid.port =
336 		    (dev_t)tp->p_au->ai_termid.at_port;
337 		udata.au_aupinfo.ap_asid = tp->p_au->ai_asid;
338 		PROC_UNLOCK(tp);
339 		break;
340 
341 	case A_SETPMASK:
342 		if (udata.au_aupinfo.ap_pid < 1)
343 			return (EINVAL);
344 
345 		if ((tp = pfind(udata.au_aupinfo.ap_pid)) == NULL)
346 			return (EINVAL);
347 		if (p_cansee(td, tp) != 0) {
348 			PROC_UNLOCK(tp);
349 			return (EINVAL);
350 		}
351 
352 		tp->p_au->ai_mask.am_success =
353 		    udata.au_aupinfo.ap_mask.am_success;
354 		tp->p_au->ai_mask.am_failure =
355 		    udata.au_aupinfo.ap_mask.am_failure;
356 		PROC_UNLOCK(tp);
357 		break;
358 
359 	case A_SETFSIZE:
360 		if ((udata.au_fstat.af_filesz != 0) &&
361 		   (udata.au_fstat.af_filesz < MIN_AUDIT_FILE_SIZE))
362 			return (EINVAL);
363 		audit_fstat.af_filesz = udata.au_fstat.af_filesz;
364 		break;
365 
366 	case A_GETFSIZE:
367 		udata.au_fstat.af_filesz = audit_fstat.af_filesz;
368 		udata.au_fstat.af_currsz = audit_fstat.af_currsz;
369 		break;
370 
371 	case A_GETPINFO_ADDR:
372 		if (udata.au_aupinfo_addr.ap_pid < 1)
373 			return (EINVAL);
374 		if ((tp = pfind(udata.au_aupinfo_addr.ap_pid)) == NULL)
375 			return (EINVAL);
376 		udata.au_aupinfo_addr.ap_auid = tp->p_au->ai_auid;
377 		udata.au_aupinfo_addr.ap_mask.am_success =
378 		    tp->p_au->ai_mask.am_success;
379 		udata.au_aupinfo_addr.ap_mask.am_failure =
380 		    tp->p_au->ai_mask.am_failure;
381 		udata.au_aupinfo_addr.ap_termid = tp->p_au->ai_termid;
382 		udata.au_aupinfo_addr.ap_asid = tp->p_au->ai_asid;
383 		PROC_UNLOCK(tp);
384 		break;
385 
386 	case A_GETKAUDIT:
387 		return (ENOSYS);
388 		break;
389 
390 	case A_SETKAUDIT:
391 		return (ENOSYS);
392 		break;
393 
394 	case A_SENDTRIGGER:
395 		if ((udata.au_trigger < AUDIT_TRIGGER_MIN) ||
396 		    (udata.au_trigger > AUDIT_TRIGGER_MAX))
397 			return (EINVAL);
398 		return (send_trigger(udata.au_trigger));
399 	}
400 
401 	/*
402 	 * Copy data back to userspace for the GET comands.
403 	 */
404 	switch (uap->cmd) {
405 	case A_GETPOLICY:
406 	case A_GETKMASK:
407 	case A_GETQCTRL:
408 	case A_GETCWD:
409 	case A_GETCAR:
410 	case A_GETSTAT:
411 	case A_GETCOND:
412 	case A_GETCLASS:
413 	case A_GETPINFO:
414 	case A_GETFSIZE:
415 	case A_GETPINFO_ADDR:
416 	case A_GETKAUDIT:
417 		error = copyout((void *)&udata, uap->data, uap->length);
418 		if (error)
419 			return (error);
420 		break;
421 	}
422 
423 	return (0);
424 }
425 
426 /*
427  * System calls to manage the user audit information.
428  */
429 /* ARGSUSED */
430 int
431 getauid(struct thread *td, struct getauid_args *uap)
432 {
433 	int error;
434 	au_id_t id;
435 
436 	if (jailed(td->td_ucred))
437 		return (ENOSYS);
438 	error = priv_check(td, PRIV_AUDIT_GETAUDIT);
439 	if (error)
440 		return (error);
441 
442 	/*
443 	 * XXX: Integer read on static pointer dereference: doesn't need
444 	 * locking?
445 	 */
446 	PROC_LOCK(td->td_proc);
447 	id = td->td_proc->p_au->ai_auid;
448 	PROC_UNLOCK(td->td_proc);
449 	return copyout(&id, uap->auid, sizeof(id));
450 }
451 
452 /* ARGSUSED */
453 int
454 setauid(struct thread *td, struct setauid_args *uap)
455 {
456 	int error;
457 	au_id_t id;
458 
459 	if (jailed(td->td_ucred))
460 		return (ENOSYS);
461 	error = priv_check(td, PRIV_AUDIT_SETAUDIT);
462 	if (error)
463 		return (error);
464 
465 	error = copyin(uap->auid, &id, sizeof(id));
466 	if (error)
467 		return (error);
468 
469 	audit_arg_auid(id);
470 
471 #ifdef MAC
472 	error = mac_check_proc_setauid(td->td_ucred, id);
473 	if (error)
474 		return (error);
475 #endif
476 
477 	/*
478 	 * XXX: Integer write on static pointer dereference: doesn't need
479 	 * locking?
480 	 *
481 	 * XXXAUDIT: Might need locking to serialize audit events in the same
482 	 * order as change events?  Or maybe that's an under-solveable
483 	 * problem.
484 	 *
485 	 * XXXRW: Test privilege while holding the proc lock?
486 	 */
487 	PROC_LOCK(td->td_proc);
488 	td->td_proc->p_au->ai_auid = id;
489 	PROC_UNLOCK(td->td_proc);
490 
491 	return (0);
492 }
493 
494 /*
495  * System calls to get and set process audit information.
496  */
497 /* ARGSUSED */
498 int
499 getaudit(struct thread *td, struct getaudit_args *uap)
500 {
501 	struct auditinfo ai;
502 	int error;
503 
504 	if (jailed(td->td_ucred))
505 		return (ENOSYS);
506 	error = priv_check(td, PRIV_AUDIT_GETAUDIT);
507 	if (error)
508 		return (error);
509 
510 	PROC_LOCK(td->td_proc);
511 	if (td->td_proc->p_au->ai_termid.at_type == AU_IPv6) {
512 		PROC_UNLOCK(td->td_proc);
513 		return (E2BIG);
514 	}
515 	bzero(&ai, sizeof(ai));
516 	ai.ai_auid = td->td_proc->p_au->ai_auid;
517 	ai.ai_mask = td->td_proc->p_au->ai_mask;
518 	ai.ai_asid = td->td_proc->p_au->ai_asid;
519 	ai.ai_termid.machine = td->td_proc->p_au->ai_termid.at_addr[0];
520 	ai.ai_termid.port = td->td_proc->p_au->ai_termid.at_port;
521 	PROC_UNLOCK(td->td_proc);
522 
523 	return (copyout(&ai, uap->auditinfo, sizeof(ai)));
524 }
525 
526 /* ARGSUSED */
527 int
528 setaudit(struct thread *td, struct setaudit_args *uap)
529 {
530 	struct auditinfo ai;
531 	int error;
532 
533 	if (jailed(td->td_ucred))
534 		return (ENOSYS);
535 	error = priv_check(td, PRIV_AUDIT_SETAUDIT);
536 	if (error)
537 		return (error);
538 
539 	error = copyin(uap->auditinfo, &ai, sizeof(ai));
540 	if (error)
541 		return (error);
542 
543 	audit_arg_auditinfo(&ai);
544 
545 #ifdef MAC
546 	error = mac_check_proc_setaudit(td->td_ucred, &ai);
547 	if (error)
548 		return (error);
549 #endif
550 
551 	/*
552 	 * XXXRW: Test privilege while holding the proc lock?
553 	*/
554 	PROC_LOCK(td->td_proc);
555 	bzero(td->td_proc->p_au, sizeof(struct auditinfo_addr));
556 	td->td_proc->p_au->ai_auid = ai.ai_auid;
557 	td->td_proc->p_au->ai_mask = ai.ai_mask;
558 	td->td_proc->p_au->ai_asid = ai.ai_asid;
559 	td->td_proc->p_au->ai_termid.at_addr[0] = ai.ai_termid.machine;
560 	td->td_proc->p_au->ai_termid.at_port = ai.ai_termid.port;
561 	td->td_proc->p_au->ai_termid.at_type = AU_IPv4;
562 	PROC_UNLOCK(td->td_proc);
563 
564 	return (0);
565 }
566 
567 /* ARGSUSED */
568 int
569 getaudit_addr(struct thread *td, struct getaudit_addr_args *uap)
570 {
571 	struct auditinfo_addr aia;
572 	int error;
573 
574 	if (jailed(td->td_ucred))
575 		return (ENOSYS);
576 	error = priv_check(td, PRIV_AUDIT_GETAUDIT);
577 	if (error)
578 		return (error);
579 	if (uap->length < sizeof(aia))
580 		return (EOVERFLOW);
581 	PROC_LOCK(td->td_proc);
582 	aia = *td->td_proc->p_au;
583 	PROC_UNLOCK(td->td_proc);
584 	return (copyout(&aia, uap->auditinfo_addr, sizeof(aia)));
585 }
586 
587 /* ARGSUSED */
588 int
589 setaudit_addr(struct thread *td, struct setaudit_addr_args *uap)
590 {
591 	struct auditinfo_addr aia;
592 	int error;
593 
594 	if (jailed(td->td_ucred))
595 		return (ENOSYS);
596 	error = priv_check(td, PRIV_AUDIT_SETAUDIT);
597 	if (error)
598 		return (error);
599 
600 #ifdef MAC
601 	error = mac_check_proc_setaudit(td->td_ucred, NULL);
602 	if (error)
603 		return (error);
604 #endif
605 	error = copyin(uap->auditinfo_addr, &aia, sizeof(aia));
606 	if (error)
607 		return (error);
608 	PROC_LOCK(td->td_proc);
609 	*td->td_proc->p_au = aia;
610 	PROC_UNLOCK(td->td_proc);
611 	return (error);
612 }
613 
614 /*
615  * Syscall to manage audit files.
616  */
617 /* ARGSUSED */
618 int
619 auditctl(struct thread *td, struct auditctl_args *uap)
620 {
621 	struct nameidata nd;
622 	struct ucred *cred;
623 	struct vnode *vp;
624 	int error = 0;
625 	int flags, vfslocked;
626 
627 	if (jailed(td->td_ucred))
628 		return (ENOSYS);
629 	error = priv_check(td, PRIV_AUDIT_CONTROL);
630 	if (error)
631 		return (error);
632 
633 	vp = NULL;
634 	cred = NULL;
635 
636 	/*
637 	 * If a path is specified, open the replacement vnode, perform
638 	 * validity checks, and grab another reference to the current
639 	 * credential.
640 	 *
641 	 * On Darwin, a NULL path argument is also used to disable audit.
642 	 */
643 	if (uap->path == NULL)
644 		return (EINVAL);
645 
646 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1,
647 	    UIO_USERSPACE, uap->path, td);
648 	flags = AUDIT_OPEN_FLAGS;
649 	error = vn_open(&nd, &flags, 0, -1);
650 	if (error)
651 		return (error);
652 	vfslocked = NDHASGIANT(&nd);
653 	vp = nd.ni_vp;
654 #ifdef MAC
655 	error = mac_check_system_auditctl(td->td_ucred, vp);
656 	VOP_UNLOCK(vp, 0, td);
657 	if (error) {
658 		vn_close(vp, AUDIT_CLOSE_FLAGS, td->td_ucred, td);
659 		VFS_UNLOCK_GIANT(vfslocked);
660 		return (error);
661 	}
662 #else
663 	VOP_UNLOCK(vp, 0, td);
664 #endif
665 	NDFREE(&nd, NDF_ONLY_PNBUF);
666 	if (vp->v_type != VREG) {
667 		vn_close(vp, AUDIT_CLOSE_FLAGS, td->td_ucred, td);
668 		VFS_UNLOCK_GIANT(vfslocked);
669 		return (EINVAL);
670 	}
671 	VFS_UNLOCK_GIANT(vfslocked);
672 	cred = td->td_ucred;
673 	crhold(cred);
674 
675 	/*
676 	 * XXXAUDIT: Should audit_suspended actually be cleared by
677 	 * audit_worker?
678 	 */
679 	audit_suspended = 0;
680 
681 	audit_rotate_vnode(cred, vp);
682 
683 	return (error);
684 }
685 
686 #else /* !AUDIT */
687 
688 int
689 audit(struct thread *td, struct audit_args *uap)
690 {
691 
692 	return (ENOSYS);
693 }
694 
695 int
696 auditon(struct thread *td, struct auditon_args *uap)
697 {
698 
699 	return (ENOSYS);
700 }
701 
702 int
703 getauid(struct thread *td, struct getauid_args *uap)
704 {
705 
706 	return (ENOSYS);
707 }
708 
709 int
710 setauid(struct thread *td, struct setauid_args *uap)
711 {
712 
713 	return (ENOSYS);
714 }
715 
716 int
717 getaudit(struct thread *td, struct getaudit_args *uap)
718 {
719 
720 	return (ENOSYS);
721 }
722 
723 int
724 setaudit(struct thread *td, struct setaudit_args *uap)
725 {
726 
727 	return (ENOSYS);
728 }
729 
730 int
731 getaudit_addr(struct thread *td, struct getaudit_addr_args *uap)
732 {
733 
734 	return (ENOSYS);
735 }
736 
737 int
738 setaudit_addr(struct thread *td, struct setaudit_addr_args *uap)
739 {
740 
741 	return (ENOSYS);
742 }
743 
744 int
745 auditctl(struct thread *td, struct auditctl_args *uap)
746 {
747 
748 	return (ENOSYS);
749 }
750 
751 void
752 audit_proc_init(struct proc *p)
753 {
754 
755 }
756 
757 void
758 audit_proc_fork(struct proc *parent, struct proc *child)
759 {
760 
761 }
762 
763 void
764 audit_proc_free(struct proc *p)
765 {
766 
767 }
768 
769 #endif /* AUDIT */
770