2 * Copyright (c) 1999-2010, 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/wait_queue.h>
77 #include <kern/sched_prim.h>
80 #include <bsm/audit_record.h>
81 #include <security/mac.h>
82 #include <security/mac_framework.h>
83 #include <security/mac_policy.h>
86 #include <net/route.h>
88 #include <netinet/in.h>
89 #include <netinet/in_pcb.h>
93 #define IS_NOT_VALID_PID(p) ((p) < 1 || (p) > PID_MAX)
95 #ifdef AUDIT_API_WARNINGS
97 * Macro to warn about auditinfo_addr_t/auditpinfo_addr_t changing sizes
98 * to encourage the userland code to be recompiled and updated.
100 #define WARN_IF_AINFO_ADDR_CHANGED(sz1, sz2, scall, tp) do { \
101 if ((size_t)(sz1) != (size_t)(sz2)) { \
102 char pn[MAXCOMLEN + 1]; \
104 proc_selfname(pn, MAXCOMLEN + 1); \
105 printf("Size of %s used by %s in %s is different from " \
106 "kernel's. Please recompile %s.\n", (tp), \
112 * Macro to warn about using ASID's outside the range [1 to PID_MAX] to
113 * encourage userland code changes.
115 #define WARN_IF_BAD_ASID(asid, scall) do { \
116 if (((asid) < 1 || (asid) > PID_MAX) && \
117 (asid) != AU_ASSIGN_ASID) { \
118 char pn[MAXCOMLEN + 1]; \
120 proc_selfname(pn, MAXCOMLEN + 1); \
121 printf("%s in %s is using an ASID (%u) outside the " \
122 "range [1 to %d]. Please change %s to use an ASID "\
123 "within this range or use AU_ASSIGN_ASID.\n", \
124 (scall), pn, (uint32_t)(asid), PID_MAX, pn); \
128 #else /* ! AUDIT_API_WARNINGS */
130 #define WARN_IF_AINFO_ADDR_CHANGED(sz1, sz2, scall, tp) do { \
133 #define WARN_IF_BAD_ASID(asid, scall) do { \
136 #endif /* AUDIT_API_WARNINGS */
139 * System call to allow a user space application to submit a BSM audit record
140 * to the kernel for inclusion in the audit log. This function does little
141 * verification on the audit record that is submitted.
143 * XXXAUDIT: Audit preselection for user records does not currently work,
144 * since we pre-select only based on the AUE_audit event type, not the event
145 * type submitted as part of the user audit data.
149 audit(proc_t p
, struct audit_args
*uap
, __unused
int32_t *retval
)
153 struct kaudit_record
*ar
;
154 struct uthread
*uthr
;
156 error
= suser(kauth_cred_get(), &p
->p_acflag
);
160 mtx_lock(&audit_mtx
);
161 if ((uap
->length
<= 0) || (uap
->length
> (int)audit_qctrl
.aq_bufsz
)) {
162 mtx_unlock(&audit_mtx
);
165 mtx_unlock(&audit_mtx
);
170 * If there's no current audit record (audit() itself not audited)
171 * commit the user audit record.
175 if (uthr
== NULL
) /* can this happen? */
179 * This is not very efficient; we're required to allocate a
180 * complete kernel audit record just so the user record can
183 uthr
->uu_ar
= audit_new(AUE_NULL
, p
, uthr
);
184 if (uthr
->uu_ar
== NULL
)
189 if (uap
->length
> MAX_AUDIT_RECORD_SIZE
)
192 rec
= malloc(uap
->length
, M_AUDITDATA
, M_WAITOK
);
194 error
= copyin(uap
->record
, rec
, uap
->length
);
199 error
= mac_system_check_audit(kauth_cred_get(), rec
, uap
->length
);
204 /* Verify the record. */
205 if (bsm_rec_verify(rec
) == 0) {
211 * Attach the user audit record to the kernel audit record. Because
212 * this system call is an auditable event, we will write the user
213 * record along with the record for this audit event.
215 * XXXAUDIT: KASSERT appropriate starting values of k_udata, k_ulen,
216 * k_ar_commit & AR_COMMIT_USER?
219 ar
->k_ulen
= uap
->length
;
220 ar
->k_ar_commit
|= AR_COMMIT_USER
;
223 * Currently we assume that all preselection has been performed in
224 * userspace. We unconditionally set these masks so that the records
225 * get committed both to the trail and pipe. In the future we will
226 * want to setup kernel based preselection.
228 ar
->k_ar_commit
|= (AR_PRESELECT_USER_TRAIL
| AR_PRESELECT_USER_PIPE
);
233 * audit_syscall_exit() will free the audit record on the thread even
234 * if we allocated it above.
236 free(rec
, M_AUDITDATA
);
241 * System call to manipulate auditing.
245 auditon(proc_t p
, struct auditon_args
*uap
, __unused
int32_t *retval
)
249 union auditon_udata udata
;
250 proc_t tp
= PROC_NULL
;
251 struct auditinfo_addr aia
;
253 AUDIT_ARG(cmd
, uap
->cmd
);
256 error
= mac_system_check_auditon(kauth_cred_get(), uap
->cmd
);
261 if ((uap
->length
<= 0) || (uap
->length
>
262 (int)sizeof(union auditon_udata
)))
265 memset((void *)&udata
, 0, sizeof(udata
));
268 * Some of the GET commands use the arguments too.
287 case A_GETPINFO_ADDR
:
289 case A_GETSINFO_ADDR
:
292 error
= copyin(uap
->data
, (void *)&udata
, uap
->length
);
295 AUDIT_ARG(auditon
, &udata
);
296 AUDIT_ARG(len
, uap
->length
);
300 /* Check appropriate privilege. */
303 * A_GETSINFO doesn't require priviledge but only superuser
304 * gets to see the audit masks.
306 case A_GETSINFO_ADDR
:
307 if ((sizeof(udata
.au_kau_info
) != uap
->length
) ||
308 (audit_session_lookup(udata
.au_kau_info
.ai_asid
,
309 &udata
.au_kau_info
) != 0))
311 else if (!kauth_cred_issuser(kauth_cred_get())) {
312 udata
.au_kau_info
.ai_mask
.am_success
= ~0;
313 udata
.au_kau_info
.ai_mask
.am_failure
= ~0;
318 /* Getting one's own audit session flags requires no
319 * privilege. Setting the flags is subject to access
320 * control implemented in audit_session_setaia().
324 error
= suser(kauth_cred_get(), &p
->p_acflag
);
331 * XXX Need to implement these commands by accessing the global
332 * values associated with the commands.
337 if (sizeof(udata
.au_policy64
) == uap
->length
) {
338 mtx_lock(&audit_mtx
);
339 if (!audit_fail_stop
)
340 udata
.au_policy64
|= AUDIT_CNT
;
341 if (audit_panic_on_write_fail
)
342 udata
.au_policy64
|= AUDIT_AHLT
;
344 udata
.au_policy64
|= AUDIT_ARGV
;
346 udata
.au_policy64
|= AUDIT_ARGE
;
347 mtx_unlock(&audit_mtx
);
350 if (sizeof(udata
.au_policy
) != uap
->length
)
352 mtx_lock(&audit_mtx
);
353 if (!audit_fail_stop
)
354 udata
.au_policy
|= AUDIT_CNT
;
355 if (audit_panic_on_write_fail
)
356 udata
.au_policy
|= AUDIT_AHLT
;
358 udata
.au_policy
|= AUDIT_ARGV
;
360 udata
.au_policy
|= AUDIT_ARGE
;
361 mtx_unlock(&audit_mtx
);
366 if (sizeof(udata
.au_policy64
) == uap
->length
) {
367 if (udata
.au_policy64
& ~(AUDIT_CNT
|AUDIT_AHLT
|
368 AUDIT_ARGV
|AUDIT_ARGE
))
370 mtx_lock(&audit_mtx
);
371 audit_fail_stop
= ((udata
.au_policy64
& AUDIT_CNT
) ==
373 audit_panic_on_write_fail
= (udata
.au_policy64
&
375 audit_argv
= (udata
.au_policy64
& AUDIT_ARGV
);
376 audit_arge
= (udata
.au_policy64
& AUDIT_ARGE
);
377 mtx_unlock(&audit_mtx
);
380 if ((sizeof(udata
.au_policy
) != uap
->length
) ||
381 (udata
.au_policy
& ~(AUDIT_CNT
|AUDIT_AHLT
|AUDIT_ARGV
|
385 * XXX - Need to wake up waiters if the policy relaxes?
387 mtx_lock(&audit_mtx
);
388 audit_fail_stop
= ((udata
.au_policy
& AUDIT_CNT
) == 0);
389 audit_panic_on_write_fail
= (udata
.au_policy
& AUDIT_AHLT
);
390 audit_argv
= (udata
.au_policy
& AUDIT_ARGV
);
391 audit_arge
= (udata
.au_policy
& AUDIT_ARGE
);
392 mtx_unlock(&audit_mtx
);
396 if (sizeof(udata
.au_mask
) != uap
->length
)
398 mtx_lock(&audit_mtx
);
399 udata
.au_mask
= audit_nae_mask
;
400 mtx_unlock(&audit_mtx
);
404 if (sizeof(udata
.au_mask
) != uap
->length
)
406 mtx_lock(&audit_mtx
);
407 audit_nae_mask
= udata
.au_mask
;
408 AUDIT_CHECK_IF_KEVENTS_MASK(audit_nae_mask
);
409 mtx_unlock(&audit_mtx
);
414 if (sizeof(udata
.au_qctrl64
) == uap
->length
) {
415 mtx_lock(&audit_mtx
);
416 udata
.au_qctrl64
.aq64_hiwater
=
417 (u_int64_t
)audit_qctrl
.aq_hiwater
;
418 udata
.au_qctrl64
.aq64_lowater
=
419 (u_int64_t
)audit_qctrl
.aq_lowater
;
420 udata
.au_qctrl64
.aq64_bufsz
=
421 (u_int64_t
)audit_qctrl
.aq_bufsz
;
422 udata
.au_qctrl64
.aq64_delay
=
423 (u_int64_t
)audit_qctrl
.aq_delay
;
424 udata
.au_qctrl64
.aq64_minfree
=
425 (int64_t)audit_qctrl
.aq_minfree
;
426 mtx_unlock(&audit_mtx
);
429 if (sizeof(udata
.au_qctrl
) != uap
->length
)
431 mtx_lock(&audit_mtx
);
432 udata
.au_qctrl
= audit_qctrl
;
433 mtx_unlock(&audit_mtx
);
438 if (sizeof(udata
.au_qctrl64
) == uap
->length
) {
439 if ((udata
.au_qctrl64
.aq64_hiwater
> AQ_MAXHIGH
) ||
440 (udata
.au_qctrl64
.aq64_lowater
>=
441 udata
.au_qctrl64
.aq64_hiwater
) ||
442 (udata
.au_qctrl64
.aq64_bufsz
> AQ_MAXBUFSZ
) ||
443 (udata
.au_qctrl64
.aq64_minfree
< 0) ||
444 (udata
.au_qctrl64
.aq64_minfree
> 100))
446 mtx_lock(&audit_mtx
);
447 audit_qctrl
.aq_hiwater
=
448 (int)udata
.au_qctrl64
.aq64_hiwater
;
449 audit_qctrl
.aq_lowater
=
450 (int)udata
.au_qctrl64
.aq64_lowater
;
451 audit_qctrl
.aq_bufsz
=
452 (int)udata
.au_qctrl64
.aq64_bufsz
;
453 audit_qctrl
.aq_minfree
=
454 (int)udata
.au_qctrl64
.aq64_minfree
;
455 audit_qctrl
.aq_delay
= -1; /* Not used. */
456 mtx_unlock(&audit_mtx
);
459 if ((sizeof(udata
.au_qctrl
) != uap
->length
) ||
460 (udata
.au_qctrl
.aq_hiwater
> AQ_MAXHIGH
) ||
461 (udata
.au_qctrl
.aq_lowater
>= udata
.au_qctrl
.aq_hiwater
) ||
462 (udata
.au_qctrl
.aq_bufsz
> AQ_MAXBUFSZ
) ||
463 (udata
.au_qctrl
.aq_minfree
< 0) ||
464 (udata
.au_qctrl
.aq_minfree
> 100))
467 mtx_lock(&audit_mtx
);
468 audit_qctrl
= udata
.au_qctrl
;
469 /* XXX The queue delay value isn't used with the kernel. */
470 audit_qctrl
.aq_delay
= -1;
471 mtx_unlock(&audit_mtx
);
494 if (sizeof(udata
.au_cond64
) == uap
->length
) {
495 mtx_lock(&audit_mtx
);
496 if (audit_enabled
&& !audit_suspended
)
497 udata
.au_cond64
= AUC_AUDITING
;
499 udata
.au_cond64
= AUC_NOAUDIT
;
500 mtx_unlock(&audit_mtx
);
503 if (sizeof(udata
.au_cond
) != uap
->length
)
505 mtx_lock(&audit_mtx
);
506 if (audit_enabled
&& !audit_suspended
)
507 udata
.au_cond
= AUC_AUDITING
;
509 udata
.au_cond
= AUC_NOAUDIT
;
510 mtx_unlock(&audit_mtx
);
515 if (sizeof(udata
.au_cond64
) == uap
->length
) {
516 mtx_lock(&audit_mtx
);
517 if (udata
.au_cond64
== AUC_NOAUDIT
)
519 if (udata
.au_cond64
== AUC_AUDITING
)
521 if (udata
.au_cond64
== AUC_DISABLED
) {
523 mtx_unlock(&audit_mtx
);
527 mtx_unlock(&audit_mtx
);
530 if (sizeof(udata
.au_cond
) != uap
->length
) {
533 mtx_lock(&audit_mtx
);
534 if (udata
.au_cond
== AUC_NOAUDIT
)
536 if (udata
.au_cond
== AUC_AUDITING
)
538 if (udata
.au_cond
== AUC_DISABLED
) {
540 mtx_unlock(&audit_mtx
);
544 mtx_unlock(&audit_mtx
);
548 if (sizeof(udata
.au_evclass
) != uap
->length
)
550 udata
.au_evclass
.ec_class
= au_event_class(
551 udata
.au_evclass
.ec_number
);
555 if (sizeof(udata
.au_evclass
) != uap
->length
)
557 au_evclassmap_insert(udata
.au_evclass
.ec_number
,
558 udata
.au_evclass
.ec_class
);
562 if ((sizeof(udata
.au_aupinfo
) != uap
->length
) ||
563 IS_NOT_VALID_PID(udata
.au_aupinfo
.ap_pid
))
565 if ((tp
= proc_find(udata
.au_aupinfo
.ap_pid
)) == NULL
)
568 scred
= kauth_cred_proc_ref(tp
);
569 if (scred
->cr_audit
.as_aia_p
->ai_termid
.at_type
== AU_IPv6
) {
570 kauth_cred_unref(&scred
);
575 udata
.au_aupinfo
.ap_auid
=
576 scred
->cr_audit
.as_aia_p
->ai_auid
;
577 udata
.au_aupinfo
.ap_mask
.am_success
=
578 scred
->cr_audit
.as_mask
.am_success
;
579 udata
.au_aupinfo
.ap_mask
.am_failure
=
580 scred
->cr_audit
.as_mask
.am_failure
;
581 udata
.au_aupinfo
.ap_termid
.machine
=
582 scred
->cr_audit
.as_aia_p
->ai_termid
.at_addr
[0];
583 udata
.au_aupinfo
.ap_termid
.port
=
584 scred
->cr_audit
.as_aia_p
->ai_termid
.at_port
;
585 udata
.au_aupinfo
.ap_asid
=
586 scred
->cr_audit
.as_aia_p
->ai_asid
;
587 kauth_cred_unref(&scred
);
593 if ((sizeof(udata
.au_aupinfo
) != uap
->length
) ||
594 IS_NOT_VALID_PID(udata
.au_aupinfo
.ap_pid
))
596 if ((tp
= proc_find(udata
.au_aupinfo
.ap_pid
)) == NULL
)
598 scred
= kauth_cred_proc_ref(tp
);
599 bcopy(scred
->cr_audit
.as_aia_p
, &aia
, sizeof(aia
));
600 kauth_cred_unref(&scred
);
601 aia
.ai_mask
.am_success
=
602 udata
.au_aupinfo
.ap_mask
.am_success
;
603 aia
.ai_mask
.am_failure
=
604 udata
.au_aupinfo
.ap_mask
.am_failure
;
605 AUDIT_CHECK_IF_KEVENTS_MASK(aia
.ai_mask
);
606 error
= audit_session_setaia(tp
, &aia
);
614 if ((sizeof(udata
.au_fstat
) != uap
->length
) ||
615 ((udata
.au_fstat
.af_filesz
!= 0) &&
616 (udata
.au_fstat
.af_filesz
< MIN_AUDIT_FILE_SIZE
)))
618 mtx_lock(&audit_mtx
);
619 audit_fstat
.af_filesz
= udata
.au_fstat
.af_filesz
;
620 mtx_unlock(&audit_mtx
);
624 if (sizeof(udata
.au_fstat
) != uap
->length
)
626 mtx_lock(&audit_mtx
);
627 udata
.au_fstat
.af_filesz
= audit_fstat
.af_filesz
;
628 udata
.au_fstat
.af_currsz
= audit_fstat
.af_currsz
;
629 mtx_unlock(&audit_mtx
);
632 case A_GETPINFO_ADDR
:
633 if ((sizeof(udata
.au_aupinfo_addr
) != uap
->length
) ||
634 IS_NOT_VALID_PID(udata
.au_aupinfo_addr
.ap_pid
))
636 if ((tp
= proc_find(udata
.au_aupinfo
.ap_pid
)) == NULL
)
638 WARN_IF_AINFO_ADDR_CHANGED(uap
->length
,
639 sizeof(auditpinfo_addr_t
), "auditon(A_GETPINFO_ADDR,...)",
640 "auditpinfo_addr_t");
641 scred
= kauth_cred_proc_ref(tp
);
642 udata
.au_aupinfo_addr
.ap_auid
=
643 scred
->cr_audit
.as_aia_p
->ai_auid
;
644 udata
.au_aupinfo_addr
.ap_asid
=
645 scred
->cr_audit
.as_aia_p
->ai_asid
;
646 udata
.au_aupinfo_addr
.ap_mask
.am_success
=
647 scred
->cr_audit
.as_mask
.am_success
;
648 udata
.au_aupinfo_addr
.ap_mask
.am_failure
=
649 scred
->cr_audit
.as_mask
.am_failure
;
650 bcopy(&scred
->cr_audit
.as_aia_p
->ai_termid
,
651 &udata
.au_aupinfo_addr
.ap_termid
,
652 sizeof(au_tid_addr_t
));
653 udata
.au_aupinfo_addr
.ap_flags
=
654 scred
->cr_audit
.as_aia_p
->ai_flags
;
655 kauth_cred_unref(&scred
);
661 if (sizeof(udata
.au_kau_info
) != uap
->length
)
663 audit_get_kinfo(&udata
.au_kau_info
);
667 if ((sizeof(udata
.au_kau_info
) != uap
->length
) ||
668 (udata
.au_kau_info
.ai_termid
.at_type
!= AU_IPv4
&&
669 udata
.au_kau_info
.ai_termid
.at_type
!= AU_IPv6
))
671 audit_set_kinfo(&udata
.au_kau_info
);
675 if ((sizeof(udata
.au_trigger
) != uap
->length
) ||
676 (udata
.au_trigger
< AUDIT_TRIGGER_MIN
) ||
677 (udata
.au_trigger
> AUDIT_TRIGGER_MAX
))
679 return (audit_send_trigger(udata
.au_trigger
));
681 case A_GETSINFO_ADDR
:
682 /* Handled above before switch(). */
686 if (sizeof(udata
.au_flags
) != uap
->length
)
688 bcopy(&(kauth_cred_get()->cr_audit
.as_aia_p
->ai_flags
),
689 &udata
.au_flags
, sizeof(udata
.au_flags
));
693 if (sizeof(udata
.au_flags
) != uap
->length
)
695 bcopy(kauth_cred_get()->cr_audit
.as_aia_p
, &aia
, sizeof(aia
));
696 aia
.ai_flags
= udata
.au_flags
;
697 error
= audit_session_setaia(p
, &aia
);
707 * Copy data back to userspace for the GET comands.
723 case A_GETPINFO_ADDR
:
725 case A_GETSINFO_ADDR
:
727 error
= copyout((void *)&udata
, uap
->data
, uap
->length
);
737 * System calls to manage the user audit information.
741 getauid(proc_t p
, struct getauid_args
*uap
, __unused
int32_t *retval
)
748 error
= mac_proc_check_getauid(p
);
752 scred
= kauth_cred_proc_ref(p
);
753 id
= scred
->cr_audit
.as_aia_p
->ai_auid
;
754 kauth_cred_unref(&scred
);
756 error
= copyout((void *)&id
, uap
->auid
, sizeof(id
));
765 setauid(proc_t p
, struct setauid_args
*uap
, __unused
int32_t *retval
)
770 struct auditinfo_addr aia
;
772 error
= copyin(uap
->auid
, &id
, sizeof(id
));
778 error
= mac_proc_check_setauid(p
, id
);
783 scred
= kauth_cred_proc_ref(p
);
784 error
= suser(scred
, &p
->p_acflag
);
786 kauth_cred_unref(&scred
);
790 bcopy(scred
->cr_audit
.as_aia_p
, &aia
, sizeof(aia
));
791 if (aia
.ai_asid
== AU_DEFAUDITSID
) {
792 aia
.ai_asid
= AU_ASSIGN_ASID
;
794 bcopy(&scred
->cr_audit
.as_mask
, &aia
.ai_mask
, sizeof(au_mask_t
));
795 kauth_cred_unref(&scred
);
797 error
= audit_session_setaia(p
, &aia
);
803 getaudit_addr_internal(proc_t p
, user_addr_t user_addr
, size_t length
)
806 auditinfo_addr_t aia
;
808 scred
= kauth_cred_proc_ref(p
);
809 bcopy(scred
->cr_audit
.as_aia_p
, &aia
, sizeof (auditinfo_addr_t
));
811 * Only superuser gets to see the real mask.
813 if (suser(scred
, &p
->p_acflag
)) {
814 aia
.ai_mask
.am_success
= ~0;
815 aia
.ai_mask
.am_failure
= ~0;
817 kauth_cred_unref(&scred
);
819 return (copyout(&aia
, user_addr
, min(sizeof(aia
), length
)));
824 getaudit_addr(proc_t p
, struct getaudit_addr_args
*uap
,
825 __unused
int32_t *retval
)
828 int error
= mac_proc_check_getaudit(p
);
832 #endif /* CONFIG_MACF */
833 WARN_IF_AINFO_ADDR_CHANGED(uap
->length
, sizeof(auditinfo_addr_t
),
834 "getaudit_addr(2)", "auditinfo_addr_t");
836 return (getaudit_addr_internal(p
, uap
->auditinfo_addr
, uap
->length
));
841 setaudit_addr(proc_t p
, struct setaudit_addr_args
*uap
,
842 __unused
int32_t *retval
)
844 struct auditinfo_addr aia
;
848 bzero(&aia
, sizeof(auditinfo_addr_t
));
849 error
= copyin(uap
->auditinfo_addr
, &aia
,
850 min(sizeof(aia
), uap
->length
));
853 AUDIT_ARG(auditinfo_addr
, &aia
);
854 if (aia
.ai_termid
.at_type
!= AU_IPv6
&&
855 aia
.ai_termid
.at_type
!= AU_IPv4
)
857 if (aia
.ai_asid
!= AU_ASSIGN_ASID
&&
858 (uint32_t)aia
.ai_asid
> ASSIGNED_ASID_MAX
)
862 error
= mac_proc_check_setaudit(p
, &aia
);
867 scred
= kauth_cred_proc_ref(p
);
868 error
= suser(scred
, &p
->p_acflag
);
870 kauth_cred_unref(&scred
);
874 WARN_IF_AINFO_ADDR_CHANGED(uap
->length
, sizeof(auditinfo_addr_t
),
875 "setaudit_addr(2)", "auditinfo_addr_t");
876 WARN_IF_BAD_ASID(aia
.ai_asid
, "setaudit_addr(2)");
877 kauth_cred_unref(&scred
);
879 AUDIT_CHECK_IF_KEVENTS_MASK(aia
.ai_mask
);
880 if (aia
.ai_asid
== AU_DEFAUDITSID
)
881 aia
.ai_asid
= AU_ASSIGN_ASID
;
883 error
= audit_session_setaia(p
, &aia
);
888 * If asked to assign an ASID then let the user know what the ASID is
889 * by copying the auditinfo_addr struct back out.
891 if (aia
.ai_asid
== AU_ASSIGN_ASID
)
892 error
= getaudit_addr_internal(p
, uap
->auditinfo_addr
,
899 * Syscall to manage audit files.
904 auditctl(proc_t p
, struct auditctl_args
*uap
, __unused
int32_t *retval
)
911 error
= suser(kauth_cred_get(), &p
->p_acflag
);
919 * If a path is specified, open the replacement vnode, perform
920 * validity checks, and grab another reference to the current
923 * XXX Changes API slightly. NULL path no longer disables audit but
926 if (uap
->path
== USER_ADDR_NULL
)
929 NDINIT(&nd
, LOOKUP
, OP_OPEN
, FOLLOW
| LOCKLEAF
| AUDITVNPATH1
,
930 (IS_64BIT_PROCESS(p
) ? UIO_USERSPACE64
:
931 UIO_USERSPACE32
), uap
->path
, vfs_context_current());
932 error
= vn_open(&nd
, AUDIT_OPEN_FLAGS
, 0);
938 * Accessibility of the vnode was determined in vn_open; the
939 * mac_system_check_auditctl should only determine whether that vnode
940 * is appropriate for storing audit data, or that the caller was
941 * permitted to control the auditing system at all. For example, a
942 * confidentiality policy may want to ensure that audit files are
943 * always high sensitivity.
945 error
= mac_system_check_auditctl(kauth_cred_get(), vp
);
947 vn_close(vp
, AUDIT_CLOSE_FLAGS
, vfs_context_current());
952 if (vp
->v_type
!= VREG
) {
953 vn_close(vp
, AUDIT_CLOSE_FLAGS
, vfs_context_current());
957 mtx_lock(&audit_mtx
);
959 * XXXAUDIT: Should audit_suspended actually be cleared by
963 mtx_unlock(&audit_mtx
);
966 * The following gets unreferenced in audit_rotate_vnode()
967 * after the rotation and it is no longer needed.
969 cred
= kauth_cred_get_with_ref();
970 audit_rotate_vnode(cred
, vp
);
976 #else /* !CONFIG_AUDIT */
979 audit(proc_t p
, struct audit_args
*uap
, int32_t *retval
)
981 #pragma unused(p, uap, retval)
987 auditon(proc_t p
, struct auditon_args
*uap
, int32_t *retval
)
989 #pragma unused(p, uap, retval)
995 getauid(proc_t p
, struct getauid_args
*uap
, int32_t *retval
)
997 #pragma unused(p, uap, retval)
1003 setauid(proc_t p
, struct setauid_args
*uap
, int32_t *retval
)
1005 #pragma unused(p, uap, retval)
1011 getaudit_addr(proc_t p
, struct getaudit_addr_args
*uap
, int32_t *retval
)
1013 #pragma unused(p, uap, retval)
1019 setaudit_addr(proc_t p
, struct setaudit_addr_args
*uap
, int32_t *retval
)
1021 #pragma unused(p, uap, retval)
1027 auditctl(proc_t p
, struct auditctl_args
*uap
, int32_t *retval
)
1029 #pragma unused(p, uap, retval)
1034 #endif /* CONFIG_AUDIT */