2 * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
22 /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
24 * Copyright (c) 1982, 1986, 1989, 1990, 1991, 1993
25 * The Regents of the University of California. All rights reserved.
26 * (c) UNIX System Laboratories, Inc.
27 * All or some portions of this file are derived from material licensed
28 * to the University of California by American Telephone and Telegraph
29 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
30 * the permission of UNIX System Laboratories, Inc.
32 * Redistribution and use in source and binary forms, with or without
33 * modification, are permitted provided that the following conditions
35 * 1. Redistributions of source code must retain the above copyright
36 * notice, this list of conditions and the following disclaimer.
37 * 2. Redistributions in binary form must reproduce the above copyright
38 * notice, this list of conditions and the following disclaimer in the
39 * documentation and/or other materials provided with the distribution.
40 * 3. All advertising materials mentioning features or use of this software
41 * must display the following acknowledgement:
42 * This product includes software developed by the University of
43 * California, Berkeley and its contributors.
44 * 4. Neither the name of the University nor the names of its contributors
45 * may be used to endorse or promote products derived from this software
46 * without specific prior written permission.
48 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
49 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
60 * @(#)kern_prot.c 8.9 (Berkeley) 2/14/95
64 * System calls related to processes and protection
67 #include <sys/param.h>
69 #include <sys/systm.h>
70 #include <sys/ucred.h>
71 #include <sys/proc_internal.h>
73 #include <sys/kauth.h>
74 #include <sys/timeb.h>
75 #include <sys/times.h>
76 #include <sys/malloc.h>
78 #include <bsm/audit_kernel.h>
80 #include <sys/mount_internal.h>
81 #include <sys/sysproto.h>
82 #include <mach/message.h>
83 #include <mach/host_security.h>
85 #include <kern/host.h>
87 int groupmember(gid_t gid
, kauth_cred_t cred
);
91 extern int prepare_profile_database(int user
);
94 * setprivexec: (dis)allow this process to hold
95 * task, thread, or execption ports of processes about to exec.
98 setprivexec(struct proc
*p
, struct setprivexec_args
*uap
, register_t
*retval
)
100 AUDIT_ARG(value
, uap
->flag
);
101 *retval
= p
->p_debugger
;
102 p
->p_debugger
= (uap
->flag
!= 0);
108 getpid(struct proc
*p
, __unused
struct getpid_args
*uap
, register_t
*retval
)
117 getppid(struct proc
*p
, __unused
struct getppid_args
*uap
, register_t
*retval
)
120 *retval
= p
->p_pptr
->p_pid
;
124 /* Get process group ID; note that POSIX getpgrp takes no parameter */
126 getpgrp(struct proc
*p
, __unused
struct getpgrp_args
*uap
, register_t
*retval
)
129 *retval
= p
->p_pgrp
->pg_id
;
133 /* Get an arbitary pid's process group id */
135 getpgid(struct proc
*p
, struct getpgid_args
*uap
, register_t
*retval
)
143 if ((pt
= pfind(uap
->pid
)) == 0)
146 *retval
= pt
->p_pgrp
->pg_id
;
151 * Get an arbitary pid's session id.
155 getsid(struct proc
*p
, struct getsid_args
*uap
, register_t
*retval
)
163 if ((pt
= pfind(uap
->pid
)) == 0)
166 *retval
= pt
->p_session
->s_sid
;
172 getuid(__unused
struct proc
*p
, __unused
struct getuid_args
*uap
, register_t
*retval
)
175 *retval
= kauth_getruid();
181 geteuid(__unused
struct proc
*p
, __unused
struct geteuid_args
*uap
, register_t
*retval
)
184 *retval
= kauth_getuid();
189 * Return the per-thread override identity.
192 gettid(__unused
struct proc
*p
, struct gettid_args
*uap
, register_t
*retval
)
194 struct uthread
*uthread
= get_bsdthread_info(current_thread());
198 * If this thread is not running with an override identity, we can't
199 * return one to the caller, so return an error instead.
201 if (!(uthread
->uu_flag
& UT_SETUID
))
204 if ((error
= suword(uap
->uidp
, uthread
->uu_ucred
->cr_ruid
)))
206 if ((error
= suword(uap
->gidp
, uthread
->uu_ucred
->cr_rgid
)))
215 getgid(__unused
struct proc
*p
, __unused
struct getgid_args
*uap
, register_t
*retval
)
218 *retval
= kauth_getrgid();
223 * Get effective group ID. The "egid" is groups[0], and could be obtained
224 * via getgroups. This syscall exists because it is somewhat painful to do
225 * correctly in a library function.
229 getegid(struct proc
*p
, __unused
struct getegid_args
*uap
, register_t
*retval
)
232 *retval
= kauth_getgid();
237 getgroups(__unused
struct proc
*p
, struct getgroups_args
*uap
, register_t
*retval
)
243 /* grab reference while we muck around with the credential */
244 cred
= kauth_cred_get_with_ref();
246 if ((ngrp
= uap
->gidsetsize
) == 0) {
247 *retval
= cred
->cr_ngroups
;
248 kauth_cred_rele(cred
);
251 if (ngrp
< cred
->cr_ngroups
) {
252 kauth_cred_rele(cred
);
255 ngrp
= cred
->cr_ngroups
;
256 if ((error
= copyout((caddr_t
)cred
->cr_groups
,
258 ngrp
* sizeof(gid_t
)))) {
259 kauth_cred_rele(cred
);
262 kauth_cred_rele(cred
);
268 * Return the per-thread/per-process supplementary groups list.
270 #warning XXX implement
272 getsgroups(__unused
struct proc
*p
, __unused
struct getsgroups_args
*uap
, __unused register_t
*retval
)
279 * Return the per-thread/per-process whiteout groups list.
281 #warning XXX implement
283 getwgroups(__unused
struct proc
*p
, __unused
struct getwgroups_args
*uap
, __unused register_t
*retval
)
291 setsid(struct proc
*p
, __unused
struct setsid_args
*uap
, register_t
*retval
)
294 if (p
->p_pgid
== p
->p_pid
|| pgfind(p
->p_pid
) || p
->p_flag
& P_INVFORK
) {
297 (void)enterpgrp(p
, p
->p_pid
, 1);
304 * set process group (setpgid/old setpgrp)
306 * caller does setpgid(targpid, targpgid)
308 * pid must be caller or child of caller (ESRCH)
310 * pid must be in same session (EPERM)
311 * pid can't have done an exec (EACCES)
312 * ig pgid is -ve return EINVAL (as per SUV spec)
314 * there must exist some pid in same session having pgid (EPERM)
315 * pid must not be session leader (EPERM)
319 setpgid(struct proc
*curp
, register struct setpgid_args
*uap
, __unused register_t
*retval
)
321 register struct proc
*targp
; /* target process */
322 register struct pgrp
*pgrp
; /* target pgrp */
324 if (uap
->pid
!= 0 && uap
->pid
!= curp
->p_pid
) {
325 if ((targp
= pfind(uap
->pid
)) == 0 || !inferior(targp
))
327 if (targp
->p_session
!= curp
->p_session
)
329 if (targp
->p_flag
& P_EXEC
)
333 if (SESS_LEADER(targp
))
338 uap
->pgid
= targp
->p_pid
;
339 else if (uap
->pgid
!= targp
->p_pid
)
340 if ((pgrp
= pgfind(uap
->pgid
)) == 0 ||
341 pgrp
->pg_session
!= curp
->p_session
)
343 return (enterpgrp(targp
, uap
->pgid
, 0));
347 issetugid(struct proc
*p
, __unused
struct issetugid_args
*uap
, register_t
*retval
)
350 * Note: OpenBSD sets a P_SUGIDEXEC flag set at execve() time,
351 * we use P_SUGID because we consider changing the owners as
352 * "tainting" as well.
353 * This is significant for procs that start as root and "become"
354 * a user without an exec - programs cannot know *everything*
355 * that libc *might* have put in their data segment.
358 *retval
= (p
->p_flag
& P_SUGID
) ? 1 : 0;
364 setuid(struct proc
*p
, struct setuid_args
*uap
, __unused register_t
*retval
)
368 kauth_cred_t my_cred
, my_new_cred
;
371 AUDIT_ARG(uid
, uid
, 0, 0, 0);
372 if (uid
!= p
->p_ucred
->cr_ruid
&&
373 (error
= suser(p
->p_ucred
, &p
->p_acflag
)))
376 * Everything's okay, do it.
377 * Transfer proc count to new user.
378 * Copy credentials so other references do not see our changes.
381 /* prepare app access profile files */
382 prepare_profile_database(uap
->uid
);
383 (void)chgproccnt(kauth_getruid(), -1);
384 (void)chgproccnt(uid
, 1);
386 /* get current credential and take a reference while we muck with it */
388 my_cred
= kauth_cred_proc_ref(p
);
391 * set the credential with new info. If there is no change we get back
392 * the same credential we passed in.
394 my_new_cred
= kauth_cred_setuid(my_cred
, uid
);
395 if (my_cred
!= my_new_cred
) {
397 /* need to protect for a race where another thread also changed
398 * the credential after we took our reference. If p_ucred has
399 * changed then we should restart this again with the new cred.
401 if (p
->p_ucred
!= my_cred
) {
403 kauth_cred_rele(my_cred
);
404 kauth_cred_rele(my_new_cred
);
408 p
->p_ucred
= my_new_cred
;
409 p
->p_flag
|= P_SUGID
;
412 /* drop our extra reference */
413 kauth_cred_rele(my_cred
);
417 set_security_token(p
);
423 seteuid(struct proc
*p
, struct seteuid_args
*uap
, __unused register_t
*retval
)
427 kauth_cred_t my_cred
, my_new_cred
;
430 AUDIT_ARG(uid
, 0, euid
, 0, 0);
431 if (euid
!= p
->p_ucred
->cr_ruid
&& euid
!= p
->p_ucred
->cr_svuid
&&
432 (error
= suser(p
->p_ucred
, &p
->p_acflag
)))
435 * Everything's okay, do it. Copy credentials so other references do
436 * not see our changes. get current credential and take a reference
437 * while we muck with it
440 my_cred
= kauth_cred_proc_ref(p
);
443 * set the credential with new info. If there is no change we get back
444 * the same credential we passed in.
446 my_new_cred
= kauth_cred_seteuid(p
->p_ucred
, euid
);
448 if (my_cred
!= my_new_cred
) {
450 /* need to protect for a race where another thread also changed
451 * the credential after we took our reference. If p_ucred has
452 * changed then we should restart this again with the new cred.
454 if (p
->p_ucred
!= my_cred
) {
456 kauth_cred_rele(my_cred
);
457 kauth_cred_rele(my_new_cred
);
461 p
->p_ucred
= my_new_cred
;
462 p
->p_flag
|= P_SUGID
;
465 /* drop our extra reference */
466 kauth_cred_rele(my_cred
);
470 set_security_token(p
);
476 setgid(struct proc
*p
, struct setgid_args
*uap
, __unused register_t
*retval
)
480 kauth_cred_t my_cred
, my_new_cred
;
483 AUDIT_ARG(gid
, gid
, 0, 0, 0);
484 if (gid
!= p
->p_ucred
->cr_rgid
&& (error
= suser(p
->p_ucred
, &p
->p_acflag
)))
487 /* get current credential and take a reference while we muck with it */
489 my_cred
= kauth_cred_proc_ref(p
);
492 * set the credential with new info. If there is no change we get back
493 * the same credential we passed in.
495 my_new_cred
= kauth_cred_setgid(p
->p_ucred
, gid
);
496 if (my_cred
!= my_new_cred
) {
498 /* need to protect for a race where another thread also changed
499 * the credential after we took our reference. If p_ucred has
500 * changed then we should restart this again with the new cred.
502 if (p
->p_ucred
!= my_cred
) {
504 kauth_cred_rele(my_cred
);
505 kauth_cred_rele(my_new_cred
);
509 p
->p_ucred
= my_new_cred
;
510 p
->p_flag
|= P_SUGID
;
513 /* drop our extra reference */
514 kauth_cred_rele(my_cred
);
518 set_security_token(p
);
524 setegid(struct proc
*p
, struct setegid_args
*uap
, __unused register_t
*retval
)
528 kauth_cred_t my_cred
, my_new_cred
;
531 AUDIT_ARG(gid
, 0, egid
, 0, 0);
532 if (egid
!= p
->p_ucred
->cr_rgid
&& egid
!= p
->p_ucred
->cr_svgid
&&
533 (error
= suser(p
->p_ucred
, &p
->p_acflag
)))
536 /* get current credential and take a reference while we muck with it */
538 my_cred
= kauth_cred_proc_ref(p
);
541 * set the credential with new info. If there is no change we get back
542 * the same credential we passed in.
544 my_new_cred
= kauth_cred_setegid(p
->p_ucred
, egid
);
545 if (my_cred
!= my_new_cred
) {
547 /* need to protect for a race where another thread also changed
548 * the credential after we took our reference. If p_ucred has
549 * changed then we should restart this again with the new cred.
551 if (p
->p_ucred
!= my_cred
) {
553 kauth_cred_rele(my_cred
);
554 kauth_cred_rele(my_new_cred
);
558 p
->p_ucred
= my_new_cred
;
559 p
->p_flag
|= P_SUGID
;
562 /* drop our extra reference */
563 kauth_cred_rele(my_cred
);
567 set_security_token(p
);
572 * Set the per-thread override identity. The first parameter can be the
573 * current real UID, KAUTH_UID_NONE, or, if the caller is priviledged, it
574 * can be any UID. If it is KAUTH_UID_NONE, then as a special case, this
575 * means "revert to the per process credential"; otherwise, if permitted,
576 * it changes the effective, real, and saved UIDs and GIDs for the current
577 * thread to the requested UID and single GID, and clears all other GIDs.
580 settid(struct proc
*p
, struct settid_args
*uap
, __unused register_t
*retval
)
583 struct uthread
*uthread
= get_bsdthread_info(current_thread());
589 AUDIT_ARG(uid
, uid
, gid
, gid
, 0);
591 if (suser(p
->p_ucred
, &p
->p_acflag
) != 0) {
595 if (uid
== KAUTH_UID_NONE
) {
597 /* must already be assuming another identity in order to revert back */
598 if ((uthread
->uu_flag
& UT_SETUID
) == 0)
601 /* revert to delayed binding of process credential */
602 uc
= kauth_cred_proc_ref(p
);
603 kauth_cred_rele(uthread
->uu_ucred
);
604 uthread
->uu_ucred
= uc
;
605 uthread
->uu_flag
&= ~UT_SETUID
;
607 kauth_cred_t my_cred
, my_new_cred
;
609 /* cannot already be assuming another identity */
610 if ((uthread
->uu_flag
& UT_SETUID
) != 0) {
615 * get a new credential instance from the old if this one changes else
616 * kauth_cred_setuidgid returns the same credential. we take an extra
617 * reference on the current credential while we muck wit it here.
619 kauth_cred_ref(uthread
->uu_ucred
);
620 my_cred
= uthread
->uu_ucred
;
621 my_new_cred
= kauth_cred_setuidgid(my_cred
, uid
, gid
);
622 if (my_cred
!= my_new_cred
)
623 uthread
->uu_ucred
= my_new_cred
;
624 uthread
->uu_flag
|= UT_SETUID
;
626 /* drop our extra reference */
627 kauth_cred_rele(my_cred
);
630 * XXX should potentially set per thread security token (there is
632 * XXX it is unclear whether P_SUGID should be st at this point;
633 * XXX in theory, it is being deprecated.
639 * Set the per-thread override identity. Use this system call for a thread to
640 * assume the identity of another process or to revert back to normal identity
641 * of the current process.
642 * When the "assume" argument is non zero the current thread will assume the
643 * identity of the process represented by the pid argument.
644 * When the assume argument is zero we revert back to our normal identity.
647 settid_with_pid(struct proc
*p
, struct settid_with_pid_args
*uap
, __unused register_t
*retval
)
650 struct uthread
*uthread
= get_bsdthread_info(current_thread());
651 kauth_cred_t my_cred
, my_target_cred
, my_new_cred
;
653 AUDIT_ARG(pid
, uap
->pid
);
654 AUDIT_ARG(value
, uap
->assume
);
656 if (suser(p
->p_ucred
, &p
->p_acflag
) != 0) {
661 * XXX should potentially set per thread security token (there is
663 * XXX it is unclear whether P_SUGID should be st at this point;
664 * XXX in theory, it is being deprecated.
668 * assume argument tells us to assume the identity of the process with the
669 * id passed in the pid argument.
671 if (uap
->assume
!= 0) {
672 /* can't do this if we have already assumed an identity */
673 if ((uthread
->uu_flag
& UT_SETUID
) != 0)
676 target_proc
= pfind(uap
->pid
);
677 /* can't assume the identity of the kernel process */
678 if (target_proc
== NULL
|| target_proc
== kernproc
) {
683 * take a reference on the credential used in our target process then use
684 * it as the identity for our current thread.
686 kauth_cred_ref(uthread
->uu_ucred
);
687 my_cred
= uthread
->uu_ucred
;
688 my_target_cred
= kauth_cred_proc_ref(target_proc
);
689 my_new_cred
= kauth_cred_setuidgid(my_cred
, my_target_cred
->cr_uid
, my_target_cred
->cr_gid
);
690 if (my_cred
!= my_new_cred
)
691 uthread
->uu_ucred
= my_new_cred
;
693 uthread
->uu_flag
|= UT_SETUID
;
695 /* drop our extra references */
696 kauth_cred_rele(my_cred
);
697 kauth_cred_rele(my_target_cred
);
702 /* we are reverting back to normal mode of operation where delayed binding
703 * of the process credential sets the credential in the thread (uu_ucred)
705 if ((uthread
->uu_flag
& UT_SETUID
) == 0)
708 /* revert to delayed binding of process credential */
709 my_new_cred
= kauth_cred_proc_ref(p
);
710 kauth_cred_rele(uthread
->uu_ucred
);
711 uthread
->uu_ucred
= my_new_cred
;
712 uthread
->uu_flag
&= ~UT_SETUID
;
719 setgroups1(struct proc
*p
, u_int gidsetsize
, user_addr_t gidset
, uid_t gmuid
, __unused register_t
*retval
)
722 gid_t newgroups
[NGROUPS
] = { 0 };
724 kauth_cred_t my_cred
, my_new_cred
;
725 struct uthread
*uthread
= get_bsdthread_info(current_thread());
727 if ((error
= suser(p
->p_ucred
, &p
->p_acflag
)))
737 error
= copyin(gidset
,
738 (caddr_t
)newgroups
, ngrp
* sizeof(gid_t
));
744 if ((uthread
->uu_flag
& UT_SETUID
) != 0) {
746 * If this thread is under an assumed identity, set the
747 * supplementary grouplist on the thread credential instead
748 * of the process one. If we were the only reference holder,
749 * the credential is updated in place, otherwise, our reference
750 * is dropped and we get back a different cred with a reference
751 * already held on it. Because this is per-thread, we don't
752 * need the referencing/locking/retry required for per-process.
754 * Hack: this opts into memberd to avoid needing to use a per
755 * thread credential initgroups() instead of setgroups() in
756 * AFP server to address <rdar://4561060>
758 my_cred
= uthread
->uu_ucred
;
759 uthread
->uu_ucred
= kauth_cred_setgroups(my_cred
, &newgroups
[0], ngrp
, my_cred
->cr_gmuid
);
763 * get current credential and take a reference while we muck
767 my_cred
= kauth_cred_proc_ref(p
);
770 * set the credential with new info. If there is no
771 * change we get back the same credential we passed in.
773 my_new_cred
= kauth_cred_setgroups(my_cred
, &newgroups
[0], ngrp
, gmuid
);
774 if (my_cred
!= my_new_cred
) {
777 * need to protect for a race where another
778 * thread also changed the credential after we
779 * took our reference. If p_ucred has
780 * changed then we should restart this again
783 if (p
->p_ucred
!= my_cred
) {
785 kauth_cred_rele(my_cred
);
786 kauth_cred_rele(my_new_cred
);
790 p
->p_ucred
= my_new_cred
;
791 p
->p_flag
|= P_SUGID
;
794 /* drop our extra reference */
795 kauth_cred_rele(my_cred
);
799 AUDIT_ARG(groupset
, p
->p_ucred
->cr_groups
, ngrp
);
800 set_security_token(p
);
807 initgroups(struct proc
*p
, struct initgroups_args
*uap
, __unused register_t
*retval
)
809 return(setgroups1(p
, uap
->gidsetsize
, uap
->gidset
, uap
->gmuid
, retval
));
813 setgroups(struct proc
*p
, struct setgroups_args
*uap
, __unused register_t
*retval
)
815 return(setgroups1(p
, uap
->gidsetsize
, uap
->gidset
, KAUTH_UID_NONE
, retval
));
819 * Set the per-thread/per-process supplementary groups list.
821 #warning XXX implement
823 setsgroups(__unused
struct proc
*p
, __unused
struct setsgroups_args
*uap
, __unused register_t
*retval
)
829 * Set the per-thread/per-process whiteout groups list.
831 #warning XXX implement
833 setwgroups(__unused
struct proc
*p
, __unused
struct setwgroups_args
*uap
, __unused register_t
*retval
)
839 * Check if gid is a member of the group set.
841 * XXX This interface is going away
844 groupmember(gid_t gid
, kauth_cred_t cred
)
848 if (kauth_cred_ismember_gid(cred
, gid
, &is_member
) == 0 && is_member
)
854 * Test whether the specified credentials imply "super-user"
855 * privilege; if so, and we have accounting info, set the flag
856 * indicating use of super-powers.
857 * Returns 0 or error.
859 * XXX This interface is going away
862 suser(kauth_cred_t cred
, u_short
*acflag
)
865 if (cred
== NOCRED
|| cred
== FSCRED
)
868 if (kauth_cred_getuid(cred
) == 0) {
879 struct proc
*p
= current_proc();
884 return (suser(p
->p_ucred
, &p
->p_acflag
) == 0);
890 struct proc
*p
= current_proc();
895 return (suser(p
->p_ucred
, &p
->p_acflag
) == 0 ||
896 p
->p_ucred
->cr_ruid
== 0 || p
->p_ucred
->cr_svuid
== 0);
900 * Get login name, if available.
904 getlogin(struct proc
*p
, struct getlogin_args
*uap
, __unused register_t
*retval
)
907 if (uap
->namelen
> sizeof (p
->p_pgrp
->pg_session
->s_login
))
908 uap
->namelen
= sizeof (p
->p_pgrp
->pg_session
->s_login
);
909 return (copyout((caddr_t
) p
->p_pgrp
->pg_session
->s_login
,
910 uap
->namebuf
, uap
->namelen
));
918 setlogin(struct proc
*p
, struct setlogin_args
*uap
, __unused register_t
*retval
)
923 if ((error
= suser(p
->p_ucred
, &p
->p_acflag
)))
926 error
= copyinstr(uap
->namebuf
,
927 (caddr_t
) p
->p_pgrp
->pg_session
->s_login
,
928 sizeof (p
->p_pgrp
->pg_session
->s_login
) - 1, (size_t *)&dummy
);
930 AUDIT_ARG(text
, p
->p_pgrp
->pg_session
->s_login
);
931 else if (error
== ENAMETOOLONG
)
937 /* Set the secrity token of the task with current euid and eguid */
939 * XXX This needs to change to give the task a reference and/or an opaque
943 set_security_token(struct proc
* p
)
945 security_token_t sec_token
;
946 audit_token_t audit_token
;
949 * Don't allow a vfork child to override the parent's token settings
950 * (since they share a task). Instead, the child will just have to
951 * suffer along using the parent's token until the exec(). It's all
952 * undefined behavior anyway, right?
954 if (p
->task
== current_task()) {
956 uthread
= (uthread_t
)get_bsdthread_info(current_thread());
957 if (uthread
->uu_flag
& UT_VFORK
)
961 /* XXX mach_init doesn't have a p_ucred when it calls this function */
962 if (p
->p_ucred
!= NOCRED
&& p
->p_ucred
!= FSCRED
) {
963 sec_token
.val
[0] = kauth_cred_getuid(p
->p_ucred
);
964 sec_token
.val
[1] = p
->p_ucred
->cr_gid
;
966 sec_token
.val
[0] = 0;
967 sec_token
.val
[1] = 0;
971 * The current layout of the Mach audit token explicitly
972 * adds these fields. But nobody should rely on such
973 * a literal representation. Instead, the BSM library
974 * provides a function to convert an audit token into
975 * a BSM subject. Use of that mechanism will isolate
976 * the user of the trailer from future representation
979 audit_token
.val
[0] = p
->p_ucred
->cr_au
.ai_auid
;
980 audit_token
.val
[1] = p
->p_ucred
->cr_uid
;
981 audit_token
.val
[2] = p
->p_ucred
->cr_gid
;
982 audit_token
.val
[3] = p
->p_ucred
->cr_ruid
;
983 audit_token
.val
[4] = p
->p_ucred
->cr_rgid
;
984 audit_token
.val
[5] = p
->p_pid
;
985 audit_token
.val
[6] = p
->p_ucred
->cr_au
.ai_asid
;
986 audit_token
.val
[7] = p
->p_ucred
->cr_au
.ai_termid
.port
;
988 return (host_security_set_task_token(host_security_self(),
994 host_priv_self()) != KERN_SUCCESS
);
999 * Fill in a struct xucred based on a kauth_cred_t.
1003 cru2x(kauth_cred_t cr
, struct xucred
*xcr
)
1006 bzero(xcr
, sizeof(*xcr
));
1007 xcr
->cr_version
= XUCRED_VERSION
;
1008 xcr
->cr_uid
= kauth_cred_getuid(cr
);
1009 xcr
->cr_ngroups
= cr
->cr_ngroups
;
1010 bcopy(cr
->cr_groups
, xcr
->cr_groups
, sizeof(xcr
->cr_groups
));