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 * NOTICE: This file was modified by McAfee Research in 2004 to introduce
31 * support for mandatory and extensible security protections. This notice
32 * is included in support of clause 2.2 (b) of the Apple Public License,
36 #include <sys/param.h>
37 #include <sys/fcntl.h>
38 #include <sys/kernel.h>
40 #include <sys/namei.h>
41 #include <sys/proc_internal.h>
42 #include <sys/kauth.h>
43 #include <sys/queue.h>
44 #include <sys/systm.h>
46 #include <sys/ucred.h>
48 #include <sys/unistd.h>
49 #include <sys/file_internal.h>
50 #include <sys/vnode_internal.h>
52 #include <sys/syscall.h>
53 #include <sys/malloc.h>
55 #include <sys/sysent.h>
56 #include <sys/sysproto.h>
57 #include <sys/vfs_context.h>
58 #include <sys/domain.h>
59 #include <sys/protosw.h>
60 #include <sys/socketvar.h>
62 #include <bsm/audit.h>
63 #include <bsm/audit_kevents.h>
65 #include <security/audit/audit.h>
66 #include <security/audit/audit_bsd.h>
67 #include <security/audit/audit_private.h>
69 #include <mach/host_priv.h>
70 #include <mach/host_special_ports.h>
71 #include <mach/audit_triggers_server.h>
73 #include <kern/host.h>
74 #include <kern/kalloc.h>
75 #include <kern/zalloc.h>
76 #include <kern/lock.h>
77 #include <kern/wait_queue.h>
78 #include <kern/sched_prim.h>
81 #include <bsm/audit_record.h>
82 #include <security/mac.h>
83 #include <security/mac_framework.h>
84 #include <security/mac_policy.h>
87 #include <net/route.h>
89 #include <netinet/in.h>
90 #include <netinet/in_pcb.h>
94 #define IS_NOT_VALID_PID(p) ((p) < 1 || (p) > PID_MAX)
96 #ifdef AUDIT_API_WARNINGS
98 * Macro to warn about auditinfo_addr_t/auditpinfo_addr_t changing sizes
99 * to encourage the userland code to be recompiled and updated.
101 #define WARN_IF_AINFO_ADDR_CHANGED(sz1, sz2, scall, tp) do { \
102 if ((size_t)(sz1) != (size_t)(sz2)) { \
103 char pn[MAXCOMLEN + 1]; \
105 proc_selfname(pn, MAXCOMLEN + 1); \
106 printf("Size of %s used by %s in %s is different from " \
107 "kernel's. Please recompile %s.\n", (tp), \
113 * Macro to warn about using ASID's outside the range [1 to PID_MAX] to
114 * encourage userland code changes.
116 #define WARN_IF_BAD_ASID(asid, scall) do { \
117 if (((asid) < 1 || (asid) > PID_MAX) && \
118 (asid) != AU_ASSIGN_ASID) { \
119 char pn[MAXCOMLEN + 1]; \
121 proc_selfname(pn, MAXCOMLEN + 1); \
122 printf("%s in %s is using an ASID (%u) outside the " \
123 "range [1 to %d]. Please change %s to use an ASID "\
124 "within this range or use AU_ASSIGN_ASID.\n", \
125 (scall), pn, (uint32_t)(asid), PID_MAX, pn); \
129 #else /* ! AUDIT_API_WARNINGS */
131 #define WARN_IF_AINFO_ADDR_CHANGED(sz1, sz2, scall, tp) do { \
134 #define WARN_IF_BAD_ASID(asid, scall) do { \
137 #endif /* AUDIT_API_WARNINGS */
140 * System call to allow a user space application to submit a BSM audit record
141 * to the kernel for inclusion in the audit log. This function does little
142 * verification on the audit record that is submitted.
144 * XXXAUDIT: Audit preselection for user records does not currently work,
145 * since we pre-select only based on the AUE_audit event type, not the event
146 * type submitted as part of the user audit data.
150 audit(proc_t p
, struct audit_args
*uap
, __unused
int32_t *retval
)
154 struct kaudit_record
*ar
;
155 struct uthread
*uthr
;
157 error
= suser(kauth_cred_get(), &p
->p_acflag
);
161 mtx_lock(&audit_mtx
);
162 if ((uap
->length
<= 0) || (uap
->length
> (int)audit_qctrl
.aq_bufsz
)) {
163 mtx_unlock(&audit_mtx
);
166 mtx_unlock(&audit_mtx
);
171 * If there's no current audit record (audit() itself not audited)
172 * commit the user audit record.
176 if (uthr
== NULL
) /* can this happen? */
180 * This is not very efficient; we're required to allocate a
181 * complete kernel audit record just so the user record can
184 uthr
->uu_ar
= audit_new(AUE_NULL
, p
, uthr
);
185 if (uthr
->uu_ar
== NULL
)
190 if (uap
->length
> MAX_AUDIT_RECORD_SIZE
)
193 rec
= malloc(uap
->length
, M_AUDITDATA
, M_WAITOK
);
195 error
= copyin(uap
->record
, rec
, uap
->length
);
200 error
= mac_system_check_audit(kauth_cred_get(), rec
, uap
->length
);
205 /* Verify the record. */
206 if (bsm_rec_verify(rec
) == 0) {
212 * Attach the user audit record to the kernel audit record. Because
213 * this system call is an auditable event, we will write the user
214 * record along with the record for this audit event.
216 * XXXAUDIT: KASSERT appropriate starting values of k_udata, k_ulen,
217 * k_ar_commit & AR_COMMIT_USER?
220 ar
->k_ulen
= uap
->length
;
221 ar
->k_ar_commit
|= AR_COMMIT_USER
;
224 * Currently we assume that all preselection has been performed in
225 * userspace. We unconditionally set these masks so that the records
226 * get committed both to the trail and pipe. In the future we will
227 * want to setup kernel based preselection.
229 ar
->k_ar_commit
|= (AR_PRESELECT_USER_TRAIL
| AR_PRESELECT_USER_PIPE
);
234 * audit_syscall_exit() will free the audit record on the thread even
235 * if we allocated it above.
237 free(rec
, M_AUDITDATA
);
242 * System call to manipulate auditing.
246 auditon(proc_t p
, struct auditon_args
*uap
, __unused
int32_t *retval
)
250 union auditon_udata udata
;
251 proc_t tp
= PROC_NULL
;
252 struct auditinfo_addr aia
;
254 AUDIT_ARG(cmd
, uap
->cmd
);
257 error
= mac_system_check_auditon(kauth_cred_get(), uap
->cmd
);
262 if ((uap
->length
<= 0) || (uap
->length
>
263 (int)sizeof(union auditon_udata
)))
266 memset((void *)&udata
, 0, sizeof(udata
));
269 * Some of the GET commands use the arguments too.
288 case A_GETPINFO_ADDR
:
290 case A_GETSINFO_ADDR
:
291 error
= copyin(uap
->data
, (void *)&udata
, uap
->length
);
294 AUDIT_ARG(auditon
, &udata
);
295 AUDIT_ARG(len
, uap
->length
);
300 * A_GETSINFO doesn't require priviledge but only superuser
301 * gets to see the audit masks.
303 error
= suser(kauth_cred_get(), &p
->p_acflag
);
304 if (A_GETSINFO_ADDR
== uap
->cmd
) {
305 if ((sizeof(udata
.au_kau_info
) != uap
->length
) ||
306 (audit_session_lookup(udata
.au_kau_info
.ai_asid
,
307 &udata
.au_kau_info
) != 0))
310 udata
.au_kau_info
.ai_mask
.am_success
= ~0;
311 udata
.au_kau_info
.ai_mask
.am_failure
= ~0;
318 * XXX Need to implement these commands by accessing the global
319 * values associated with the commands.
321 mtx_lock(&audit_mtx
);
325 if (sizeof(udata
.au_policy64
) == uap
->length
) {
326 if (!audit_fail_stop
)
327 udata
.au_policy64
|= AUDIT_CNT
;
328 if (audit_panic_on_write_fail
)
329 udata
.au_policy64
|= AUDIT_AHLT
;
331 udata
.au_policy64
|= AUDIT_ARGV
;
333 udata
.au_policy64
|= AUDIT_ARGE
;
336 if (sizeof(udata
.au_policy
) != uap
->length
) {
337 mtx_unlock(&audit_mtx
);
340 if (!audit_fail_stop
)
341 udata
.au_policy
|= AUDIT_CNT
;
342 if (audit_panic_on_write_fail
)
343 udata
.au_policy
|= AUDIT_AHLT
;
345 udata
.au_policy
|= AUDIT_ARGV
;
347 udata
.au_policy
|= AUDIT_ARGE
;
352 if (sizeof(udata
.au_policy64
) == uap
->length
) {
353 if (udata
.au_policy64
& ~(AUDIT_CNT
|AUDIT_AHLT
|
354 AUDIT_ARGV
|AUDIT_ARGE
)) {
355 mtx_unlock(&audit_mtx
);
358 audit_fail_stop
= ((udata
.au_policy64
& AUDIT_CNT
) ==
360 audit_panic_on_write_fail
= (udata
.au_policy64
&
362 audit_argv
= (udata
.au_policy64
& AUDIT_ARGV
);
363 audit_arge
= (udata
.au_policy64
& AUDIT_ARGE
);
367 if ((sizeof(udata
.au_policy
) != uap
->length
) ||
368 (udata
.au_policy
& ~(AUDIT_CNT
|AUDIT_AHLT
|AUDIT_ARGV
|
370 mtx_unlock(&audit_mtx
);
374 * XXX - Need to wake up waiters if the policy relaxes?
376 audit_fail_stop
= ((udata
.au_policy
& AUDIT_CNT
) == 0);
377 audit_panic_on_write_fail
= (udata
.au_policy
& AUDIT_AHLT
);
378 audit_argv
= (udata
.au_policy
& AUDIT_ARGV
);
379 audit_arge
= (udata
.au_policy
& AUDIT_ARGE
);
383 if (sizeof(udata
.au_mask
) != uap
->length
) {
384 mtx_unlock(&audit_mtx
);
387 udata
.au_mask
= audit_nae_mask
;
391 if (sizeof(udata
.au_mask
) != uap
->length
) {
392 mtx_unlock(&audit_mtx
);
395 audit_nae_mask
= udata
.au_mask
;
396 AUDIT_CHECK_IF_KEVENTS_MASK(audit_nae_mask
);
401 if (sizeof(udata
.au_qctrl64
) == uap
->length
) {
402 udata
.au_qctrl64
.aq64_hiwater
=
403 (u_int64_t
)audit_qctrl
.aq_hiwater
;
404 udata
.au_qctrl64
.aq64_lowater
=
405 (u_int64_t
)audit_qctrl
.aq_lowater
;
406 udata
.au_qctrl64
.aq64_bufsz
=
407 (u_int64_t
)audit_qctrl
.aq_bufsz
;
408 udata
.au_qctrl64
.aq64_delay
=
409 (u_int64_t
)audit_qctrl
.aq_delay
;
410 udata
.au_qctrl64
.aq64_minfree
=
411 (int64_t)audit_qctrl
.aq_minfree
;
414 if (sizeof(udata
.au_qctrl
) != uap
->length
) {
415 mtx_unlock(&audit_mtx
);
418 udata
.au_qctrl
= audit_qctrl
;
423 if (sizeof(udata
.au_qctrl64
) == uap
->length
) {
424 if ((udata
.au_qctrl64
.aq64_hiwater
> AQ_MAXHIGH
) ||
425 (udata
.au_qctrl64
.aq64_lowater
>=
426 udata
.au_qctrl64
.aq64_hiwater
) ||
427 (udata
.au_qctrl64
.aq64_bufsz
> AQ_MAXBUFSZ
) ||
428 (udata
.au_qctrl64
.aq64_minfree
< 0) ||
429 (udata
.au_qctrl64
.aq64_minfree
> 100)) {
430 mtx_unlock(&audit_mtx
);
433 audit_qctrl
.aq_hiwater
=
434 (int)udata
.au_qctrl64
.aq64_hiwater
;
435 audit_qctrl
.aq_lowater
=
436 (int)udata
.au_qctrl64
.aq64_lowater
;
437 audit_qctrl
.aq_bufsz
=
438 (int)udata
.au_qctrl64
.aq64_bufsz
;
439 audit_qctrl
.aq_minfree
=
440 (int)udata
.au_qctrl64
.aq64_minfree
;
441 audit_qctrl
.aq_delay
= -1; /* Not used. */
445 if ((sizeof(udata
.au_qctrl
) != uap
->length
) ||
446 (udata
.au_qctrl
.aq_hiwater
> AQ_MAXHIGH
) ||
447 (udata
.au_qctrl
.aq_lowater
>= udata
.au_qctrl
.aq_hiwater
) ||
448 (udata
.au_qctrl
.aq_bufsz
> AQ_MAXBUFSZ
) ||
449 (udata
.au_qctrl
.aq_minfree
< 0) ||
450 (udata
.au_qctrl
.aq_minfree
> 100)) {
451 mtx_unlock(&audit_mtx
);
455 audit_qctrl
= udata
.au_qctrl
;
456 /* XXX The queue delay value isn't used with the kernel. */
457 audit_qctrl
.aq_delay
= -1;
461 mtx_unlock(&audit_mtx
);
466 mtx_unlock(&audit_mtx
);
471 mtx_unlock(&audit_mtx
);
476 mtx_unlock(&audit_mtx
);
481 mtx_unlock(&audit_mtx
);
486 mtx_unlock(&audit_mtx
);
492 if (sizeof(udata
.au_cond64
) == uap
->length
) {
493 if (audit_enabled
&& !audit_suspended
)
494 udata
.au_cond64
= AUC_AUDITING
;
496 udata
.au_cond64
= AUC_NOAUDIT
;
500 if (sizeof(udata
.au_cond
) != uap
->length
) {
501 mtx_unlock(&audit_mtx
);
504 if (audit_enabled
&& !audit_suspended
)
505 udata
.au_cond
= AUC_AUDITING
;
507 udata
.au_cond
= AUC_NOAUDIT
;
512 if (sizeof(udata
.au_cond64
) == uap
->length
) {
513 if (udata
.au_cond64
== AUC_NOAUDIT
)
515 if (udata
.au_cond64
== AUC_AUDITING
)
517 if (udata
.au_cond64
== AUC_DISABLED
) {
519 mtx_unlock(&audit_mtx
);
521 mtx_lock(&audit_mtx
);
525 if (sizeof(udata
.au_cond
) != uap
->length
) {
526 mtx_unlock(&audit_mtx
);
529 if (udata
.au_cond
== AUC_NOAUDIT
)
531 if (udata
.au_cond
== AUC_AUDITING
)
533 if (udata
.au_cond
== AUC_DISABLED
) {
535 mtx_unlock(&audit_mtx
);
537 mtx_lock(&audit_mtx
);
542 if (sizeof(udata
.au_evclass
) != uap
->length
) {
543 mtx_unlock(&audit_mtx
);
546 udata
.au_evclass
.ec_class
= au_event_class(
547 udata
.au_evclass
.ec_number
);
551 if (sizeof(udata
.au_evclass
) != uap
->length
) {
552 mtx_unlock(&audit_mtx
);
555 au_evclassmap_insert(udata
.au_evclass
.ec_number
,
556 udata
.au_evclass
.ec_class
);
560 if ((sizeof(udata
.au_aupinfo
) != uap
->length
) ||
561 IS_NOT_VALID_PID(udata
.au_aupinfo
.ap_pid
)) {
562 mtx_unlock(&audit_mtx
);
565 if ((tp
= proc_find(udata
.au_aupinfo
.ap_pid
)) == NULL
) {
566 mtx_unlock(&audit_mtx
);
570 mtx_unlock(&audit_mtx
);
571 scred
= kauth_cred_proc_ref(tp
);
572 if (scred
->cr_audit
.as_aia_p
->ai_termid
.at_type
== AU_IPv6
) {
573 kauth_cred_unref(&scred
);
578 udata
.au_aupinfo
.ap_auid
=
579 scred
->cr_audit
.as_aia_p
->ai_auid
;
580 udata
.au_aupinfo
.ap_mask
.am_success
=
581 scred
->cr_audit
.as_mask
.am_success
;
582 udata
.au_aupinfo
.ap_mask
.am_failure
=
583 scred
->cr_audit
.as_mask
.am_failure
;
584 udata
.au_aupinfo
.ap_termid
.machine
=
585 scred
->cr_audit
.as_aia_p
->ai_termid
.at_addr
[0];
586 udata
.au_aupinfo
.ap_termid
.port
=
587 scred
->cr_audit
.as_aia_p
->ai_termid
.at_port
;
588 udata
.au_aupinfo
.ap_asid
=
589 scred
->cr_audit
.as_aia_p
->ai_asid
;
590 kauth_cred_unref(&scred
);
593 mtx_lock(&audit_mtx
);
597 if ((sizeof(udata
.au_aupinfo
) != uap
->length
) ||
598 IS_NOT_VALID_PID(udata
.au_aupinfo
.ap_pid
)) {
599 mtx_unlock(&audit_mtx
);
602 if ((tp
= proc_find(udata
.au_aupinfo
.ap_pid
)) == NULL
) {
603 mtx_unlock(&audit_mtx
);
606 scred
= kauth_cred_proc_ref(tp
);
607 bcopy(scred
->cr_audit
.as_aia_p
, &aia
, sizeof(aia
));
608 kauth_cred_unref(&scred
);
609 aia
.ai_mask
.am_success
=
610 udata
.au_aupinfo
.ap_mask
.am_success
;
611 aia
.ai_mask
.am_failure
=
612 udata
.au_aupinfo
.ap_mask
.am_failure
;
613 AUDIT_CHECK_IF_KEVENTS_MASK(aia
.ai_mask
);
614 error
= audit_session_setaia(tp
, &aia
, 0);
615 mtx_unlock(&audit_mtx
);
620 mtx_lock(&audit_mtx
);
624 if ((sizeof(udata
.au_fstat
) != uap
->length
) ||
625 ((udata
.au_fstat
.af_filesz
!= 0) &&
626 (udata
.au_fstat
.af_filesz
< MIN_AUDIT_FILE_SIZE
))) {
627 mtx_unlock(&audit_mtx
);
630 audit_fstat
.af_filesz
= udata
.au_fstat
.af_filesz
;
634 if (sizeof(udata
.au_fstat
) != uap
->length
) {
635 mtx_unlock(&audit_mtx
);
638 udata
.au_fstat
.af_filesz
= audit_fstat
.af_filesz
;
639 udata
.au_fstat
.af_currsz
= audit_fstat
.af_currsz
;
642 case A_GETPINFO_ADDR
:
643 if ((sizeof(udata
.au_aupinfo_addr
) != uap
->length
) ||
644 IS_NOT_VALID_PID(udata
.au_aupinfo_addr
.ap_pid
)) {
645 mtx_unlock(&audit_mtx
);
648 if ((tp
= proc_find(udata
.au_aupinfo
.ap_pid
)) == NULL
) {
649 mtx_unlock(&audit_mtx
);
652 WARN_IF_AINFO_ADDR_CHANGED(uap
->length
,
653 sizeof(auditpinfo_addr_t
), "auditon(A_GETPINFO_ADDR,...)",
654 "auditpinfo_addr_t");
655 scred
= kauth_cred_proc_ref(tp
);
656 udata
.au_aupinfo_addr
.ap_auid
=
657 scred
->cr_audit
.as_aia_p
->ai_auid
;
658 udata
.au_aupinfo_addr
.ap_asid
=
659 scred
->cr_audit
.as_aia_p
->ai_asid
;
660 udata
.au_aupinfo_addr
.ap_mask
.am_success
=
661 scred
->cr_audit
.as_mask
.am_success
;
662 udata
.au_aupinfo_addr
.ap_mask
.am_failure
=
663 scred
->cr_audit
.as_mask
.am_failure
;
664 bcopy(&scred
->cr_audit
.as_aia_p
->ai_termid
,
665 &udata
.au_aupinfo_addr
.ap_termid
,
666 sizeof(au_tid_addr_t
));
667 udata
.au_aupinfo_addr
.ap_flags
=
668 scred
->cr_audit
.as_aia_p
->ai_flags
;
669 kauth_cred_unref(&scred
);
675 mtx_unlock(&audit_mtx
);
676 if (sizeof(udata
.au_kau_info
) != uap
->length
)
678 audit_get_kinfo(&udata
.au_kau_info
);
679 mtx_lock(&audit_mtx
);
683 if ((sizeof(udata
.au_kau_info
) != uap
->length
) ||
684 (udata
.au_kau_info
.ai_termid
.at_type
!= AU_IPv4
&&
685 udata
.au_kau_info
.ai_termid
.at_type
!= AU_IPv6
)) {
686 mtx_unlock(&audit_mtx
);
689 mtx_unlock(&audit_mtx
);
690 audit_set_kinfo(&udata
.au_kau_info
);
691 mtx_lock(&audit_mtx
);
695 if ((sizeof(udata
.au_trigger
) != uap
->length
) ||
696 (udata
.au_trigger
< AUDIT_TRIGGER_MIN
) ||
697 (udata
.au_trigger
> AUDIT_TRIGGER_MAX
)) {
698 mtx_unlock(&audit_mtx
);
701 mtx_unlock(&audit_mtx
);
702 return (audit_send_trigger(udata
.au_trigger
));
704 case A_GETSINFO_ADDR
:
705 /* Handled above before switch(). */
709 mtx_unlock(&audit_mtx
);
714 * Copy data back to userspace for the GET comands.
730 case A_GETPINFO_ADDR
:
732 case A_GETSINFO_ADDR
:
733 error
= copyout((void *)&udata
, uap
->data
, uap
->length
);
735 mtx_unlock(&audit_mtx
);
741 mtx_unlock(&audit_mtx
);
746 * System calls to manage the user audit information.
750 getauid(proc_t p
, struct getauid_args
*uap
, __unused
int32_t *retval
)
757 error
= mac_proc_check_getauid(p
);
761 scred
= kauth_cred_proc_ref(p
);
762 id
= scred
->cr_audit
.as_aia_p
->ai_auid
;
763 kauth_cred_unref(&scred
);
765 error
= copyout((void *)&id
, uap
->auid
, sizeof(id
));
774 setauid(proc_t p
, struct setauid_args
*uap
, __unused
int32_t *retval
)
779 struct auditinfo_addr aia
;
781 error
= copyin(uap
->auid
, &id
, sizeof(id
));
787 error
= mac_proc_check_setauid(p
, id
);
792 scred
= kauth_cred_proc_ref(p
);
793 error
= suser(scred
, &p
->p_acflag
);
795 kauth_cred_unref(&scred
);
799 bcopy(scred
->cr_audit
.as_aia_p
, &aia
, sizeof(aia
));
800 if (aia
.ai_asid
== AU_DEFAUDITSID
) {
801 aia
.ai_asid
= AU_ASSIGN_ASID
;
803 bcopy(&scred
->cr_audit
.as_mask
, &aia
.ai_mask
, sizeof(au_mask_t
));
804 kauth_cred_unref(&scred
);
806 error
= audit_session_setaia(p
, &aia
, 0);
812 getaudit_internal(proc_t p
, user_addr_t user_addr
)
817 scred
= kauth_cred_proc_ref(p
);
818 if (scred
->cr_audit
.as_aia_p
->ai_termid
.at_type
== AU_IPv6
) {
819 kauth_cred_unref(&scred
);
823 bzero(&ai
, sizeof(ai
));
824 ai
.ai_auid
= scred
->cr_audit
.as_aia_p
->ai_auid
;
825 ai
.ai_asid
= scred
->cr_audit
.as_aia_p
->ai_asid
;
828 * Only superuser gets to see the real mask.
830 if (suser(scred
, &p
->p_acflag
)) {
831 ai
.ai_mask
.am_success
= ~0;
832 ai
.ai_mask
.am_failure
= ~0;
834 ai
.ai_mask
.am_success
= scred
->cr_audit
.as_mask
.am_success
;
835 ai
.ai_mask
.am_failure
= scred
->cr_audit
.as_mask
.am_failure
;
837 ai
.ai_termid
.machine
= scred
->cr_audit
.as_aia_p
->ai_termid
.at_addr
[0];
838 ai
.ai_termid
.port
= scred
->cr_audit
.as_aia_p
->ai_termid
.at_port
;
839 kauth_cred_unref(&scred
);
841 return (copyout(&ai
, user_addr
, sizeof (ai
)));
845 * System calls to get and set process audit information.
849 getaudit(proc_t p
, struct getaudit_args
*uap
, __unused
int32_t *retval
)
854 error
= mac_proc_check_getaudit(p
);
858 return (getaudit_internal(p
, uap
->auditinfo
));
863 setaudit(proc_t p
, struct setaudit_args
*uap
, __unused
int32_t *retval
)
866 struct auditinfo_addr newaia
;
870 error
= copyin(uap
->auditinfo
, &ai
, sizeof(ai
));
873 AUDIT_ARG(auditinfo
, &ai
);
875 if (ai
.ai_asid
!= AU_ASSIGN_ASID
&&
876 (uint32_t)ai
.ai_asid
> ASSIGNED_ASID_MAX
)
881 struct auditinfo_addr aia
= {
882 .ai_auid
= ai
.ai_auid
,
883 .ai_mask
= ai
.ai_mask
,
885 .at_port
= ai
.ai_termid
.port
,
887 .at_addr
= { ai
.ai_termid
.machine
, 0, 0, 0 } },
888 .ai_asid
= ai
.ai_asid
,
890 error
= mac_proc_check_setaudit(p
, &aia
);
896 bzero(&newaia
, sizeof(newaia
));
897 scred
= kauth_cred_proc_ref(p
);
898 error
= suser(scred
, &p
->p_acflag
);
900 kauth_cred_unref(&scred
);
903 newaia
.ai_flags
= scred
->cr_audit
.as_aia_p
->ai_flags
;
904 kauth_cred_unref(&scred
);
906 WARN_IF_BAD_ASID(ai
.ai_asid
, "setaudit(2)");
908 newaia
.ai_auid
= ai
.ai_auid
;
909 bcopy(&ai
.ai_mask
, &newaia
.ai_mask
, sizeof(au_mask_t
));
910 AUDIT_CHECK_IF_KEVENTS_MASK(ai
.ai_mask
);
911 newaia
.ai_asid
= ai
.ai_asid
;
912 if (ai
.ai_asid
== AU_DEFAUDITSID
)
913 newaia
.ai_asid
= AU_ASSIGN_ASID
;
915 newaia
.ai_asid
= ai
.ai_asid
;
916 newaia
.ai_termid
.at_addr
[0] = ai
.ai_termid
.machine
;
917 newaia
.ai_termid
.at_port
= ai
.ai_termid
.port
;
918 newaia
.ai_termid
.at_type
= AU_IPv4
;
920 error
= audit_session_setaia(p
, &newaia
, 0);
925 * If asked to assign an ASID then let the user know what the ASID is
926 * by copying the auditinfo struct back out.
928 if (newaia
.ai_asid
== AU_ASSIGN_ASID
)
929 error
= getaudit_internal(p
, uap
->auditinfo
);
935 getaudit_addr_internal(proc_t p
, user_addr_t user_addr
, size_t length
)
938 auditinfo_addr_t aia
;
940 scred
= kauth_cred_proc_ref(p
);
941 bcopy(scred
->cr_audit
.as_aia_p
, &aia
, sizeof (auditinfo_addr_t
));
943 * Only superuser gets to see the real mask.
945 if (suser(scred
, &p
->p_acflag
)) {
946 aia
.ai_mask
.am_success
= ~0;
947 aia
.ai_mask
.am_failure
= ~0;
949 kauth_cred_unref(&scred
);
951 return (copyout(&aia
, user_addr
, min(sizeof(aia
), length
)));
956 getaudit_addr(proc_t p
, struct getaudit_addr_args
*uap
,
957 __unused
int32_t *retval
)
960 WARN_IF_AINFO_ADDR_CHANGED(uap
->length
, sizeof(auditinfo_addr_t
),
961 "getaudit_addr(2)", "auditinfo_addr_t");
963 return (getaudit_addr_internal(p
, uap
->auditinfo_addr
, uap
->length
));
968 setaudit_addr(proc_t p
, struct setaudit_addr_args
*uap
,
969 __unused
int32_t *retval
)
971 struct auditinfo_addr aia
;
975 bzero(&aia
, sizeof(auditinfo_addr_t
));
976 error
= copyin(uap
->auditinfo_addr
, &aia
,
977 min(sizeof(aia
), uap
->length
));
980 AUDIT_ARG(auditinfo_addr
, &aia
);
981 if (aia
.ai_termid
.at_type
!= AU_IPv6
&&
982 aia
.ai_termid
.at_type
!= AU_IPv4
)
984 if (aia
.ai_asid
!= AU_ASSIGN_ASID
&&
985 (uint32_t)aia
.ai_asid
> ASSIGNED_ASID_MAX
)
989 error
= mac_proc_check_setaudit(p
, &aia
);
994 scred
= kauth_cred_proc_ref(p
);
995 error
= suser(scred
, &p
->p_acflag
);
997 kauth_cred_unref(&scred
);
1001 WARN_IF_AINFO_ADDR_CHANGED(uap
->length
, sizeof(auditinfo_addr_t
),
1002 "setaudit_addr(2)", "auditinfo_addr_t");
1003 WARN_IF_BAD_ASID(aia
.ai_asid
, "setaudit_addr(2)");
1004 kauth_cred_unref(&scred
);
1006 AUDIT_CHECK_IF_KEVENTS_MASK(aia
.ai_mask
);
1007 if (aia
.ai_asid
== AU_DEFAUDITSID
)
1008 aia
.ai_asid
= AU_ASSIGN_ASID
;
1010 error
= audit_session_setaia(p
, &aia
, 0);
1015 * If asked to assign an ASID then let the user know what the ASID is
1016 * by copying the auditinfo_addr struct back out.
1018 if (aia
.ai_asid
== AU_ASSIGN_ASID
)
1019 error
= getaudit_addr_internal(p
, uap
->auditinfo_addr
,
1026 * Syscall to manage audit files.
1031 auditctl(proc_t p
, struct auditctl_args
*uap
, __unused
int32_t *retval
)
1033 struct nameidata nd
;
1038 error
= suser(kauth_cred_get(), &p
->p_acflag
);
1046 * If a path is specified, open the replacement vnode, perform
1047 * validity checks, and grab another reference to the current
1050 * XXX Changes API slightly. NULL path no longer disables audit but
1053 if (uap
->path
== USER_ADDR_NULL
)
1056 NDINIT(&nd
, LOOKUP
, FOLLOW
| LOCKLEAF
| AUDITVNPATH1
,
1057 (IS_64BIT_PROCESS(p
) ? UIO_USERSPACE64
:
1058 UIO_USERSPACE32
), uap
->path
, vfs_context_current());
1059 error
= vn_open(&nd
, AUDIT_OPEN_FLAGS
, 0);
1065 * Accessibility of the vnode was determined in vn_open; the
1066 * mac_system_check_auditctl should only determine whether that vnode
1067 * is appropriate for storing audit data, or that the caller was
1068 * permitted to control the auditing system at all. For example, a
1069 * confidentiality policy may want to ensure that audit files are
1070 * always high sensitivity.
1072 error
= mac_system_check_auditctl(kauth_cred_get(), vp
);
1074 vn_close(vp
, AUDIT_CLOSE_FLAGS
, vfs_context_current());
1079 if (vp
->v_type
!= VREG
) {
1080 vn_close(vp
, AUDIT_CLOSE_FLAGS
, vfs_context_current());
1084 mtx_lock(&audit_mtx
);
1086 * XXXAUDIT: Should audit_suspended actually be cleared by
1089 audit_suspended
= 0;
1090 mtx_unlock(&audit_mtx
);
1093 * The following gets unreferenced in audit_rotate_vnode()
1094 * after the rotation and it is no longer needed.
1096 cred
= kauth_cred_get_with_ref();
1097 audit_rotate_vnode(cred
, vp
);
1103 #else /* !CONFIG_AUDIT */
1106 audit(proc_t p
, struct audit_args
*uap
, int32_t *retval
)
1108 #pragma unused(p, uap, retval)
1114 auditon(proc_t p
, struct auditon_args
*uap
, int32_t *retval
)
1116 #pragma unused(p, uap, retval)
1122 getauid(proc_t p
, struct getauid_args
*uap
, int32_t *retval
)
1124 #pragma unused(p, uap, retval)
1130 setauid(proc_t p
, struct setauid_args
*uap
, int32_t *retval
)
1132 #pragma unused(p, uap, retval)
1138 getaudit(proc_t p
, struct getaudit_args
*uap
, int32_t *retval
)
1140 #pragma unused(p, uap, retval)
1146 setaudit(proc_t p
, struct setaudit_args
*uap
, int32_t *retval
)
1148 #pragma unused(p, uap, retval)
1154 getaudit_addr(proc_t p
, struct getaudit_addr_args
*uap
, int32_t *retval
)
1156 #pragma unused(p, uap, retval)
1162 setaudit_addr(proc_t p
, struct setaudit_addr_args
*uap
, int32_t *retval
)
1164 #pragma unused(p, uap, retval)
1170 auditctl(proc_t p
, struct auditctl_args
*uap
, int32_t *retval
)
1172 #pragma unused(p, uap, retval)
1177 #endif /* CONFIG_AUDIT */