2 * Copyright (c) 1999-2009 Apple Inc.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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.
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
33 #include <sys/param.h>
34 #include <sys/mount.h>
35 #include <sys/namei.h>
38 #include <sys/sysproto.h>
39 #include <sys/systm.h>
40 #include <sys/vnode.h>
43 #include <bsm/audit.h>
44 #include <bsm/audit_kevents.h>
46 #include <security/audit/audit.h>
47 #include <security/audit/audit_private.h>
48 #include <security/mac/mac_framework.h>
53 * System call to allow a user space application to submit a BSM audit record
54 * to the kernel for inclusion in the audit log. This function does little
55 * verification on the audit record that is submitted.
57 * XXXAUDIT: Audit preselection for user records does not currently work,
58 * since we pre-select only based on the AUE_audit event type, not the event
59 * type submitted as part of the user audit data.
63 sys_audit(struct thread *td, struct audit_args *uap)
67 struct kaudit_record *ar;
69 if (jailed(td->td_ucred))
71 error = priv_check(td, PRIV_AUDIT_SUBMIT);
75 if ((uap->length <= 0) || (uap->length > audit_qctrl.aq_bufsz))
81 * If there's no current audit record (audit() itself not audited)
82 * commit the user audit record.
87 * This is not very efficient; we're required to allocate a
88 * complete kernel audit record just so the user record can
91 * XXXAUDIT: Maybe AUE_AUDIT in the system call context and
92 * special pre-select handling?
94 td->td_ar = audit_new(AUE_NULL, td);
95 if (td->td_ar == NULL)
97 td->td_pflags |= TDP_AUDITREC;
101 if (uap->length > MAX_AUDIT_RECORD_SIZE)
104 rec = malloc(uap->length, M_AUDITDATA, M_WAITOK);
106 error = copyin(uap->record, rec, uap->length);
110 /* Verify the record. */
111 if (bsm_rec_verify(rec) == 0) {
117 error = mac_system_check_audit(td->td_ucred, rec, uap->length);
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.
127 * XXXAUDIT: KASSERT appropriate starting values of k_udata, k_ulen,
128 * k_ar_commit & AR_COMMIT_USER?
131 ar->k_ulen = uap->length;
132 ar->k_ar_commit |= AR_COMMIT_USER;
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.
140 ar->k_ar_commit |= (AR_PRESELECT_USER_TRAIL | AR_PRESELECT_USER_PIPE);
145 * audit_syscall_exit() will free the audit record on the thread even
146 * if we allocated it above.
148 free(rec, M_AUDITDATA);
153 * System call to manipulate auditing.
157 sys_auditon(struct thread *td, struct auditon_args *uap)
159 struct ucred *cred, *newcred, *oldcred;
161 union auditon_udata udata;
164 if (jailed(td->td_ucred))
166 AUDIT_ARG_CMD(uap->cmd);
169 error = mac_system_check_auditon(td->td_ucred, uap->cmd);
174 error = priv_check(td, PRIV_AUDIT_CONTROL);
178 if ((uap->length <= 0) || (uap->length > sizeof(union auditon_udata)))
181 memset((void *)&udata, 0, sizeof(udata));
184 * Some of the GET commands use the arguments too.
203 case A_GETPINFO_ADDR:
205 error = copyin(uap->data, (void *)&udata, uap->length);
208 AUDIT_ARG_AUDITON(&udata);
218 if (uap->length == sizeof(udata.au_policy64)) {
219 if (!audit_fail_stop)
220 udata.au_policy64 |= AUDIT_CNT;
221 if (audit_panic_on_write_fail)
222 udata.au_policy64 |= AUDIT_AHLT;
224 udata.au_policy64 |= AUDIT_ARGV;
226 udata.au_policy64 |= AUDIT_ARGE;
229 if (uap->length != sizeof(udata.au_policy))
231 if (!audit_fail_stop)
232 udata.au_policy |= AUDIT_CNT;
233 if (audit_panic_on_write_fail)
234 udata.au_policy |= AUDIT_AHLT;
236 udata.au_policy |= AUDIT_ARGV;
238 udata.au_policy |= AUDIT_ARGE;
243 if (uap->length == sizeof(udata.au_policy64)) {
244 if (udata.au_policy & (~AUDIT_CNT|AUDIT_AHLT|
245 AUDIT_ARGV|AUDIT_ARGE))
247 audit_fail_stop = ((udata.au_policy64 & AUDIT_CNT) ==
249 audit_panic_on_write_fail = (udata.au_policy64 &
251 audit_argv = (udata.au_policy64 & AUDIT_ARGV);
252 audit_arge = (udata.au_policy64 & AUDIT_ARGE);
255 if (uap->length != sizeof(udata.au_policy))
257 if (udata.au_policy & ~(AUDIT_CNT|AUDIT_AHLT|AUDIT_ARGV|
261 * XXX - Need to wake up waiters if the policy relaxes?
263 audit_fail_stop = ((udata.au_policy & AUDIT_CNT) == 0);
264 audit_panic_on_write_fail = (udata.au_policy & AUDIT_AHLT);
265 audit_argv = (udata.au_policy & AUDIT_ARGV);
266 audit_arge = (udata.au_policy & AUDIT_ARGE);
270 if (uap->length != sizeof(udata.au_mask))
272 udata.au_mask = audit_nae_mask;
276 if (uap->length != sizeof(udata.au_mask))
278 audit_nae_mask = udata.au_mask;
283 if (uap->length == sizeof(udata.au_qctrl64)) {
284 udata.au_qctrl64.aq64_hiwater =
285 (u_int64_t)audit_qctrl.aq_hiwater;
286 udata.au_qctrl64.aq64_lowater =
287 (u_int64_t)audit_qctrl.aq_lowater;
288 udata.au_qctrl64.aq64_bufsz =
289 (u_int64_t)audit_qctrl.aq_bufsz;
290 udata.au_qctrl64.aq64_minfree =
291 (u_int64_t)audit_qctrl.aq_minfree;
294 if (uap->length != sizeof(udata.au_qctrl))
296 udata.au_qctrl = audit_qctrl;
301 if (uap->length == sizeof(udata.au_qctrl64)) {
302 if ((udata.au_qctrl64.aq64_hiwater > AQ_MAXHIGH) ||
303 (udata.au_qctrl64.aq64_lowater >=
304 udata.au_qctrl.aq_hiwater) ||
305 (udata.au_qctrl64.aq64_bufsz > AQ_MAXBUFSZ) ||
306 (udata.au_qctrl64.aq64_minfree < 0) ||
307 (udata.au_qctrl64.aq64_minfree > 100))
309 audit_qctrl.aq_hiwater =
310 (int)udata.au_qctrl64.aq64_hiwater;
311 audit_qctrl.aq_lowater =
312 (int)udata.au_qctrl64.aq64_lowater;
313 audit_qctrl.aq_bufsz =
314 (int)udata.au_qctrl64.aq64_bufsz;
315 audit_qctrl.aq_minfree =
316 (int)udata.au_qctrl64.aq64_minfree;
317 audit_qctrl.aq_delay = -1; /* Not used. */
320 if (uap->length != sizeof(udata.au_qctrl))
322 if ((udata.au_qctrl.aq_hiwater > AQ_MAXHIGH) ||
323 (udata.au_qctrl.aq_lowater >= udata.au_qctrl.aq_hiwater) ||
324 (udata.au_qctrl.aq_bufsz > AQ_MAXBUFSZ) ||
325 (udata.au_qctrl.aq_minfree < 0) ||
326 (udata.au_qctrl.aq_minfree > 100))
329 audit_qctrl = udata.au_qctrl;
330 /* XXX The queue delay value isn't used with the kernel. */
331 audit_qctrl.aq_delay = -1;
360 if (uap->length == sizeof(udata.au_cond64)) {
361 if (audit_enabled && !audit_suspended)
362 udata.au_cond64 = AUC_AUDITING;
364 udata.au_cond64 = AUC_NOAUDIT;
367 if (uap->length != sizeof(udata.au_cond))
369 if (audit_enabled && !audit_suspended)
370 udata.au_cond = AUC_AUDITING;
372 udata.au_cond = AUC_NOAUDIT;
377 if (uap->length == sizeof(udata.au_cond64)) {
378 if (udata.au_cond64 == AUC_NOAUDIT)
380 if (udata.au_cond64 == AUC_AUDITING)
382 if (udata.au_cond64 == AUC_DISABLED) {
384 audit_shutdown(NULL, 0);
388 if (uap->length != sizeof(udata.au_cond))
390 if (udata.au_cond == AUC_NOAUDIT)
392 if (udata.au_cond == AUC_AUDITING)
394 if (udata.au_cond == AUC_DISABLED) {
396 audit_shutdown(NULL, 0);
401 if (uap->length != sizeof(udata.au_evclass))
403 udata.au_evclass.ec_class = au_event_class(
404 udata.au_evclass.ec_number);
408 if (uap->length != sizeof(udata.au_evclass))
410 au_evclassmap_insert(udata.au_evclass.ec_number,
411 udata.au_evclass.ec_class);
415 if (uap->length != sizeof(udata.au_aupinfo))
417 if (udata.au_aupinfo.ap_pid < 1)
419 if ((tp = pfind(udata.au_aupinfo.ap_pid)) == NULL)
421 if ((error = p_cansee(td, tp)) != 0) {
426 if (cred->cr_audit.ai_termid.at_type == AU_IPv6) {
430 udata.au_aupinfo.ap_auid = cred->cr_audit.ai_auid;
431 udata.au_aupinfo.ap_mask.am_success =
432 cred->cr_audit.ai_mask.am_success;
433 udata.au_aupinfo.ap_mask.am_failure =
434 cred->cr_audit.ai_mask.am_failure;
435 udata.au_aupinfo.ap_termid.machine =
436 cred->cr_audit.ai_termid.at_addr[0];
437 udata.au_aupinfo.ap_termid.port =
438 (dev_t)cred->cr_audit.ai_termid.at_port;
439 udata.au_aupinfo.ap_asid = cred->cr_audit.ai_asid;
444 if (uap->length != sizeof(udata.au_aupinfo))
446 if (udata.au_aupinfo.ap_pid < 1)
449 if ((tp = pfind(udata.au_aupinfo.ap_pid)) == NULL) {
453 if ((error = p_cansee(td, tp)) != 0) {
458 oldcred = tp->p_ucred;
459 crcopy(newcred, oldcred);
460 newcred->cr_audit.ai_mask.am_success =
461 udata.au_aupinfo.ap_mask.am_success;
462 newcred->cr_audit.ai_mask.am_failure =
463 udata.au_aupinfo.ap_mask.am_failure;
464 td->td_proc->p_ucred = newcred;
470 if (uap->length != sizeof(udata.au_fstat))
472 if ((udata.au_fstat.af_filesz != 0) &&
473 (udata.au_fstat.af_filesz < MIN_AUDIT_FILE_SIZE))
475 audit_fstat.af_filesz = udata.au_fstat.af_filesz;
479 if (uap->length != sizeof(udata.au_fstat))
481 udata.au_fstat.af_filesz = audit_fstat.af_filesz;
482 udata.au_fstat.af_currsz = audit_fstat.af_currsz;
485 case A_GETPINFO_ADDR:
486 if (uap->length != sizeof(udata.au_aupinfo_addr))
488 if (udata.au_aupinfo_addr.ap_pid < 1)
490 if ((tp = pfind(udata.au_aupinfo_addr.ap_pid)) == NULL)
493 udata.au_aupinfo_addr.ap_auid = cred->cr_audit.ai_auid;
494 udata.au_aupinfo_addr.ap_mask.am_success =
495 cred->cr_audit.ai_mask.am_success;
496 udata.au_aupinfo_addr.ap_mask.am_failure =
497 cred->cr_audit.ai_mask.am_failure;
498 udata.au_aupinfo_addr.ap_termid = cred->cr_audit.ai_termid;
499 udata.au_aupinfo_addr.ap_asid = cred->cr_audit.ai_asid;
504 if (uap->length != sizeof(udata.au_kau_info))
506 audit_get_kinfo(&udata.au_kau_info);
510 if (uap->length != sizeof(udata.au_kau_info))
512 if (udata.au_kau_info.ai_termid.at_type != AU_IPv4 &&
513 udata.au_kau_info.ai_termid.at_type != AU_IPv6)
515 audit_set_kinfo(&udata.au_kau_info);
519 if (uap->length != sizeof(udata.au_trigger))
521 if ((udata.au_trigger < AUDIT_TRIGGER_MIN) ||
522 (udata.au_trigger > AUDIT_TRIGGER_MAX))
524 return (audit_send_trigger(udata.au_trigger));
531 * Copy data back to userspace for the GET comands.
547 case A_GETPINFO_ADDR:
549 error = copyout((void *)&udata, uap->data, uap->length);
559 * System calls to manage the user audit information.
563 sys_getauid(struct thread *td, struct getauid_args *uap)
567 if (jailed(td->td_ucred))
569 error = priv_check(td, PRIV_AUDIT_GETAUDIT);
572 return (copyout(&td->td_ucred->cr_audit.ai_auid, uap->auid,
573 sizeof(td->td_ucred->cr_audit.ai_auid)));
578 sys_setauid(struct thread *td, struct setauid_args *uap)
580 struct ucred *newcred, *oldcred;
584 if (jailed(td->td_ucred))
586 error = copyin(uap->auid, &id, sizeof(id));
591 PROC_LOCK(td->td_proc);
592 oldcred = td->td_proc->p_ucred;
593 crcopy(newcred, oldcred);
595 error = mac_cred_check_setauid(oldcred, id);
599 error = priv_check_cred(oldcred, PRIV_AUDIT_SETAUDIT, 0);
602 newcred->cr_audit.ai_auid = id;
603 td->td_proc->p_ucred = newcred;
604 PROC_UNLOCK(td->td_proc);
608 PROC_UNLOCK(td->td_proc);
614 * System calls to get and set process audit information.
618 sys_getaudit(struct thread *td, struct getaudit_args *uap)
627 error = priv_check(td, PRIV_AUDIT_GETAUDIT);
630 if (cred->cr_audit.ai_termid.at_type == AU_IPv6)
632 bzero(&ai, sizeof(ai));
633 ai.ai_auid = cred->cr_audit.ai_auid;
634 ai.ai_mask = cred->cr_audit.ai_mask;
635 ai.ai_asid = cred->cr_audit.ai_asid;
636 ai.ai_termid.machine = cred->cr_audit.ai_termid.at_addr[0];
637 ai.ai_termid.port = cred->cr_audit.ai_termid.at_port;
638 return (copyout(&ai, uap->auditinfo, sizeof(ai)));
643 sys_setaudit(struct thread *td, struct setaudit_args *uap)
645 struct ucred *newcred, *oldcred;
649 if (jailed(td->td_ucred))
651 error = copyin(uap->auditinfo, &ai, sizeof(ai));
654 audit_arg_auditinfo(&ai);
656 PROC_LOCK(td->td_proc);
657 oldcred = td->td_proc->p_ucred;
658 crcopy(newcred, oldcred);
660 error = mac_cred_check_setaudit(oldcred, &ai);
664 error = priv_check_cred(oldcred, PRIV_AUDIT_SETAUDIT, 0);
667 bzero(&newcred->cr_audit, sizeof(newcred->cr_audit));
668 newcred->cr_audit.ai_auid = ai.ai_auid;
669 newcred->cr_audit.ai_mask = ai.ai_mask;
670 newcred->cr_audit.ai_asid = ai.ai_asid;
671 newcred->cr_audit.ai_termid.at_addr[0] = ai.ai_termid.machine;
672 newcred->cr_audit.ai_termid.at_port = ai.ai_termid.port;
673 newcred->cr_audit.ai_termid.at_type = AU_IPv4;
674 td->td_proc->p_ucred = newcred;
675 PROC_UNLOCK(td->td_proc);
679 PROC_UNLOCK(td->td_proc);
686 sys_getaudit_addr(struct thread *td, struct getaudit_addr_args *uap)
690 if (jailed(td->td_ucred))
692 if (uap->length < sizeof(*uap->auditinfo_addr))
694 error = priv_check(td, PRIV_AUDIT_GETAUDIT);
697 return (copyout(&td->td_ucred->cr_audit, uap->auditinfo_addr,
698 sizeof(*uap->auditinfo_addr)));
703 sys_setaudit_addr(struct thread *td, struct setaudit_addr_args *uap)
705 struct ucred *newcred, *oldcred;
706 struct auditinfo_addr aia;
709 if (jailed(td->td_ucred))
711 error = copyin(uap->auditinfo_addr, &aia, sizeof(aia));
714 audit_arg_auditinfo_addr(&aia);
715 if (aia.ai_termid.at_type != AU_IPv6 &&
716 aia.ai_termid.at_type != AU_IPv4)
719 PROC_LOCK(td->td_proc);
720 oldcred = td->td_proc->p_ucred;
721 crcopy(newcred, oldcred);
723 error = mac_cred_check_setaudit_addr(oldcred, &aia);
727 error = priv_check_cred(oldcred, PRIV_AUDIT_SETAUDIT, 0);
730 newcred->cr_audit = aia;
731 td->td_proc->p_ucred = newcred;
732 PROC_UNLOCK(td->td_proc);
736 PROC_UNLOCK(td->td_proc);
742 * Syscall to manage audit files.
746 sys_auditctl(struct thread *td, struct auditctl_args *uap)
754 if (jailed(td->td_ucred))
756 error = priv_check(td, PRIV_AUDIT_CONTROL);
764 * If a path is specified, open the replacement vnode, perform
765 * validity checks, and grab another reference to the current
768 * On Darwin, a NULL path argument is also used to disable audit.
770 if (uap->path == NULL)
773 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | AUDITVNODE1,
774 UIO_USERSPACE, uap->path, td);
775 flags = AUDIT_OPEN_FLAGS;
776 error = vn_open(&nd, &flags, 0, NULL);
781 error = mac_system_check_auditctl(td->td_ucred, vp);
784 vn_close(vp, AUDIT_CLOSE_FLAGS, td->td_ucred, td);
790 NDFREE(&nd, NDF_ONLY_PNBUF);
791 if (vp->v_type != VREG) {
792 vn_close(vp, AUDIT_CLOSE_FLAGS, td->td_ucred, td);
799 * XXXAUDIT: Should audit_suspended actually be cleared by
804 audit_rotate_vnode(cred, vp);
812 sys_audit(struct thread *td, struct audit_args *uap)
819 sys_auditon(struct thread *td, struct auditon_args *uap)
826 sys_getauid(struct thread *td, struct getauid_args *uap)
833 sys_setauid(struct thread *td, struct setauid_args *uap)
840 sys_getaudit(struct thread *td, struct getaudit_args *uap)
847 sys_setaudit(struct thread *td, struct setaudit_args *uap)
854 sys_getaudit_addr(struct thread *td, struct getaudit_addr_args *uap)
861 sys_setaudit_addr(struct thread *td, struct setaudit_addr_args *uap)
868 sys_auditctl(struct thread *td, struct auditctl_args *uap)