2 * Copyright (c) 1999-2019 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. Neither the name of Apple Inc. ("Apple") nor the names of
13 * its contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR
20 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
24 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
25 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
29 * NOTICE: This file was modified by McAfee Research in 2004 to introduce
30 * support for mandatory and extensible security protections. This notice
31 * is included in support of clause 2.2 (b) of the Apple Public License,
35 #include <sys/param.h>
36 #include <sys/fcntl.h>
37 #include <sys/kernel.h>
39 #include <sys/namei.h>
40 #include <sys/proc_internal.h>
41 #include <sys/kauth.h>
42 #include <sys/queue.h>
43 #include <sys/systm.h>
45 #include <sys/ucred.h>
47 #include <sys/unistd.h>
48 #include <sys/file_internal.h>
49 #include <sys/vnode_internal.h>
51 #include <sys/syscall.h>
52 #include <sys/malloc.h>
54 #include <sys/sysent.h>
55 #include <sys/sysproto.h>
56 #include <sys/vfs_context.h>
57 #include <sys/domain.h>
58 #include <sys/protosw.h>
59 #include <sys/socketvar.h>
61 #include <bsm/audit.h>
62 #include <bsm/audit_internal.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/sched_prim.h>
77 #include <bsm/audit_record.h>
78 #include <security/mac.h>
79 #include <security/mac_framework.h>
80 #include <security/mac_policy.h>
83 #include <net/route.h>
85 #include <netinet/in.h>
86 #include <netinet/in_pcb.h>
88 #include <IOKit/IOBSD.h>
92 #define IS_NOT_VALID_PID(p) ((p) < 1 || (p) > PID_MAX)
94 #ifdef AUDIT_API_WARNINGS
96 * Macro to warn about auditinfo_addr_t/auditpinfo_addr_t changing sizes
97 * to encourage the userland code to be recompiled and updated.
99 #define WARN_IF_AINFO_ADDR_CHANGED(sz1, sz2, scall, tp) do { \
100 if ((size_t)(sz1) != (size_t)(sz2)) { \
101 char pn[MAXCOMLEN + 1]; \
103 proc_selfname(pn, MAXCOMLEN + 1); \
104 printf("Size of %s used by %s in %s is different from " \
105 "kernel's. Please recompile %s.\n", (tp), \
111 * Macro to warn about using ASID's outside the range [1 to PID_MAX] to
112 * encourage userland code changes.
114 #define WARN_IF_BAD_ASID(asid, scall) do { \
115 if (((asid) < 1 || (asid) > PID_MAX) && \
116 (asid) != AU_ASSIGN_ASID) { \
117 char pn[MAXCOMLEN + 1]; \
119 proc_selfname(pn, MAXCOMLEN + 1); \
120 printf("%s in %s is using an ASID (%u) outside the " \
121 "range [1 to %d]. Please change %s to use an ASID "\
122 "within this range or use AU_ASSIGN_ASID.\n", \
123 (scall), pn, (uint32_t)(asid), PID_MAX, pn); \
127 #else /* ! AUDIT_API_WARNINGS */
129 #define WARN_IF_AINFO_ADDR_CHANGED(sz1, sz2, scall, tp) do { \
132 #define WARN_IF_BAD_ASID(asid, scall) do { \
135 #endif /* AUDIT_API_WARNINGS */
138 * System call to allow a user space application to submit a BSM audit record
139 * to the kernel for inclusion in the audit log. This function does little
140 * verification on the audit record that is submitted.
142 * XXXAUDIT: Audit preselection for user records does not currently work,
143 * since we pre-select only based on the AUE_audit event type, not the event
144 * type submitted as part of the user audit data.
148 audit(proc_t p
, struct audit_args
*uap
, __unused
int32_t *retval
)
152 void * full_rec
= NULL
;
153 struct kaudit_record
*ar
= NULL
;
154 struct uthread
*uthr
= NULL
;
155 int add_identity_token
= 1;
156 int max_record_length
= MAX_AUDIT_RECORD_SIZE
;
159 struct au_identity_info id_info
= {
162 .signing_id_trunc
= 0,
168 token_t
*id_tok
= NULL
;
169 boolean_t kern_events_allowed
= FALSE
;
170 char *signing_id
= NULL
;
171 char process_name
[MAXCOMLEN
+ 1] = {};
174 error
= suser(kauth_cred_get(), &p
->p_acflag
);
177 * If a process is not running as root but is properly
178 * entitled, allow it to audit non-kernel events only.
180 if (!IOTaskHasEntitlement(current_task(),
181 AU_AUDIT_USER_ENTITLEMENT
)) {
185 kern_events_allowed
= TRUE
;
188 mtx_lock(&audit_mtx
);
189 max_record_length
= MIN(audit_qctrl
.aq_bufsz
, MAX_AUDIT_RECORD_SIZE
);
190 mtx_unlock(&audit_mtx
);
192 if (IOTaskHasEntitlement(current_task(),
193 AU_CLASS_RESERVED_ENTITLEMENT
)) {
194 /* Entitled tasks are trusted to add appropriate identity info */
195 add_identity_token
= 0;
198 * If the caller is unentitled, an identity token will be added and
199 * the space must be accounted for
201 max_record_length
-= MAX_AUDIT_IDENTITY_SIZE
;
204 if ((uap
->length
<= 0) || (uap
->length
> max_record_length
)) {
212 * If there's no current audit record (audit() itself not audited)
213 * commit the user audit record.
218 /* can this happen? */
224 * This is not very efficient; we're required to allocate a
225 * complete kernel audit record just so the user record can
228 uthr
->uu_ar
= audit_new(AUE_NULL
, p
, uthr
);
229 if (uthr
->uu_ar
== NULL
) {
236 rec
= malloc(uap
->length
, M_AUDITDATA
, M_WAITOK
);
242 error
= copyin(uap
->record
, rec
, uap
->length
);
248 error
= mac_system_check_audit(kauth_cred_get(), rec
, uap
->length
);
254 /* Verify the record. */
255 if (bsm_rec_verify(rec
, uap
->length
, kern_events_allowed
) == 0) {
260 if (add_identity_token
) {
261 struct hdr_tok_partial
*hdr
;
262 struct trl_tok_partial
*trl
;
263 int bytes_copied
= 0;
265 /* Create a new identity token for this buffer */
266 audit_identity_info_construct(&id_info
);
267 id_tok
= au_to_identity(id_info
.signer_type
, id_info
.signing_id
,
268 id_info
.signing_id_trunc
, id_info
.team_id
, id_info
.team_id_trunc
,
269 id_info
.cdhash
, id_info
.cdhash_len
);
275 /* Splice the record together using a new buffer */
276 full_rec
= malloc(uap
->length
+ id_tok
->len
, M_AUDITDATA
, M_WAITOK
);
282 signing_id
= id_info
.signing_id
;
283 signer_type
= id_info
.signer_type
;
285 /* Copy the original buffer up to but not including the trailer */
286 memcpy(full_rec
, rec
, uap
->length
- AUDIT_TRAILER_SIZE
);
287 bytes_copied
= uap
->length
- AUDIT_TRAILER_SIZE
;
289 /* Copy the identity token */
290 memcpy(full_rec
+ bytes_copied
, id_tok
->t_data
, id_tok
->len
);
291 bytes_copied
+= id_tok
->len
;
293 /* Copy the old trailer */
294 memcpy(full_rec
+ bytes_copied
,
295 rec
+ (uap
->length
- AUDIT_TRAILER_SIZE
), AUDIT_TRAILER_SIZE
);
296 bytes_copied
+= AUDIT_TRAILER_SIZE
;
298 /* Fix the record size stored in the header token */
299 hdr
= (struct hdr_tok_partial
*)full_rec
;
300 hdr
->len
= htonl(bytes_copied
);
302 /* Fix the record size stored in the trailer token */
303 trl
= (struct trl_tok_partial
*)
304 (full_rec
+ bytes_copied
- AUDIT_TRAILER_SIZE
);
305 trl
->len
= htonl(bytes_copied
);
315 * Attach the user audit record to the kernel audit record. Because
316 * this system call is an auditable event, we will write the user
317 * record along with the record for this audit event.
319 * XXXAUDIT: KASSERT appropriate starting values of k_udata, k_ulen,
320 * k_ar_commit & AR_COMMIT_USER?
324 ar
->k_ar_commit
|= AR_COMMIT_USER
;
327 * Currently we assume that all preselection has been performed in
328 * userspace. We unconditionally set these masks so that the records
329 * get committed both to the trail and pipe. In the future we will
330 * want to setup kernel based preselection.
332 ar
->k_ar_commit
|= (AR_PRESELECT_USER_TRAIL
| AR_PRESELECT_USER_PIPE
);
334 // Send data for analytics for non-platform binaries only
335 if (signer_type
== 0 && add_identity_token
) {
336 proc_name(proc_pid(p
), process_name
, sizeof(process_name
));
337 (void)audit_send_analytics(signing_id
, process_name
);
342 * If rec was allocated, it must be freed if an identity token was added
343 * (since full_rec will be used) OR there was an error (since nothing
344 * will be attached to the kernel structure).
346 if (rec
&& (add_identity_token
|| error
)) {
347 free(rec
, M_AUDITDATA
);
350 /* Only free full_rec if an error occurred */
351 if (full_rec
&& error
) {
352 free(full_rec
, M_AUDITDATA
);
355 audit_identity_info_destruct(&id_info
);
357 if (id_tok
->t_data
) {
358 free(id_tok
->t_data
, M_AUDITBSM
);
360 free(id_tok
, M_AUDITBSM
);
367 * System call to manipulate auditing.
371 auditon(proc_t p
, struct auditon_args
*uap
, __unused
int32_t *retval
)
375 union auditon_udata udata
;
376 proc_t tp
= PROC_NULL
;
377 struct auditinfo_addr aia
;
379 AUDIT_ARG(cmd
, uap
->cmd
);
382 error
= mac_system_check_auditon(kauth_cred_get(), uap
->cmd
);
388 if ((uap
->length
<= 0) || (uap
->length
>
389 (int)sizeof(union auditon_udata
))) {
393 memset((void *)&udata
, 0, sizeof(udata
));
396 * Some of the GET commands use the arguments too.
415 case A_GETPINFO_ADDR
:
417 case A_GETSINFO_ADDR
:
422 error
= copyin(uap
->data
, (void *)&udata
, uap
->length
);
426 AUDIT_ARG(auditon
, &udata
);
427 AUDIT_ARG(len
, uap
->length
);
431 /* Check appropriate privilege. */
434 * A_GETSINFO doesn't require priviledge but only superuser
435 * gets to see the audit masks.
437 case A_GETSINFO_ADDR
:
438 if ((sizeof(udata
.au_kau_info
) != uap
->length
) ||
439 (audit_session_lookup(udata
.au_kau_info
.ai_asid
,
440 &udata
.au_kau_info
) != 0)) {
442 } else if (!kauth_cred_issuser(kauth_cred_get())) {
443 udata
.au_kau_info
.ai_mask
.am_success
= ~0;
444 udata
.au_kau_info
.ai_mask
.am_failure
= ~0;
449 /* Getting one's own audit session flags requires no
450 * privilege. Setting the flags is subject to access
451 * control implemented in audit_session_setaia().
456 if (!IOTaskHasEntitlement(current_task(),
457 AU_CLASS_RESERVED_ENTITLEMENT
)) {
462 error
= suser(kauth_cred_get(), &p
->p_acflag
);
470 * If the audit subsytem is in external control mode, additional
471 * privilege checks are required for a subset of auditon commands
473 if (audit_ctl_mode
== AUDIT_CTLMODE_EXTERNAL
) {
479 if (!IOTaskHasEntitlement(current_task(),
480 AU_CLASS_RESERVED_ENTITLEMENT
)) {
491 * XXX Need to implement these commands by accessing the global
492 * values associated with the commands.
497 if (sizeof(udata
.au_policy64
) == uap
->length
) {
498 mtx_lock(&audit_mtx
);
499 if (!audit_fail_stop
) {
500 udata
.au_policy64
|= AUDIT_CNT
;
502 if (audit_panic_on_write_fail
) {
503 udata
.au_policy64
|= AUDIT_AHLT
;
506 udata
.au_policy64
|= AUDIT_ARGV
;
509 udata
.au_policy64
|= AUDIT_ARGE
;
511 mtx_unlock(&audit_mtx
);
514 if (sizeof(udata
.au_policy
) != uap
->length
) {
517 mtx_lock(&audit_mtx
);
518 if (!audit_fail_stop
) {
519 udata
.au_policy
|= AUDIT_CNT
;
521 if (audit_panic_on_write_fail
) {
522 udata
.au_policy
|= AUDIT_AHLT
;
525 udata
.au_policy
|= AUDIT_ARGV
;
528 udata
.au_policy
|= AUDIT_ARGE
;
530 mtx_unlock(&audit_mtx
);
535 if (sizeof(udata
.au_policy64
) == uap
->length
) {
536 if (udata
.au_policy64
& ~(AUDIT_CNT
| AUDIT_AHLT
|
537 AUDIT_ARGV
| AUDIT_ARGE
)) {
540 mtx_lock(&audit_mtx
);
541 audit_fail_stop
= ((udata
.au_policy64
& AUDIT_CNT
) ==
543 audit_panic_on_write_fail
= (udata
.au_policy64
&
545 audit_argv
= (udata
.au_policy64
& AUDIT_ARGV
);
546 audit_arge
= (udata
.au_policy64
& AUDIT_ARGE
);
547 mtx_unlock(&audit_mtx
);
550 if ((sizeof(udata
.au_policy
) != uap
->length
) ||
551 (udata
.au_policy
& ~(AUDIT_CNT
| AUDIT_AHLT
| AUDIT_ARGV
|
556 * XXX - Need to wake up waiters if the policy relaxes?
558 mtx_lock(&audit_mtx
);
559 audit_fail_stop
= ((udata
.au_policy
& AUDIT_CNT
) == 0);
560 audit_panic_on_write_fail
= (udata
.au_policy
& AUDIT_AHLT
);
561 audit_argv
= (udata
.au_policy
& AUDIT_ARGV
);
562 audit_arge
= (udata
.au_policy
& AUDIT_ARGE
);
563 mtx_unlock(&audit_mtx
);
567 if (sizeof(udata
.au_mask
) != uap
->length
) {
570 mtx_lock(&audit_mtx
);
571 udata
.au_mask
= audit_nae_mask
;
572 mtx_unlock(&audit_mtx
);
576 if (sizeof(udata
.au_mask
) != uap
->length
) {
579 mtx_lock(&audit_mtx
);
580 audit_nae_mask
= udata
.au_mask
;
581 AUDIT_CHECK_IF_KEVENTS_MASK(audit_nae_mask
);
582 mtx_unlock(&audit_mtx
);
587 if (sizeof(udata
.au_qctrl64
) == uap
->length
) {
588 mtx_lock(&audit_mtx
);
589 udata
.au_qctrl64
.aq64_hiwater
=
590 (u_int64_t
)audit_qctrl
.aq_hiwater
;
591 udata
.au_qctrl64
.aq64_lowater
=
592 (u_int64_t
)audit_qctrl
.aq_lowater
;
593 udata
.au_qctrl64
.aq64_bufsz
=
594 (u_int64_t
)audit_qctrl
.aq_bufsz
;
595 udata
.au_qctrl64
.aq64_delay
=
596 (u_int64_t
)audit_qctrl
.aq_delay
;
597 udata
.au_qctrl64
.aq64_minfree
=
598 (int64_t)audit_qctrl
.aq_minfree
;
599 mtx_unlock(&audit_mtx
);
602 if (sizeof(udata
.au_qctrl
) != uap
->length
) {
605 mtx_lock(&audit_mtx
);
606 udata
.au_qctrl
= audit_qctrl
;
607 mtx_unlock(&audit_mtx
);
612 if (sizeof(udata
.au_qctrl64
) == uap
->length
) {
613 if ((udata
.au_qctrl64
.aq64_hiwater
> AQ_MAXHIGH
) ||
614 (udata
.au_qctrl64
.aq64_lowater
>=
615 udata
.au_qctrl64
.aq64_hiwater
) ||
616 (udata
.au_qctrl64
.aq64_bufsz
> AQ_MAXBUFSZ
) ||
617 (udata
.au_qctrl64
.aq64_minfree
< 0) ||
618 (udata
.au_qctrl64
.aq64_minfree
> 100)) {
621 mtx_lock(&audit_mtx
);
622 audit_qctrl
.aq_hiwater
=
623 (int)udata
.au_qctrl64
.aq64_hiwater
;
624 audit_qctrl
.aq_lowater
=
625 (int)udata
.au_qctrl64
.aq64_lowater
;
626 audit_qctrl
.aq_bufsz
=
627 (int)udata
.au_qctrl64
.aq64_bufsz
;
628 audit_qctrl
.aq_minfree
=
629 (int)udata
.au_qctrl64
.aq64_minfree
;
630 audit_qctrl
.aq_delay
= -1; /* Not used. */
631 mtx_unlock(&audit_mtx
);
634 if ((sizeof(udata
.au_qctrl
) != uap
->length
) ||
635 (udata
.au_qctrl
.aq_hiwater
> AQ_MAXHIGH
) ||
636 (udata
.au_qctrl
.aq_lowater
>= udata
.au_qctrl
.aq_hiwater
) ||
637 (udata
.au_qctrl
.aq_bufsz
> AQ_MAXBUFSZ
) ||
638 (udata
.au_qctrl
.aq_minfree
< 0) ||
639 (udata
.au_qctrl
.aq_minfree
> 100)) {
643 mtx_lock(&audit_mtx
);
644 audit_qctrl
= udata
.au_qctrl
;
645 /* XXX The queue delay value isn't used with the kernel. */
646 audit_qctrl
.aq_delay
= -1;
647 mtx_unlock(&audit_mtx
);
670 if (sizeof(udata
.au_cond64
) == uap
->length
) {
671 mtx_lock(&audit_mtx
);
672 if (audit_enabled
&& !audit_suspended
) {
673 udata
.au_cond64
= AUC_AUDITING
;
675 udata
.au_cond64
= AUC_NOAUDIT
;
677 mtx_unlock(&audit_mtx
);
680 if (sizeof(udata
.au_cond
) != uap
->length
) {
683 mtx_lock(&audit_mtx
);
684 if (audit_enabled
&& !audit_suspended
) {
685 udata
.au_cond
= AUC_AUDITING
;
687 udata
.au_cond
= AUC_NOAUDIT
;
689 mtx_unlock(&audit_mtx
);
694 if (sizeof(udata
.au_cond64
) == uap
->length
) {
695 mtx_lock(&audit_mtx
);
696 if (udata
.au_cond64
== AUC_NOAUDIT
) {
699 if (udata
.au_cond64
== AUC_AUDITING
) {
702 if (udata
.au_cond64
== AUC_DISABLED
) {
704 mtx_unlock(&audit_mtx
);
708 mtx_unlock(&audit_mtx
);
711 if (sizeof(udata
.au_cond
) != uap
->length
) {
714 mtx_lock(&audit_mtx
);
715 if (udata
.au_cond
== AUC_NOAUDIT
) {
718 if (udata
.au_cond
== AUC_AUDITING
) {
721 if (udata
.au_cond
== AUC_DISABLED
) {
723 mtx_unlock(&audit_mtx
);
727 mtx_unlock(&audit_mtx
);
731 if (sizeof(udata
.au_evclass
) != uap
->length
) {
734 udata
.au_evclass
.ec_class
= au_event_class(
735 udata
.au_evclass
.ec_number
);
739 if (sizeof(udata
.au_evclass
) != uap
->length
) {
742 au_evclassmap_insert(udata
.au_evclass
.ec_number
,
743 udata
.au_evclass
.ec_class
);
747 if ((sizeof(udata
.au_aupinfo
) != uap
->length
) ||
748 IS_NOT_VALID_PID(udata
.au_aupinfo
.ap_pid
)) {
751 if ((tp
= proc_find(udata
.au_aupinfo
.ap_pid
)) == NULL
) {
755 scred
= kauth_cred_proc_ref(tp
);
756 if (scred
->cr_audit
.as_aia_p
->ai_termid
.at_type
== AU_IPv6
) {
757 kauth_cred_unref(&scred
);
762 udata
.au_aupinfo
.ap_auid
=
763 scred
->cr_audit
.as_aia_p
->ai_auid
;
764 udata
.au_aupinfo
.ap_mask
.am_success
=
765 scred
->cr_audit
.as_mask
.am_success
;
766 udata
.au_aupinfo
.ap_mask
.am_failure
=
767 scred
->cr_audit
.as_mask
.am_failure
;
768 udata
.au_aupinfo
.ap_termid
.machine
=
769 scred
->cr_audit
.as_aia_p
->ai_termid
.at_addr
[0];
770 udata
.au_aupinfo
.ap_termid
.port
=
771 scred
->cr_audit
.as_aia_p
->ai_termid
.at_port
;
772 udata
.au_aupinfo
.ap_asid
=
773 scred
->cr_audit
.as_aia_p
->ai_asid
;
774 kauth_cred_unref(&scred
);
780 if ((sizeof(udata
.au_aupinfo
) != uap
->length
) ||
781 IS_NOT_VALID_PID(udata
.au_aupinfo
.ap_pid
)) {
784 if ((tp
= proc_find(udata
.au_aupinfo
.ap_pid
)) == NULL
) {
787 scred
= kauth_cred_proc_ref(tp
);
788 bcopy(scred
->cr_audit
.as_aia_p
, &aia
, sizeof(aia
));
789 kauth_cred_unref(&scred
);
790 aia
.ai_mask
.am_success
=
791 udata
.au_aupinfo
.ap_mask
.am_success
;
792 aia
.ai_mask
.am_failure
=
793 udata
.au_aupinfo
.ap_mask
.am_failure
;
794 AUDIT_CHECK_IF_KEVENTS_MASK(aia
.ai_mask
);
795 error
= audit_session_setaia(tp
, &aia
);
804 if ((sizeof(udata
.au_fstat
) != uap
->length
) ||
805 ((udata
.au_fstat
.af_filesz
!= 0) &&
806 (udata
.au_fstat
.af_filesz
< MIN_AUDIT_FILE_SIZE
))) {
809 mtx_lock(&audit_mtx
);
810 audit_fstat
.af_filesz
= udata
.au_fstat
.af_filesz
;
811 mtx_unlock(&audit_mtx
);
815 if (sizeof(udata
.au_fstat
) != uap
->length
) {
818 mtx_lock(&audit_mtx
);
819 udata
.au_fstat
.af_filesz
= audit_fstat
.af_filesz
;
820 udata
.au_fstat
.af_currsz
= audit_fstat
.af_currsz
;
821 mtx_unlock(&audit_mtx
);
824 case A_GETPINFO_ADDR
:
825 if ((sizeof(udata
.au_aupinfo_addr
) != uap
->length
) ||
826 IS_NOT_VALID_PID(udata
.au_aupinfo_addr
.ap_pid
)) {
829 if ((tp
= proc_find(udata
.au_aupinfo
.ap_pid
)) == NULL
) {
832 WARN_IF_AINFO_ADDR_CHANGED(uap
->length
,
833 sizeof(auditpinfo_addr_t
), "auditon(A_GETPINFO_ADDR,...)",
834 "auditpinfo_addr_t");
835 scred
= kauth_cred_proc_ref(tp
);
836 udata
.au_aupinfo_addr
.ap_auid
=
837 scred
->cr_audit
.as_aia_p
->ai_auid
;
838 udata
.au_aupinfo_addr
.ap_asid
=
839 scred
->cr_audit
.as_aia_p
->ai_asid
;
840 udata
.au_aupinfo_addr
.ap_mask
.am_success
=
841 scred
->cr_audit
.as_mask
.am_success
;
842 udata
.au_aupinfo_addr
.ap_mask
.am_failure
=
843 scred
->cr_audit
.as_mask
.am_failure
;
844 bcopy(&scred
->cr_audit
.as_aia_p
->ai_termid
,
845 &udata
.au_aupinfo_addr
.ap_termid
,
846 sizeof(au_tid_addr_t
));
847 udata
.au_aupinfo_addr
.ap_flags
=
848 scred
->cr_audit
.as_aia_p
->ai_flags
;
849 kauth_cred_unref(&scred
);
855 if (sizeof(udata
.au_kau_info
) != uap
->length
) {
858 audit_get_kinfo(&udata
.au_kau_info
);
862 if ((sizeof(udata
.au_kau_info
) != uap
->length
) ||
863 (udata
.au_kau_info
.ai_termid
.at_type
!= AU_IPv4
&&
864 udata
.au_kau_info
.ai_termid
.at_type
!= AU_IPv6
)) {
867 audit_set_kinfo(&udata
.au_kau_info
);
871 if ((sizeof(udata
.au_trigger
) != uap
->length
) ||
872 (udata
.au_trigger
< AUDIT_TRIGGER_MIN
) ||
873 (udata
.au_trigger
> AUDIT_TRIGGER_MAX
)) {
876 return audit_send_trigger(udata
.au_trigger
);
878 case A_GETSINFO_ADDR
:
879 /* Handled above before switch(). */
883 if (sizeof(udata
.au_flags
) != uap
->length
) {
886 bcopy(&(kauth_cred_get()->cr_audit
.as_aia_p
->ai_flags
),
887 &udata
.au_flags
, sizeof(udata
.au_flags
));
891 if (sizeof(udata
.au_flags
) != uap
->length
) {
894 bcopy(kauth_cred_get()->cr_audit
.as_aia_p
, &aia
, sizeof(aia
));
895 aia
.ai_flags
= udata
.au_flags
;
896 error
= audit_session_setaia(p
, &aia
);
903 if (sizeof(udata
.au_ctl_mode
) != uap
->length
) {
906 mtx_lock(&audit_mtx
);
907 udata
.au_ctl_mode
= audit_ctl_mode
;
908 mtx_unlock(&audit_mtx
);
912 if (sizeof(udata
.au_ctl_mode
) != uap
->length
) {
916 mtx_lock(&audit_mtx
);
918 if (udata
.au_ctl_mode
== AUDIT_CTLMODE_NORMAL
) {
919 audit_ctl_mode
= AUDIT_CTLMODE_NORMAL
;
920 } else if (udata
.au_ctl_mode
== AUDIT_CTLMODE_EXTERNAL
) {
921 audit_ctl_mode
= AUDIT_CTLMODE_EXTERNAL
;
923 mtx_unlock(&audit_mtx
);
927 mtx_unlock(&audit_mtx
);
931 if (sizeof(udata
.au_expire_after
) != uap
->length
) {
934 mtx_lock(&audit_mtx
);
935 udata
.au_expire_after
.age
= audit_expire_after
.age
;
936 udata
.au_expire_after
.size
= audit_expire_after
.size
;
937 udata
.au_expire_after
.op_type
= audit_expire_after
.op_type
;
938 mtx_unlock(&audit_mtx
);
942 if (sizeof(udata
.au_expire_after
) != uap
->length
) {
945 mtx_lock(&audit_mtx
);
946 audit_expire_after
.age
= udata
.au_expire_after
.age
;
947 audit_expire_after
.size
= udata
.au_expire_after
.size
;
948 audit_expire_after
.op_type
= udata
.au_expire_after
.op_type
;
949 mtx_unlock(&audit_mtx
);
957 * Copy data back to userspace for the GET comands.
973 case A_GETPINFO_ADDR
:
975 case A_GETSINFO_ADDR
:
979 error
= copyout((void *)&udata
, uap
->data
, uap
->length
);
990 * System calls to manage the user audit information.
994 getauid(proc_t p
, struct getauid_args
*uap
, __unused
int32_t *retval
)
1001 error
= mac_proc_check_getauid(p
);
1006 scred
= kauth_cred_proc_ref(p
);
1007 id
= scred
->cr_audit
.as_aia_p
->ai_auid
;
1008 kauth_cred_unref(&scred
);
1010 error
= copyout((void *)&id
, uap
->auid
, sizeof(id
));
1020 setauid(proc_t p
, struct setauid_args
*uap
, __unused
int32_t *retval
)
1025 struct auditinfo_addr aia
;
1027 error
= copyin(uap
->auid
, &id
, sizeof(id
));
1031 AUDIT_ARG(auid
, id
);
1034 error
= mac_proc_check_setauid(p
, id
);
1040 scred
= kauth_cred_proc_ref(p
);
1041 error
= suser(scred
, &p
->p_acflag
);
1043 kauth_cred_unref(&scred
);
1047 bcopy(scred
->cr_audit
.as_aia_p
, &aia
, sizeof(aia
));
1048 if (aia
.ai_asid
== AU_DEFAUDITSID
) {
1049 aia
.ai_asid
= AU_ASSIGN_ASID
;
1051 bcopy(&scred
->cr_audit
.as_mask
, &aia
.ai_mask
, sizeof(au_mask_t
));
1052 kauth_cred_unref(&scred
);
1054 error
= audit_session_setaia(p
, &aia
);
1060 getaudit_addr_internal(proc_t p
, user_addr_t user_addr
, size_t length
)
1063 auditinfo_addr_t aia
;
1065 scred
= kauth_cred_proc_ref(p
);
1066 bcopy(scred
->cr_audit
.as_aia_p
, &aia
, sizeof(auditinfo_addr_t
));
1068 * Only superuser gets to see the real mask.
1070 if (suser(scred
, &p
->p_acflag
)) {
1071 aia
.ai_mask
.am_success
= ~0;
1072 aia
.ai_mask
.am_failure
= ~0;
1074 kauth_cred_unref(&scred
);
1076 return copyout(&aia
, user_addr
, min(sizeof(aia
), length
));
1081 getaudit_addr(proc_t p
, struct getaudit_addr_args
*uap
,
1082 __unused
int32_t *retval
)
1085 int error
= mac_proc_check_getaudit(p
);
1090 #endif /* CONFIG_MACF */
1091 WARN_IF_AINFO_ADDR_CHANGED(uap
->length
, sizeof(auditinfo_addr_t
),
1092 "getaudit_addr(2)", "auditinfo_addr_t");
1094 return getaudit_addr_internal(p
, uap
->auditinfo_addr
, uap
->length
);
1099 setaudit_addr(proc_t p
, struct setaudit_addr_args
*uap
,
1100 __unused
int32_t *retval
)
1102 struct auditinfo_addr aia
;
1106 bzero(&aia
, sizeof(auditinfo_addr_t
));
1107 error
= copyin(uap
->auditinfo_addr
, &aia
,
1108 min(sizeof(aia
), uap
->length
));
1112 AUDIT_ARG(auditinfo_addr
, &aia
);
1113 if (aia
.ai_termid
.at_type
!= AU_IPv6
&&
1114 aia
.ai_termid
.at_type
!= AU_IPv4
) {
1117 if (aia
.ai_asid
!= AU_ASSIGN_ASID
&&
1118 (uint32_t)aia
.ai_asid
> ASSIGNED_ASID_MAX
) {
1123 error
= mac_proc_check_setaudit(p
, &aia
);
1129 scred
= kauth_cred_proc_ref(p
);
1130 error
= suser(scred
, &p
->p_acflag
);
1132 kauth_cred_unref(&scred
);
1136 WARN_IF_AINFO_ADDR_CHANGED(uap
->length
, sizeof(auditinfo_addr_t
),
1137 "setaudit_addr(2)", "auditinfo_addr_t");
1138 WARN_IF_BAD_ASID(aia
.ai_asid
, "setaudit_addr(2)");
1139 kauth_cred_unref(&scred
);
1141 AUDIT_CHECK_IF_KEVENTS_MASK(aia
.ai_mask
);
1142 if (aia
.ai_asid
== AU_DEFAUDITSID
) {
1143 aia
.ai_asid
= AU_ASSIGN_ASID
;
1146 error
= audit_session_setaia(p
, &aia
);
1152 * If asked to assign an ASID then let the user know what the ASID is
1153 * by copying the auditinfo_addr struct back out.
1155 if (aia
.ai_asid
== AU_ASSIGN_ASID
) {
1156 error
= getaudit_addr_internal(p
, uap
->auditinfo_addr
,
1164 * Syscall to manage audit files.
1169 auditctl(proc_t p
, struct auditctl_args
*uap
, __unused
int32_t *retval
)
1171 struct nameidata nd
;
1175 au_ctlmode_t ctlmode
;
1177 error
= suser(kauth_cred_get(), &p
->p_acflag
);
1182 ctlmode
= audit_ctl_mode
;
1185 * Do not allow setting of a path when auditing is in reserved mode
1187 if (ctlmode
== AUDIT_CTLMODE_EXTERNAL
&&
1188 !IOTaskHasEntitlement(current_task(), AU_AUDITCTL_RESERVED_ENTITLEMENT
)) {
1196 * If a path is specified, open the replacement vnode, perform
1197 * validity checks, and grab another reference to the current
1200 * XXX Changes API slightly. NULL path no longer disables audit but
1203 if (uap
->path
== USER_ADDR_NULL
) {
1207 NDINIT(&nd
, LOOKUP
, OP_OPEN
, FOLLOW
| LOCKLEAF
| AUDITVNPATH1
,
1208 (IS_64BIT_PROCESS(p
) ? UIO_USERSPACE64
:
1209 UIO_USERSPACE32
), uap
->path
, vfs_context_current());
1210 error
= vn_open(&nd
, AUDIT_OPEN_FLAGS
, 0);
1217 * Accessibility of the vnode was determined in vn_open; the
1218 * mac_system_check_auditctl should only determine whether that vnode
1219 * is appropriate for storing audit data, or that the caller was
1220 * permitted to control the auditing system at all. For example, a
1221 * confidentiality policy may want to ensure that audit files are
1222 * always high sensitivity.
1224 error
= mac_system_check_auditctl(kauth_cred_get(), vp
);
1226 vn_close(vp
, AUDIT_CLOSE_FLAGS
, vfs_context_current());
1231 if (vp
->v_type
!= VREG
) {
1232 vn_close(vp
, AUDIT_CLOSE_FLAGS
, vfs_context_current());
1236 mtx_lock(&audit_mtx
);
1238 * XXXAUDIT: Should audit_suspended actually be cleared by
1241 audit_suspended
= 0;
1242 mtx_unlock(&audit_mtx
);
1245 * The following gets unreferenced in audit_rotate_vnode()
1246 * after the rotation and it is no longer needed.
1248 cred
= kauth_cred_get_with_ref();
1249 audit_rotate_vnode(cred
, vp
);
1255 #else /* !CONFIG_AUDIT */
1258 audit(proc_t p
, struct audit_args
*uap
, int32_t *retval
)
1260 #pragma unused(p, uap, retval)
1266 auditon(proc_t p
, struct auditon_args
*uap
, int32_t *retval
)
1268 #pragma unused(p, uap, retval)
1274 getauid(proc_t p
, struct getauid_args
*uap
, int32_t *retval
)
1276 #pragma unused(p, uap, retval)
1282 setauid(proc_t p
, struct setauid_args
*uap
, int32_t *retval
)
1284 #pragma unused(p, uap, retval)
1290 getaudit_addr(proc_t p
, struct getaudit_addr_args
*uap
, int32_t *retval
)
1292 #pragma unused(p, uap, retval)
1298 setaudit_addr(proc_t p
, struct setaudit_addr_args
*uap
, int32_t *retval
)
1300 #pragma unused(p, uap, retval)
1306 auditctl(proc_t p
, struct auditctl_args
*uap
, int32_t *retval
)
1308 #pragma unused(p, uap, retval)
1313 #endif /* CONFIG_AUDIT */