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