audit_syscalls.c revision 170777
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: head/sys/security/audit/audit_syscalls.c 170777 2007-06-15 15:20:56Z rwatson $
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 */
63int
64audit(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
143free_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 */
156int
157auditon(struct thread *td, struct auditon_args *uap)
158{
159	struct ucred *newcred, *oldcred;
160	int error;
161	union auditon_udata udata;
162	struct proc *tp;
163
164	if (jailed(td->td_ucred))
165		return (ENOSYS);
166	AUDIT_ARG(cmd, uap->cmd);
167
168#ifdef MAC
169	error = mac_check_system_auditon(td->td_ucred, uap->cmd);
170	if (error)
171		return (error);
172#endif
173
174	error = priv_check(td, PRIV_AUDIT_CONTROL);
175	if (error)
176		return (error);
177
178	if ((uap->length <= 0) || (uap->length > sizeof(union auditon_udata)))
179		return (EINVAL);
180
181	memset((void *)&udata, 0, sizeof(udata));
182
183	/*
184	 * Some of the GET commands use the arguments too.
185	 */
186	switch (uap->cmd) {
187	case A_SETPOLICY:
188	case A_SETKMASK:
189	case A_SETQCTRL:
190	case A_SETSTAT:
191	case A_SETUMASK:
192	case A_SETSMASK:
193	case A_SETCOND:
194	case A_SETCLASS:
195	case A_SETPMASK:
196	case A_SETFSIZE:
197	case A_SETKAUDIT:
198	case A_GETCLASS:
199	case A_GETPINFO:
200	case A_GETPINFO_ADDR:
201	case A_SENDTRIGGER:
202		error = copyin(uap->data, (void *)&udata, uap->length);
203		if (error)
204			return (error);
205		AUDIT_ARG(auditon, &udata);
206		break;
207	}
208
209	/*
210	 * XXXAUDIT: Locking?
211	 */
212	switch (uap->cmd) {
213	case A_GETPOLICY:
214		if (!audit_fail_stop)
215			udata.au_policy |= AUDIT_CNT;
216		if (audit_panic_on_write_fail)
217			udata.au_policy |= AUDIT_AHLT;
218		if (audit_argv)
219			udata.au_policy |= AUDIT_ARGV;
220		if (audit_arge)
221			udata.au_policy |= AUDIT_ARGE;
222		break;
223
224	case A_SETPOLICY:
225		if (udata.au_policy & ~(AUDIT_CNT|AUDIT_AHLT|AUDIT_ARGV|
226		    AUDIT_ARGE))
227			return (EINVAL);
228		/*
229		 * XXX - Need to wake up waiters if the policy relaxes?
230		 */
231		audit_fail_stop = ((udata.au_policy & AUDIT_CNT) == 0);
232		audit_panic_on_write_fail = (udata.au_policy & AUDIT_AHLT);
233		audit_argv = (udata.au_policy & AUDIT_ARGV);
234		audit_arge = (udata.au_policy & AUDIT_ARGE);
235		break;
236
237	case A_GETKMASK:
238		udata.au_mask = audit_nae_mask;
239		break;
240
241	case A_SETKMASK:
242		audit_nae_mask = udata.au_mask;
243		break;
244
245	case A_GETQCTRL:
246		udata.au_qctrl = audit_qctrl;
247		break;
248
249	case A_SETQCTRL:
250		if ((udata.au_qctrl.aq_hiwater > AQ_MAXHIGH) ||
251		    (udata.au_qctrl.aq_lowater >= udata.au_qctrl.aq_hiwater) ||
252		    (udata.au_qctrl.aq_bufsz > AQ_MAXBUFSZ) ||
253		    (udata.au_qctrl.aq_minfree < 0) ||
254		    (udata.au_qctrl.aq_minfree > 100))
255			return (EINVAL);
256
257		audit_qctrl = udata.au_qctrl;
258		/* XXX The queue delay value isn't used with the kernel. */
259		audit_qctrl.aq_delay = -1;
260		break;
261
262	case A_GETCWD:
263		return (ENOSYS);
264		break;
265
266	case A_GETCAR:
267		return (ENOSYS);
268		break;
269
270	case A_GETSTAT:
271		return (ENOSYS);
272		break;
273
274	case A_SETSTAT:
275		return (ENOSYS);
276		break;
277
278	case A_SETUMASK:
279		return (ENOSYS);
280		break;
281
282	case A_SETSMASK:
283		return (ENOSYS);
284		break;
285
286	case A_GETCOND:
287		if (audit_enabled && !audit_suspended)
288			udata.au_cond = AUC_AUDITING;
289		else
290			udata.au_cond = AUC_NOAUDIT;
291		break;
292
293	case A_SETCOND:
294		if (udata.au_cond == AUC_NOAUDIT)
295			audit_suspended = 1;
296		if (udata.au_cond == AUC_AUDITING)
297			audit_suspended = 0;
298		if (udata.au_cond == AUC_DISABLED) {
299			audit_suspended = 1;
300			audit_shutdown(NULL, 0);
301		}
302		break;
303
304	case A_GETCLASS:
305		udata.au_evclass.ec_class = au_event_class(
306		    udata.au_evclass.ec_number);
307		break;
308
309	case A_SETCLASS:
310		au_evclassmap_insert(udata.au_evclass.ec_number,
311		    udata.au_evclass.ec_class);
312		break;
313
314	case A_GETPINFO:
315		if (udata.au_aupinfo.ap_pid < 1)
316			return (EINVAL);
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		if (tp->p_ucred->cr_audit.ai_termid.at_type == AU_IPv6) {
324			PROC_UNLOCK(tp);
325			return (EINVAL);
326		}
327		udata.au_aupinfo.ap_auid =
328		    tp->p_ucred->cr_audit.ai_auid;
329		udata.au_aupinfo.ap_mask.am_success =
330		    tp->p_ucred->cr_audit.ai_mask.am_success;
331		udata.au_aupinfo.ap_mask.am_failure =
332		    tp->p_ucred->cr_audit.ai_mask.am_failure;
333		udata.au_aupinfo.ap_termid.machine =
334		    tp->p_ucred->cr_audit.ai_termid.at_addr[0];
335		udata.au_aupinfo.ap_termid.port =
336		    (dev_t)tp->p_ucred->cr_audit.ai_termid.at_port;
337		udata.au_aupinfo.ap_asid =
338		    tp->p_ucred->cr_audit.ai_asid;
339		PROC_UNLOCK(tp);
340		break;
341
342	case A_SETPMASK:
343		if (udata.au_aupinfo.ap_pid < 1)
344			return (EINVAL);
345		newcred = crget();
346		if ((tp = pfind(udata.au_aupinfo.ap_pid)) == NULL) {
347			crfree(newcred);
348			return (EINVAL);
349		}
350		if (p_cansee(td, tp) != 0) {
351			PROC_UNLOCK(tp);
352			crfree(newcred);
353			return (EINVAL);
354		}
355		oldcred = tp->p_ucred;
356		crcopy(newcred, oldcred);
357		newcred->cr_audit.ai_mask.am_success =
358		    udata.au_aupinfo.ap_mask.am_success;
359		newcred->cr_audit.ai_mask.am_failure =
360		    udata.au_aupinfo.ap_mask.am_failure;
361		td->td_proc->p_ucred = newcred;
362		PROC_UNLOCK(tp);
363		crfree(oldcred);
364		break;
365
366	case A_SETFSIZE:
367		if ((udata.au_fstat.af_filesz != 0) &&
368		   (udata.au_fstat.af_filesz < MIN_AUDIT_FILE_SIZE))
369			return (EINVAL);
370		audit_fstat.af_filesz = udata.au_fstat.af_filesz;
371		break;
372
373	case A_GETFSIZE:
374		udata.au_fstat.af_filesz = audit_fstat.af_filesz;
375		udata.au_fstat.af_currsz = audit_fstat.af_currsz;
376		break;
377
378	case A_GETPINFO_ADDR:
379		if (udata.au_aupinfo_addr.ap_pid < 1)
380			return (EINVAL);
381		if ((tp = pfind(udata.au_aupinfo_addr.ap_pid)) == NULL)
382			return (EINVAL);
383		udata.au_aupinfo_addr.ap_auid =
384		    tp->p_ucred->cr_audit.ai_auid;
385		udata.au_aupinfo_addr.ap_mask.am_success =
386		    tp->p_ucred->cr_audit.ai_mask.am_success;
387		udata.au_aupinfo_addr.ap_mask.am_failure =
388		    tp->p_ucred->cr_audit.ai_mask.am_failure;
389		udata.au_aupinfo_addr.ap_termid =
390		    tp->p_ucred->cr_audit.ai_termid;
391		udata.au_aupinfo_addr.ap_asid =
392		    tp->p_ucred->cr_audit.ai_asid;
393		PROC_UNLOCK(tp);
394		break;
395
396	case A_GETKAUDIT:
397		return (ENOSYS);
398		break;
399
400	case A_SETKAUDIT:
401		return (ENOSYS);
402		break;
403
404	case A_SENDTRIGGER:
405		if ((udata.au_trigger < AUDIT_TRIGGER_MIN) ||
406		    (udata.au_trigger > AUDIT_TRIGGER_MAX))
407			return (EINVAL);
408		return (send_trigger(udata.au_trigger));
409	}
410
411	/*
412	 * Copy data back to userspace for the GET comands.
413	 */
414	switch (uap->cmd) {
415	case A_GETPOLICY:
416	case A_GETKMASK:
417	case A_GETQCTRL:
418	case A_GETCWD:
419	case A_GETCAR:
420	case A_GETSTAT:
421	case A_GETCOND:
422	case A_GETCLASS:
423	case A_GETPINFO:
424	case A_GETFSIZE:
425	case A_GETPINFO_ADDR:
426	case A_GETKAUDIT:
427		error = copyout((void *)&udata, uap->data, uap->length);
428		if (error)
429			return (error);
430		break;
431	}
432
433	return (0);
434}
435
436/*
437 * System calls to manage the user audit information.
438 */
439/* ARGSUSED */
440int
441getauid(struct thread *td, struct getauid_args *uap)
442{
443	int error;
444
445	if (jailed(td->td_ucred))
446		return (ENOSYS);
447	error = priv_check(td, PRIV_AUDIT_GETAUDIT);
448	if (error)
449		return (error);
450	return (copyout(&td->td_ucred->cr_audit.ai_auid, uap->auid,
451	    sizeof(td->td_ucred->cr_audit.ai_auid)));
452}
453
454/* ARGSUSED */
455int
456setauid(struct thread *td, struct setauid_args *uap)
457{
458	struct ucred *newcred, *oldcred;
459	au_id_t id;
460	int error;
461
462	if (jailed(td->td_ucred))
463		return (ENOSYS);
464	error = copyin(uap->auid, &id, sizeof(id));
465	if (error)
466		return (error);
467	audit_arg_auid(id);
468	newcred = crget();
469	PROC_LOCK(td->td_proc);
470	oldcred = td->td_proc->p_ucred;
471	crcopy(newcred, oldcred);
472#ifdef MAC
473	error = mac_check_proc_setauid(oldcred, id);
474	if (error)
475		goto fail;
476#endif
477	error = priv_check_cred(oldcred, PRIV_AUDIT_SETAUDIT, 0);
478	if (error)
479		goto fail;
480	newcred->cr_audit.ai_auid = id;
481	td->td_proc->p_ucred = newcred;
482	PROC_UNLOCK(td->td_proc);
483	crfree(oldcred);
484	return (0);
485fail:
486	PROC_UNLOCK(td->td_proc);
487	crfree(newcred);
488	return (error);
489}
490
491/*
492 * System calls to get and set process audit information.
493 */
494/* ARGSUSED */
495int
496getaudit(struct thread *td, struct getaudit_args *uap)
497{
498	struct auditinfo ai;
499	int error;
500
501	if (jailed(td->td_ucred))
502		return (ENOSYS);
503	error = priv_check(td, PRIV_AUDIT_GETAUDIT);
504	if (error)
505		return (error);
506	bzero(&ai, sizeof(ai));
507	ai.ai_auid = td->td_ucred->cr_audit.ai_auid;
508	ai.ai_mask = td->td_ucred->cr_audit.ai_mask;
509	ai.ai_asid = td->td_ucred->cr_audit.ai_asid;
510	ai.ai_termid.machine = td->td_ucred->cr_audit.ai_termid.at_addr[0];
511	ai.ai_termid.port = td->td_ucred->cr_audit.ai_termid.at_port;
512	return (copyout(&ai, uap->auditinfo, sizeof(&ai)));
513}
514
515/* ARGSUSED */
516int
517setaudit(struct thread *td, struct setaudit_args *uap)
518{
519	struct ucred *newcred, *oldcred;
520	struct auditinfo ai;
521	int error;
522
523	if (jailed(td->td_ucred))
524		return (ENOSYS);
525	error = copyin(uap->auditinfo, &ai, sizeof(ai));
526	if (error)
527		return (error);
528	audit_arg_auditinfo(&ai);
529	newcred = crget();
530	PROC_LOCK(td->td_proc);
531	oldcred = td->td_proc->p_ucred;
532	crcopy(newcred, oldcred);
533#ifdef MAC
534	error = mac_check_proc_setaudit(oldcred, &ai);
535	if (error)
536		goto fail;
537#endif
538	error = priv_check_cred(oldcred, PRIV_AUDIT_SETAUDIT, 0);
539	if (error)
540		goto fail;
541	bzero(&newcred->cr_audit, sizeof(newcred->cr_audit));
542	newcred->cr_audit.ai_auid = ai.ai_auid;
543	newcred->cr_audit.ai_mask = ai.ai_mask;
544	newcred->cr_audit.ai_asid = ai.ai_asid;
545	newcred->cr_audit.ai_termid.at_addr[0] = ai.ai_termid.machine;
546	newcred->cr_audit.ai_termid.at_port = ai.ai_termid.port;
547	newcred->cr_audit.ai_termid.at_type = AU_IPv4;
548	td->td_proc->p_ucred = newcred;
549	PROC_UNLOCK(td->td_proc);
550	crfree(oldcred);
551	return (0);
552fail:
553	PROC_UNLOCK(td->td_proc);
554	crfree(newcred);
555	return (error);
556}
557
558/* ARGSUSED */
559int
560getaudit_addr(struct thread *td, struct getaudit_addr_args *uap)
561{
562	int error;
563
564	if (jailed(td->td_ucred))
565		return (ENOSYS);
566	if (uap->length < sizeof(*uap->auditinfo_addr))
567		return (EOVERFLOW);
568	error = priv_check(td, PRIV_AUDIT_GETAUDIT);
569	if (error)
570		return (error);
571	return (copyout(&td->td_ucred->cr_audit, uap->auditinfo_addr,
572	    sizeof(*uap->auditinfo_addr)));
573}
574
575/* ARGSUSED */
576int
577setaudit_addr(struct thread *td, struct setaudit_addr_args *uap)
578{
579	struct ucred *newcred, *oldcred;
580	struct auditinfo_addr aia;
581	int error;
582
583	if (jailed(td->td_ucred))
584		return (ENOSYS);
585	error = copyin(uap->auditinfo_addr, &aia, sizeof(aia));
586	if (error)
587		return (error);
588	/* XXXRW: Audit argument. */
589	newcred = crget();
590	PROC_LOCK(td->td_proc);
591	oldcred = td->td_proc->p_ucred;
592	crcopy(newcred, oldcred);
593#ifdef MAC
594	error = mac_check_proc_setaudit(oldcred, NULL);
595	if (error)
596		goto fail;
597#endif
598	error = priv_check_cred(oldcred, PRIV_AUDIT_SETAUDIT, 0);
599	if (error)
600		goto fail;
601	newcred->cr_audit = aia;
602	td->td_proc->p_ucred = newcred;
603	PROC_UNLOCK(td->td_proc);
604	crfree(oldcred);
605	return (0);
606fail:
607	PROC_UNLOCK(td->td_proc);
608	crfree(newcred);
609	return (error);
610}
611
612/*
613 * Syscall to manage audit files.
614 */
615/* ARGSUSED */
616int
617auditctl(struct thread *td, struct auditctl_args *uap)
618{
619	struct nameidata nd;
620	struct ucred *cred;
621	struct vnode *vp;
622	int error = 0;
623	int flags, vfslocked;
624
625	if (jailed(td->td_ucred))
626		return (ENOSYS);
627	error = priv_check(td, PRIV_AUDIT_CONTROL);
628	if (error)
629		return (error);
630
631	vp = NULL;
632	cred = NULL;
633
634	/*
635	 * If a path is specified, open the replacement vnode, perform
636	 * validity checks, and grab another reference to the current
637	 * credential.
638	 *
639	 * On Darwin, a NULL path argument is also used to disable audit.
640	 */
641	if (uap->path == NULL)
642		return (EINVAL);
643
644	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1,
645	    UIO_USERSPACE, uap->path, td);
646	flags = AUDIT_OPEN_FLAGS;
647	error = vn_open(&nd, &flags, 0, NULL);
648	if (error)
649		return (error);
650	vfslocked = NDHASGIANT(&nd);
651	vp = nd.ni_vp;
652#ifdef MAC
653	error = mac_check_system_auditctl(td->td_ucred, vp);
654	VOP_UNLOCK(vp, 0, td);
655	if (error) {
656		vn_close(vp, AUDIT_CLOSE_FLAGS, td->td_ucred, td);
657		VFS_UNLOCK_GIANT(vfslocked);
658		return (error);
659	}
660#else
661	VOP_UNLOCK(vp, 0, td);
662#endif
663	NDFREE(&nd, NDF_ONLY_PNBUF);
664	if (vp->v_type != VREG) {
665		vn_close(vp, AUDIT_CLOSE_FLAGS, td->td_ucred, td);
666		VFS_UNLOCK_GIANT(vfslocked);
667		return (EINVAL);
668	}
669	VFS_UNLOCK_GIANT(vfslocked);
670	cred = td->td_ucred;
671	crhold(cred);
672
673	/*
674	 * XXXAUDIT: Should audit_suspended actually be cleared by
675	 * audit_worker?
676	 */
677	audit_suspended = 0;
678
679	audit_rotate_vnode(cred, vp);
680
681	return (error);
682}
683
684#else /* !AUDIT */
685
686int
687audit(struct thread *td, struct audit_args *uap)
688{
689
690	return (ENOSYS);
691}
692
693int
694auditon(struct thread *td, struct auditon_args *uap)
695{
696
697	return (ENOSYS);
698}
699
700int
701getauid(struct thread *td, struct getauid_args *uap)
702{
703
704	return (ENOSYS);
705}
706
707int
708setauid(struct thread *td, struct setauid_args *uap)
709{
710
711	return (ENOSYS);
712}
713
714int
715getaudit(struct thread *td, struct getaudit_args *uap)
716{
717
718	return (ENOSYS);
719}
720
721int
722setaudit(struct thread *td, struct setaudit_args *uap)
723{
724
725	return (ENOSYS);
726}
727
728int
729getaudit_addr(struct thread *td, struct getaudit_addr_args *uap)
730{
731
732	return (ENOSYS);
733}
734
735int
736setaudit_addr(struct thread *td, struct setaudit_addr_args *uap)
737{
738
739	return (ENOSYS);
740}
741
742int
743auditctl(struct thread *td, struct auditctl_args *uap)
744{
745
746	return (ENOSYS);
747}
748#endif /* AUDIT */
749