2 * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
23 /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
25 * Copyright (c) 1982, 1986, 1989, 1990, 1991, 1993
26 * The Regents of the University of California. All rights reserved.
27 * (c) UNIX System Laboratories, Inc.
28 * All or some portions of this file are derived from material licensed
29 * to the University of California by American Telephone and Telegraph
30 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
31 * the permission of UNIX System Laboratories, Inc.
33 * Redistribution and use in source and binary forms, with or without
34 * modification, are permitted provided that the following conditions
36 * 1. Redistributions of source code must retain the above copyright
37 * notice, this list of conditions and the following disclaimer.
38 * 2. Redistributions in binary form must reproduce the above copyright
39 * notice, this list of conditions and the following disclaimer in the
40 * documentation and/or other materials provided with the distribution.
41 * 3. All advertising materials mentioning features or use of this software
42 * must display the following acknowledgement:
43 * This product includes software developed by the University of
44 * California, Berkeley and its contributors.
45 * 4. Neither the name of the University nor the names of its contributors
46 * may be used to endorse or promote products derived from this software
47 * without specific prior written permission.
49 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
50 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
53 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
58 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
61 * @(#)kern_prot.c 8.9 (Berkeley) 2/14/95
65 * System calls related to processes and protection
68 #include <sys/param.h>
70 #include <sys/systm.h>
71 #include <sys/ucred.h>
72 #include <sys/proc_internal.h>
74 #include <sys/kauth.h>
75 #include <sys/timeb.h>
76 #include <sys/times.h>
77 #include <sys/malloc.h>
79 #include <bsm/audit_kernel.h>
81 #include <sys/mount_internal.h>
82 #include <sys/sysproto.h>
83 #include <mach/message.h>
84 #include <mach/host_security.h>
86 #include <kern/host.h>
88 int groupmember(gid_t gid
, kauth_cred_t cred
);
92 extern int prepare_profile_database(int user
);
95 * setprivexec: (dis)allow this process to hold
96 * task, thread, or execption ports of processes about to exec.
99 setprivexec(struct proc
*p
, struct setprivexec_args
*uap
, register_t
*retval
)
101 AUDIT_ARG(value
, uap
->flag
);
102 *retval
= p
->p_debugger
;
103 p
->p_debugger
= (uap
->flag
!= 0);
109 getpid(struct proc
*p
, __unused
struct getpid_args
*uap
, register_t
*retval
)
118 getppid(struct proc
*p
, __unused
struct getppid_args
*uap
, register_t
*retval
)
121 *retval
= p
->p_pptr
->p_pid
;
125 /* Get process group ID; note that POSIX getpgrp takes no parameter */
127 getpgrp(struct proc
*p
, __unused
struct getpgrp_args
*uap
, register_t
*retval
)
130 *retval
= p
->p_pgrp
->pg_id
;
134 /* Get an arbitary pid's process group id */
136 getpgid(struct proc
*p
, struct getpgid_args
*uap
, register_t
*retval
)
144 if ((pt
= pfind(uap
->pid
)) == 0)
147 *retval
= pt
->p_pgrp
->pg_id
;
152 * Get an arbitary pid's session id.
156 getsid(struct proc
*p
, struct getsid_args
*uap
, register_t
*retval
)
164 if ((pt
= pfind(uap
->pid
)) == 0)
167 *retval
= pt
->p_session
->s_sid
;
173 getuid(__unused
struct proc
*p
, __unused
struct getuid_args
*uap
, register_t
*retval
)
176 *retval
= kauth_getruid();
182 geteuid(__unused
struct proc
*p
, __unused
struct geteuid_args
*uap
, register_t
*retval
)
185 *retval
= kauth_getuid();
190 * Return the per-thread override identity.
193 gettid(__unused
struct proc
*p
, struct gettid_args
*uap
, register_t
*retval
)
195 struct uthread
*uthread
= get_bsdthread_info(current_thread());
199 * If this thread is not running with an override identity, we can't
200 * return one to the caller, so return an error instead.
202 if (!(uthread
->uu_flag
& UT_SETUID
))
205 if ((error
= suword(uap
->uidp
, uthread
->uu_ucred
->cr_ruid
)))
207 if ((error
= suword(uap
->gidp
, uthread
->uu_ucred
->cr_rgid
)))
216 getgid(__unused
struct proc
*p
, __unused
struct getgid_args
*uap
, register_t
*retval
)
219 *retval
= kauth_getrgid();
224 * Get effective group ID. The "egid" is groups[0], and could be obtained
225 * via getgroups. This syscall exists because it is somewhat painful to do
226 * correctly in a library function.
230 getegid(struct proc
*p
, __unused
struct getegid_args
*uap
, register_t
*retval
)
233 *retval
= kauth_getgid();
238 getgroups(__unused
struct proc
*p
, struct getgroups_args
*uap
, register_t
*retval
)
244 /* grab reference while we muck around with the credential */
245 cred
= kauth_cred_get_with_ref();
247 if ((ngrp
= uap
->gidsetsize
) == 0) {
248 *retval
= cred
->cr_ngroups
;
249 kauth_cred_rele(cred
);
252 if (ngrp
< cred
->cr_ngroups
) {
253 kauth_cred_rele(cred
);
256 ngrp
= cred
->cr_ngroups
;
257 if ((error
= copyout((caddr_t
)cred
->cr_groups
,
259 ngrp
* sizeof(gid_t
)))) {
260 kauth_cred_rele(cred
);
263 kauth_cred_rele(cred
);
269 * Return the per-thread/per-process supplementary groups list.
271 #warning XXX implement
273 getsgroups(__unused
struct proc
*p
, __unused
struct getsgroups_args
*uap
, __unused register_t
*retval
)
280 * Return the per-thread/per-process whiteout groups list.
282 #warning XXX implement
284 getwgroups(__unused
struct proc
*p
, __unused
struct getwgroups_args
*uap
, __unused register_t
*retval
)
292 setsid(struct proc
*p
, __unused
struct setsid_args
*uap
, register_t
*retval
)
295 if (p
->p_pgid
== p
->p_pid
|| pgfind(p
->p_pid
) || p
->p_flag
& P_INVFORK
) {
298 (void)enterpgrp(p
, p
->p_pid
, 1);
305 * set process group (setpgid/old setpgrp)
307 * caller does setpgid(targpid, targpgid)
309 * pid must be caller or child of caller (ESRCH)
311 * pid must be in same session (EPERM)
312 * pid can't have done an exec (EACCES)
313 * ig pgid is -ve return EINVAL (as per SUV spec)
315 * there must exist some pid in same session having pgid (EPERM)
316 * pid must not be session leader (EPERM)
320 setpgid(struct proc
*curp
, register struct setpgid_args
*uap
, __unused register_t
*retval
)
322 register struct proc
*targp
; /* target process */
323 register struct pgrp
*pgrp
; /* target pgrp */
325 if (uap
->pid
!= 0 && uap
->pid
!= curp
->p_pid
) {
326 if ((targp
= pfind(uap
->pid
)) == 0 || !inferior(targp
))
328 if (targp
->p_session
!= curp
->p_session
)
330 if (targp
->p_flag
& P_EXEC
)
334 if (SESS_LEADER(targp
))
339 uap
->pgid
= targp
->p_pid
;
340 else if (uap
->pgid
!= targp
->p_pid
)
341 if ((pgrp
= pgfind(uap
->pgid
)) == 0 ||
342 pgrp
->pg_session
!= curp
->p_session
)
344 return (enterpgrp(targp
, uap
->pgid
, 0));
348 issetugid(struct proc
*p
, __unused
struct issetugid_args
*uap
, register_t
*retval
)
351 * Note: OpenBSD sets a P_SUGIDEXEC flag set at execve() time,
352 * we use P_SUGID because we consider changing the owners as
353 * "tainting" as well.
354 * This is significant for procs that start as root and "become"
355 * a user without an exec - programs cannot know *everything*
356 * that libc *might* have put in their data segment.
359 *retval
= (p
->p_flag
& P_SUGID
) ? 1 : 0;
365 setuid(struct proc
*p
, struct setuid_args
*uap
, __unused register_t
*retval
)
369 kauth_cred_t my_cred
, my_new_cred
;
372 AUDIT_ARG(uid
, uid
, 0, 0, 0);
373 if (uid
!= p
->p_ucred
->cr_ruid
&&
374 (error
= suser(p
->p_ucred
, &p
->p_acflag
)))
377 * Everything's okay, do it.
378 * Transfer proc count to new user.
379 * Copy credentials so other references do not see our changes.
382 /* prepare app access profile files */
383 prepare_profile_database(uap
->uid
);
384 (void)chgproccnt(kauth_getruid(), -1);
385 (void)chgproccnt(uid
, 1);
387 /* get current credential and take a reference while we muck with it */
389 my_cred
= kauth_cred_proc_ref(p
);
392 * set the credential with new info. If there is no change we get back
393 * the same credential we passed in.
395 my_new_cred
= kauth_cred_setuid(my_cred
, uid
);
396 if (my_cred
!= my_new_cred
) {
398 /* need to protect for a race where another thread also changed
399 * the credential after we took our reference. If p_ucred has
400 * changed then we should restart this again with the new cred.
402 if (p
->p_ucred
!= my_cred
) {
404 kauth_cred_rele(my_cred
);
405 kauth_cred_rele(my_new_cred
);
409 p
->p_ucred
= my_new_cred
;
410 p
->p_flag
|= P_SUGID
;
413 /* drop our extra reference */
414 kauth_cred_rele(my_cred
);
418 set_security_token(p
);
424 seteuid(struct proc
*p
, struct seteuid_args
*uap
, __unused register_t
*retval
)
428 kauth_cred_t my_cred
, my_new_cred
;
431 AUDIT_ARG(uid
, 0, euid
, 0, 0);
432 if (euid
!= p
->p_ucred
->cr_ruid
&& euid
!= p
->p_ucred
->cr_svuid
&&
433 (error
= suser(p
->p_ucred
, &p
->p_acflag
)))
436 * Everything's okay, do it. Copy credentials so other references do
437 * not see our changes. get current credential and take a reference
438 * while we muck with it
441 my_cred
= kauth_cred_proc_ref(p
);
444 * set the credential with new info. If there is no change we get back
445 * the same credential we passed in.
447 my_new_cred
= kauth_cred_seteuid(p
->p_ucred
, euid
);
449 if (my_cred
!= my_new_cred
) {
451 /* need to protect for a race where another thread also changed
452 * the credential after we took our reference. If p_ucred has
453 * changed then we should restart this again with the new cred.
455 if (p
->p_ucred
!= my_cred
) {
457 kauth_cred_rele(my_cred
);
458 kauth_cred_rele(my_new_cred
);
462 p
->p_ucred
= my_new_cred
;
463 p
->p_flag
|= P_SUGID
;
466 /* drop our extra reference */
467 kauth_cred_rele(my_cred
);
471 set_security_token(p
);
477 setgid(struct proc
*p
, struct setgid_args
*uap
, __unused register_t
*retval
)
481 kauth_cred_t my_cred
, my_new_cred
;
484 AUDIT_ARG(gid
, gid
, 0, 0, 0);
485 if (gid
!= p
->p_ucred
->cr_rgid
&& (error
= suser(p
->p_ucred
, &p
->p_acflag
)))
488 /* get current credential and take a reference while we muck with it */
490 my_cred
= kauth_cred_proc_ref(p
);
493 * set the credential with new info. If there is no change we get back
494 * the same credential we passed in.
496 my_new_cred
= kauth_cred_setgid(p
->p_ucred
, gid
);
497 if (my_cred
!= my_new_cred
) {
499 /* need to protect for a race where another thread also changed
500 * the credential after we took our reference. If p_ucred has
501 * changed then we should restart this again with the new cred.
503 if (p
->p_ucred
!= my_cred
) {
505 kauth_cred_rele(my_cred
);
506 kauth_cred_rele(my_new_cred
);
510 p
->p_ucred
= my_new_cred
;
511 p
->p_flag
|= P_SUGID
;
514 /* drop our extra reference */
515 kauth_cred_rele(my_cred
);
519 set_security_token(p
);
525 setegid(struct proc
*p
, struct setegid_args
*uap
, __unused register_t
*retval
)
529 kauth_cred_t my_cred
, my_new_cred
;
532 AUDIT_ARG(gid
, 0, egid
, 0, 0);
533 if (egid
!= p
->p_ucred
->cr_rgid
&& egid
!= p
->p_ucred
->cr_svgid
&&
534 (error
= suser(p
->p_ucred
, &p
->p_acflag
)))
537 /* get current credential and take a reference while we muck with it */
539 my_cred
= kauth_cred_proc_ref(p
);
542 * set the credential with new info. If there is no change we get back
543 * the same credential we passed in.
545 my_new_cred
= kauth_cred_setegid(p
->p_ucred
, egid
);
546 if (my_cred
!= my_new_cred
) {
548 /* need to protect for a race where another thread also changed
549 * the credential after we took our reference. If p_ucred has
550 * changed then we should restart this again with the new cred.
552 if (p
->p_ucred
!= my_cred
) {
554 kauth_cred_rele(my_cred
);
555 kauth_cred_rele(my_new_cred
);
559 p
->p_ucred
= my_new_cred
;
560 p
->p_flag
|= P_SUGID
;
563 /* drop our extra reference */
564 kauth_cred_rele(my_cred
);
568 set_security_token(p
);
573 * Set the per-thread override identity. The first parameter can be the
574 * current real UID, KAUTH_UID_NONE, or, if the caller is priviledged, it
575 * can be any UID. If it is KAUTH_UID_NONE, then as a special case, this
576 * means "revert to the per process credential"; otherwise, if permitted,
577 * it changes the effective, real, and saved UIDs and GIDs for the current
578 * thread to the requested UID and single GID, and clears all other GIDs.
581 settid(struct proc
*p
, struct settid_args
*uap
, __unused register_t
*retval
)
584 struct uthread
*uthread
= get_bsdthread_info(current_thread());
590 AUDIT_ARG(uid
, uid
, gid
, gid
, 0);
592 if (suser(p
->p_ucred
, &p
->p_acflag
) != 0) {
596 if (uid
== KAUTH_UID_NONE
) {
598 /* must already be assuming another identity in order to revert back */
599 if ((uthread
->uu_flag
& UT_SETUID
) == 0)
602 /* revert to delayed binding of process credential */
603 uc
= kauth_cred_proc_ref(p
);
604 kauth_cred_rele(uthread
->uu_ucred
);
605 uthread
->uu_ucred
= uc
;
606 uthread
->uu_flag
&= ~UT_SETUID
;
608 kauth_cred_t my_cred
, my_new_cred
;
610 /* cannot already be assuming another identity */
611 if ((uthread
->uu_flag
& UT_SETUID
) != 0) {
616 * get a new credential instance from the old if this one changes else
617 * kauth_cred_setuidgid returns the same credential. we take an extra
618 * reference on the current credential while we muck wit it here.
620 kauth_cred_ref(uthread
->uu_ucred
);
621 my_cred
= uthread
->uu_ucred
;
622 my_new_cred
= kauth_cred_setuidgid(my_cred
, uid
, gid
);
623 if (my_cred
!= my_new_cred
)
624 uthread
->uu_ucred
= my_new_cred
;
625 uthread
->uu_flag
|= UT_SETUID
;
627 /* drop our extra reference */
628 kauth_cred_rele(my_cred
);
631 * XXX should potentially set per thread security token (there is
633 * XXX it is unclear whether P_SUGID should be st at this point;
634 * XXX in theory, it is being deprecated.
640 * Set the per-thread override identity. Use this system call for a thread to
641 * assume the identity of another process or to revert back to normal identity
642 * of the current process.
643 * When the "assume" argument is non zero the current thread will assume the
644 * identity of the process represented by the pid argument.
645 * When the assume argument is zero we revert back to our normal identity.
648 settid_with_pid(struct proc
*p
, struct settid_with_pid_args
*uap
, __unused register_t
*retval
)
651 struct uthread
*uthread
= get_bsdthread_info(current_thread());
652 kauth_cred_t my_cred
, my_target_cred
, my_new_cred
;
654 AUDIT_ARG(pid
, uap
->pid
);
655 AUDIT_ARG(value
, uap
->assume
);
657 if (suser(p
->p_ucred
, &p
->p_acflag
) != 0) {
662 * XXX should potentially set per thread security token (there is
664 * XXX it is unclear whether P_SUGID should be st at this point;
665 * XXX in theory, it is being deprecated.
669 * assume argument tells us to assume the identity of the process with the
670 * id passed in the pid argument.
672 if (uap
->assume
!= 0) {
673 /* can't do this if we have already assumed an identity */
674 if ((uthread
->uu_flag
& UT_SETUID
) != 0)
677 target_proc
= pfind(uap
->pid
);
678 /* can't assume the identity of the kernel process */
679 if (target_proc
== NULL
|| target_proc
== kernproc
) {
684 * take a reference on the credential used in our target process then use
685 * it as the identity for our current thread.
687 kauth_cred_ref(uthread
->uu_ucred
);
688 my_cred
= uthread
->uu_ucred
;
689 my_target_cred
= kauth_cred_proc_ref(target_proc
);
690 my_new_cred
= kauth_cred_setuidgid(my_cred
, my_target_cred
->cr_uid
, my_target_cred
->cr_gid
);
691 if (my_cred
!= my_new_cred
)
692 uthread
->uu_ucred
= my_new_cred
;
694 uthread
->uu_flag
|= UT_SETUID
;
696 /* drop our extra references */
697 kauth_cred_rele(my_cred
);
698 kauth_cred_rele(my_target_cred
);
703 /* we are reverting back to normal mode of operation where delayed binding
704 * of the process credential sets the credential in the thread (uu_ucred)
706 if ((uthread
->uu_flag
& UT_SETUID
) == 0)
709 /* revert to delayed binding of process credential */
710 my_new_cred
= kauth_cred_proc_ref(p
);
711 kauth_cred_rele(uthread
->uu_ucred
);
712 uthread
->uu_ucred
= my_new_cred
;
713 uthread
->uu_flag
&= ~UT_SETUID
;
720 setgroups1(struct proc
*p
, u_int gidsetsize
, user_addr_t gidset
, uid_t gmuid
, __unused register_t
*retval
)
723 gid_t newgroups
[NGROUPS
] = { 0 };
725 kauth_cred_t my_cred
, my_new_cred
;
727 if ((error
= suser(p
->p_ucred
, &p
->p_acflag
)))
737 error
= copyin(gidset
,
738 (caddr_t
)newgroups
, ngrp
* sizeof(gid_t
));
744 /* get current credential and take a reference while we muck with it */
746 my_cred
= kauth_cred_proc_ref(p
);
749 * set the credential with new info. If there is no change we get back
750 * the same credential we passed in.
752 my_new_cred
= kauth_cred_setgroups(p
->p_ucred
, &newgroups
[0], ngrp
, gmuid
);
753 if (my_cred
!= my_new_cred
) {
755 /* need to protect for a race where another thread also changed
756 * the credential after we took our reference. If p_ucred has
757 * changed then we should restart this again with the new cred.
759 if (p
->p_ucred
!= my_cred
) {
761 kauth_cred_rele(my_cred
);
762 kauth_cred_rele(my_new_cred
);
766 p
->p_ucred
= my_new_cred
;
767 p
->p_flag
|= P_SUGID
;
770 /* drop our extra reference */
771 kauth_cred_rele(my_cred
);
775 AUDIT_ARG(groupset
, p
->p_ucred
->cr_groups
, ngrp
);
776 set_security_token(p
);
782 initgroups(struct proc
*p
, struct initgroups_args
*uap
, __unused register_t
*retval
)
784 return(setgroups1(p
, uap
->gidsetsize
, uap
->gidset
, uap
->gmuid
, retval
));
788 setgroups(struct proc
*p
, struct setgroups_args
*uap
, __unused register_t
*retval
)
790 return(setgroups1(p
, uap
->gidsetsize
, uap
->gidset
, KAUTH_UID_NONE
, retval
));
794 * Set the per-thread/per-process supplementary groups list.
796 #warning XXX implement
798 setsgroups(__unused
struct proc
*p
, __unused
struct setsgroups_args
*uap
, __unused register_t
*retval
)
804 * Set the per-thread/per-process whiteout groups list.
806 #warning XXX implement
808 setwgroups(__unused
struct proc
*p
, __unused
struct setwgroups_args
*uap
, __unused register_t
*retval
)
814 * Check if gid is a member of the group set.
816 * XXX This interface is going away
819 groupmember(gid_t gid
, kauth_cred_t cred
)
823 if (kauth_cred_ismember_gid(cred
, gid
, &is_member
) == 0 && is_member
)
829 * Test whether the specified credentials imply "super-user"
830 * privilege; if so, and we have accounting info, set the flag
831 * indicating use of super-powers.
832 * Returns 0 or error.
834 * XXX This interface is going away
837 suser(kauth_cred_t cred
, u_short
*acflag
)
840 if (cred
== NOCRED
|| cred
== FSCRED
)
843 if (kauth_cred_getuid(cred
) == 0) {
854 struct proc
*p
= current_proc();
859 return (suser(p
->p_ucred
, &p
->p_acflag
) == 0);
865 struct proc
*p
= current_proc();
870 return (suser(p
->p_ucred
, &p
->p_acflag
) == 0 ||
871 p
->p_ucred
->cr_ruid
== 0 || p
->p_ucred
->cr_svuid
== 0);
875 * Get login name, if available.
879 getlogin(struct proc
*p
, struct getlogin_args
*uap
, __unused register_t
*retval
)
882 if (uap
->namelen
> sizeof (p
->p_pgrp
->pg_session
->s_login
))
883 uap
->namelen
= sizeof (p
->p_pgrp
->pg_session
->s_login
);
884 return (copyout((caddr_t
) p
->p_pgrp
->pg_session
->s_login
,
885 uap
->namebuf
, uap
->namelen
));
893 setlogin(struct proc
*p
, struct setlogin_args
*uap
, __unused register_t
*retval
)
898 if ((error
= suser(p
->p_ucred
, &p
->p_acflag
)))
901 error
= copyinstr(uap
->namebuf
,
902 (caddr_t
) p
->p_pgrp
->pg_session
->s_login
,
903 sizeof (p
->p_pgrp
->pg_session
->s_login
) - 1, (size_t *)&dummy
);
905 AUDIT_ARG(text
, p
->p_pgrp
->pg_session
->s_login
);
906 else if (error
== ENAMETOOLONG
)
912 /* Set the secrity token of the task with current euid and eguid */
914 * XXX This needs to change to give the task a reference and/or an opaque
918 set_security_token(struct proc
* p
)
920 security_token_t sec_token
;
921 audit_token_t audit_token
;
924 * Don't allow a vfork child to override the parent's token settings
925 * (since they share a task). Instead, the child will just have to
926 * suffer along using the parent's token until the exec(). It's all
927 * undefined behavior anyway, right?
929 if (p
->task
== current_task()) {
931 uthread
= (uthread_t
)get_bsdthread_info(current_thread());
932 if (uthread
->uu_flag
& UT_VFORK
)
936 /* XXX mach_init doesn't have a p_ucred when it calls this function */
937 if (p
->p_ucred
!= NOCRED
&& p
->p_ucred
!= FSCRED
) {
938 sec_token
.val
[0] = kauth_cred_getuid(p
->p_ucred
);
939 sec_token
.val
[1] = p
->p_ucred
->cr_gid
;
941 sec_token
.val
[0] = 0;
942 sec_token
.val
[1] = 0;
946 * The current layout of the Mach audit token explicitly
947 * adds these fields. But nobody should rely on such
948 * a literal representation. Instead, the BSM library
949 * provides a function to convert an audit token into
950 * a BSM subject. Use of that mechanism will isolate
951 * the user of the trailer from future representation
954 audit_token
.val
[0] = p
->p_ucred
->cr_au
.ai_auid
;
955 audit_token
.val
[1] = p
->p_ucred
->cr_uid
;
956 audit_token
.val
[2] = p
->p_ucred
->cr_gid
;
957 audit_token
.val
[3] = p
->p_ucred
->cr_ruid
;
958 audit_token
.val
[4] = p
->p_ucred
->cr_rgid
;
959 audit_token
.val
[5] = p
->p_pid
;
960 audit_token
.val
[6] = p
->p_ucred
->cr_au
.ai_asid
;
961 audit_token
.val
[7] = p
->p_ucred
->cr_au
.ai_termid
.port
;
963 return (host_security_set_task_token(host_security_self(),
969 host_priv_self()) != KERN_SUCCESS
);
974 * Fill in a struct xucred based on a kauth_cred_t.
978 cru2x(kauth_cred_t cr
, struct xucred
*xcr
)
981 bzero(xcr
, sizeof(*xcr
));
982 xcr
->cr_version
= XUCRED_VERSION
;
983 xcr
->cr_uid
= kauth_cred_getuid(cr
);
984 xcr
->cr_ngroups
= cr
->cr_ngroups
;
985 bcopy(cr
->cr_groups
, xcr
->cr_groups
, sizeof(xcr
->cr_groups
));