2 * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_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. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
28 /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
30 * Copyright (c) 1982, 1986, 1989, 1990, 1991, 1993
31 * The Regents of the University of California. All rights reserved.
32 * (c) UNIX System Laboratories, Inc.
33 * All or some portions of this file are derived from material licensed
34 * to the University of California by American Telephone and Telegraph
35 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
36 * the permission of UNIX System Laboratories, Inc.
38 * Redistribution and use in source and binary forms, with or without
39 * modification, are permitted provided that the following conditions
41 * 1. Redistributions of source code must retain the above copyright
42 * notice, this list of conditions and the following disclaimer.
43 * 2. Redistributions in binary form must reproduce the above copyright
44 * notice, this list of conditions and the following disclaimer in the
45 * documentation and/or other materials provided with the distribution.
46 * 3. All advertising materials mentioning features or use of this software
47 * must display the following acknowledgement:
48 * This product includes software developed by the University of
49 * California, Berkeley and its contributors.
50 * 4. Neither the name of the University nor the names of its contributors
51 * may be used to endorse or promote products derived from this software
52 * without specific prior written permission.
54 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
55 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
56 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
57 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
58 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
59 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
60 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
61 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
62 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
63 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
66 * @(#)kern_prot.c 8.9 (Berkeley) 2/14/95
70 * System calls related to processes and protection
73 #include <sys/param.h>
75 #include <sys/systm.h>
76 #include <sys/ucred.h>
77 #include <sys/proc_internal.h>
79 #include <sys/kauth.h>
80 #include <sys/timeb.h>
81 #include <sys/times.h>
82 #include <sys/malloc.h>
84 #include <bsm/audit_kernel.h>
86 #include <sys/mount_internal.h>
87 #include <sys/sysproto.h>
88 #include <mach/message.h>
89 #include <mach/host_security.h>
91 #include <kern/host.h>
93 int groupmember(gid_t gid
, kauth_cred_t cred
);
97 extern int prepare_profile_database(int user
);
100 * setprivexec: (dis)allow this process to hold
101 * task, thread, or execption ports of processes about to exec.
104 setprivexec(struct proc
*p
, struct setprivexec_args
*uap
, register_t
*retval
)
106 AUDIT_ARG(value
, uap
->flag
);
107 *retval
= p
->p_debugger
;
108 p
->p_debugger
= (uap
->flag
!= 0);
114 getpid(struct proc
*p
, __unused
struct getpid_args
*uap
, register_t
*retval
)
123 getppid(struct proc
*p
, __unused
struct getppid_args
*uap
, register_t
*retval
)
126 *retval
= p
->p_pptr
->p_pid
;
130 /* Get process group ID; note that POSIX getpgrp takes no parameter */
132 getpgrp(struct proc
*p
, __unused
struct getpgrp_args
*uap
, register_t
*retval
)
135 *retval
= p
->p_pgrp
->pg_id
;
139 /* Get an arbitary pid's process group id */
141 getpgid(struct proc
*p
, struct getpgid_args
*uap
, register_t
*retval
)
149 if ((pt
= pfind(uap
->pid
)) == 0)
152 *retval
= pt
->p_pgrp
->pg_id
;
157 * Get an arbitary pid's session id.
161 getsid(struct proc
*p
, struct getsid_args
*uap
, register_t
*retval
)
169 if ((pt
= pfind(uap
->pid
)) == 0)
172 *retval
= pt
->p_session
->s_sid
;
178 getuid(__unused
struct proc
*p
, __unused
struct getuid_args
*uap
, register_t
*retval
)
181 *retval
= kauth_getruid();
187 geteuid(__unused
struct proc
*p
, __unused
struct geteuid_args
*uap
, register_t
*retval
)
190 *retval
= kauth_getuid();
195 * Return the per-thread override identity.
198 gettid(__unused
struct proc
*p
, struct gettid_args
*uap
, register_t
*retval
)
200 struct uthread
*uthread
= get_bsdthread_info(current_thread());
204 * If this thread is not running with an override identity, we can't
205 * return one to the caller, so return an error instead.
207 if (!(uthread
->uu_flag
& UT_SETUID
))
210 if ((error
= suword(uap
->uidp
, uthread
->uu_ucred
->cr_ruid
)))
212 if ((error
= suword(uap
->gidp
, uthread
->uu_ucred
->cr_rgid
)))
221 getgid(__unused
struct proc
*p
, __unused
struct getgid_args
*uap
, register_t
*retval
)
224 *retval
= kauth_getrgid();
229 * Get effective group ID. The "egid" is groups[0], and could be obtained
230 * via getgroups. This syscall exists because it is somewhat painful to do
231 * correctly in a library function.
235 getegid(struct proc
*p
, __unused
struct getegid_args
*uap
, register_t
*retval
)
238 *retval
= kauth_getgid();
243 getgroups(__unused
struct proc
*p
, struct getgroups_args
*uap
, register_t
*retval
)
249 /* grab reference while we muck around with the credential */
250 cred
= kauth_cred_get_with_ref();
252 if ((ngrp
= uap
->gidsetsize
) == 0) {
253 *retval
= cred
->cr_ngroups
;
254 kauth_cred_unref(&cred
);
257 if (ngrp
< cred
->cr_ngroups
) {
258 kauth_cred_unref(&cred
);
261 ngrp
= cred
->cr_ngroups
;
262 if ((error
= copyout((caddr_t
)cred
->cr_groups
,
264 ngrp
* sizeof(gid_t
)))) {
265 kauth_cred_unref(&cred
);
268 kauth_cred_unref(&cred
);
274 * Return the per-thread/per-process supplementary groups list.
276 #warning XXX implement
278 getsgroups(__unused
struct proc
*p
, __unused
struct getsgroups_args
*uap
, __unused register_t
*retval
)
285 * Return the per-thread/per-process whiteout groups list.
287 #warning XXX implement
289 getwgroups(__unused
struct proc
*p
, __unused
struct getwgroups_args
*uap
, __unused register_t
*retval
)
297 setsid(struct proc
*p
, __unused
struct setsid_args
*uap
, register_t
*retval
)
300 if (p
->p_pgid
== p
->p_pid
|| pgfind(p
->p_pid
) || p
->p_flag
& P_INVFORK
) {
303 (void)enterpgrp(p
, p
->p_pid
, 1);
310 * set process group (setpgid/old setpgrp)
312 * caller does setpgid(targpid, targpgid)
314 * pid must be caller or child of caller (ESRCH)
316 * pid must be in same session (EPERM)
317 * pid can't have done an exec (EACCES)
318 * ig pgid is -ve return EINVAL (as per SUV spec)
320 * there must exist some pid in same session having pgid (EPERM)
321 * pid must not be session leader (EPERM)
325 setpgid(struct proc
*curp
, register struct setpgid_args
*uap
, __unused register_t
*retval
)
327 register struct proc
*targp
; /* target process */
328 register struct pgrp
*pgrp
; /* target pgrp */
330 if (uap
->pid
!= 0 && uap
->pid
!= curp
->p_pid
) {
331 if ((targp
= pfind(uap
->pid
)) == 0 || !inferior(targp
))
333 if (targp
->p_session
!= curp
->p_session
)
335 if (targp
->p_flag
& P_EXEC
)
339 if (SESS_LEADER(targp
))
344 uap
->pgid
= targp
->p_pid
;
345 else if (uap
->pgid
!= targp
->p_pid
)
346 if ((pgrp
= pgfind(uap
->pgid
)) == 0 ||
347 pgrp
->pg_session
!= curp
->p_session
)
349 return (enterpgrp(targp
, uap
->pgid
, 0));
353 issetugid(struct proc
*p
, __unused
struct issetugid_args
*uap
, register_t
*retval
)
356 * Note: OpenBSD sets a P_SUGIDEXEC flag set at execve() time,
357 * we use P_SUGID because we consider changing the owners as
358 * "tainting" as well.
359 * This is significant for procs that start as root and "become"
360 * a user without an exec - programs cannot know *everything*
361 * that libc *might* have put in their data segment.
364 *retval
= (p
->p_flag
& P_SUGID
) ? 1 : 0;
370 setuid(struct proc
*p
, struct setuid_args
*uap
, __unused register_t
*retval
)
374 kauth_cred_t my_cred
, my_new_cred
;
377 AUDIT_ARG(uid
, uid
, 0, 0, 0);
378 if (uid
!= p
->p_ucred
->cr_ruid
&&
379 (error
= suser(p
->p_ucred
, &p
->p_acflag
)))
382 * Everything's okay, do it.
383 * Transfer proc count to new user.
384 * Copy credentials so other references do not see our changes.
387 /* prepare app access profile files */
388 prepare_profile_database(uap
->uid
);
389 (void)chgproccnt(kauth_getruid(), -1);
390 (void)chgproccnt(uid
, 1);
392 /* get current credential and take a reference while we muck with it */
394 my_cred
= kauth_cred_proc_ref(p
);
397 * Set the credential with new info. If there is no change,
398 * we get back the same credential we passed in; if there is
399 * a change, we drop the reference on the credential we
400 * passed in. The subsequent compare is safe, because it is
401 * a pointer compare rather than a contents compare.
403 my_new_cred
= kauth_cred_setuid(my_cred
, uid
);
404 if (my_cred
!= my_new_cred
) {
406 /* need to protect for a race where another thread also changed
407 * the credential after we took our reference. If p_ucred has
408 * changed then we should restart this again with the new cred.
410 if (p
->p_ucred
!= my_cred
) {
412 kauth_cred_unref(&my_new_cred
);
416 p
->p_ucred
= my_new_cred
;
417 p
->p_flag
|= P_SUGID
;
420 /* drop old proc reference or our extra reference */
421 kauth_cred_unref(&my_cred
);
425 set_security_token(p
);
431 seteuid(struct proc
*p
, struct seteuid_args
*uap
, __unused register_t
*retval
)
435 kauth_cred_t my_cred
, my_new_cred
;
438 AUDIT_ARG(uid
, 0, euid
, 0, 0);
439 if (euid
!= p
->p_ucred
->cr_ruid
&& euid
!= p
->p_ucred
->cr_svuid
&&
440 (error
= suser(p
->p_ucred
, &p
->p_acflag
)))
443 * Everything's okay, do it. Copy credentials so other references do
444 * not see our changes. get current credential and take a reference
445 * while we muck with it
448 my_cred
= kauth_cred_proc_ref(p
);
451 * Set the credential with new info. If there is no change,
452 * we get back the same credential we passed in; if there is
453 * a change, we drop the reference on the credential we
454 * passed in. The subsequent compare is safe, because it is
455 * a pointer compare rather than a contents compare.
457 my_new_cred
= kauth_cred_seteuid(my_cred
, euid
);
459 if (my_cred
!= my_new_cred
) {
462 * We need to protect for a race where another thread
463 * also changed the credential after we took our
464 * reference. If p_ucred has changed then we should
465 * restart this again with the new cred.
467 if (p
->p_ucred
!= my_cred
) {
469 kauth_cred_unref(&my_new_cred
);
473 p
->p_ucred
= my_new_cred
;
474 p
->p_flag
|= P_SUGID
;
477 /* drop old proc reference or our extra reference */
478 kauth_cred_unref(&my_cred
);
482 set_security_token(p
);
488 setgid(struct proc
*p
, struct setgid_args
*uap
, __unused register_t
*retval
)
492 kauth_cred_t my_cred
, my_new_cred
;
495 AUDIT_ARG(gid
, gid
, 0, 0, 0);
496 if (gid
!= p
->p_ucred
->cr_rgid
&& (error
= suser(p
->p_ucred
, &p
->p_acflag
)))
499 /* get current credential and take a reference while we muck with it */
501 my_cred
= kauth_cred_proc_ref(p
);
504 * Set the credential with new info. If there is no change,
505 * we get back the same credential we passed in; if there is
506 * a change, we drop the reference on the credential we
507 * passed in. The subsequent compare is safe, because it is
508 * a pointer compare rather than a contents compare.
510 my_new_cred
= kauth_cred_setgid(my_cred
, gid
);
511 if (my_cred
!= my_new_cred
) {
514 * We need to protect for a race where another thread
515 * also changed the credential after we took our
516 * reference. If p_ucred has changed then we should
517 * restart this again with the new cred.
519 if (p
->p_ucred
!= my_cred
) {
521 kauth_cred_unref(&my_new_cred
);
525 p
->p_ucred
= my_new_cred
;
526 p
->p_flag
|= P_SUGID
;
529 /* drop old proc reference or our extra reference */
530 kauth_cred_unref(&my_cred
);
534 set_security_token(p
);
540 setegid(struct proc
*p
, struct setegid_args
*uap
, __unused register_t
*retval
)
544 kauth_cred_t my_cred
, my_new_cred
;
547 AUDIT_ARG(gid
, 0, egid
, 0, 0);
548 if (egid
!= p
->p_ucred
->cr_rgid
&& egid
!= p
->p_ucred
->cr_svgid
&&
549 (error
= suser(p
->p_ucred
, &p
->p_acflag
)))
552 /* get current credential and take a reference while we muck with it */
554 my_cred
= kauth_cred_proc_ref(p
);
557 * Set the credential with new info. If there is no change,
558 * we get back the same credential we passed in; if there is
559 * a change, we drop the reference on the credential we
560 * passed in. The subsequent compare is safe, because it is
561 * a pointer compare rather than a contents compare.
563 my_new_cred
= kauth_cred_setegid(my_cred
, egid
);
564 if (my_cred
!= my_new_cred
) {
566 /* need to protect for a race where another thread also changed
567 * the credential after we took our reference. If p_ucred has
568 * changed then we should restart this again with the new cred.
570 if (p
->p_ucred
!= my_cred
) {
572 kauth_cred_unref(&my_new_cred
);
576 p
->p_ucred
= my_new_cred
;
577 p
->p_flag
|= P_SUGID
;
580 /* drop old proc reference or our extra reference */
581 kauth_cred_unref(&my_cred
);
585 set_security_token(p
);
590 * Set the per-thread override identity. The first parameter can be the
591 * current real UID, KAUTH_UID_NONE, or, if the caller is priviledged, it
592 * can be any UID. If it is KAUTH_UID_NONE, then as a special case, this
593 * means "revert to the per process credential"; otherwise, if permitted,
594 * it changes the effective, real, and saved UIDs and GIDs for the current
595 * thread to the requested UID and single GID, and clears all other GIDs.
598 settid(struct proc
*p
, struct settid_args
*uap
, __unused register_t
*retval
)
601 struct uthread
*uthread
= get_bsdthread_info(current_thread());
607 AUDIT_ARG(uid
, uid
, gid
, gid
, 0);
609 if (suser(p
->p_ucred
, &p
->p_acflag
) != 0) {
613 if (uid
== KAUTH_UID_NONE
) {
615 /* must already be assuming another identity in order to revert back */
616 if ((uthread
->uu_flag
& UT_SETUID
) == 0)
619 /* revert to delayed binding of process credential */
620 uc
= kauth_cred_proc_ref(p
);
621 kauth_cred_unref(&uthread
->uu_ucred
);
622 uthread
->uu_ucred
= uc
;
623 uthread
->uu_flag
&= ~UT_SETUID
;
625 kauth_cred_t my_cred
, my_new_cred
;
627 /* cannot already be assuming another identity */
628 if ((uthread
->uu_flag
& UT_SETUID
) != 0) {
633 * get a new credential instance from the old if this one changes else
634 * kauth_cred_setuidgid returns the same credential. we take an extra
635 * reference on the current credential while we muck wit it here.
637 kauth_cred_ref(uthread
->uu_ucred
);
638 my_cred
= uthread
->uu_ucred
;
639 my_new_cred
= kauth_cred_setuidgid(my_cred
, uid
, gid
);
640 if (my_cred
!= my_new_cred
)
641 uthread
->uu_ucred
= my_new_cred
;
642 uthread
->uu_flag
|= UT_SETUID
;
644 /* drop our extra reference */
645 kauth_cred_unref(&my_cred
);
648 * XXX should potentially set per thread security token (there is
650 * XXX it is unclear whether P_SUGID should be st at this point;
651 * XXX in theory, it is being deprecated.
657 * Set the per-thread override identity. Use this system call for a thread to
658 * assume the identity of another process or to revert back to normal identity
659 * of the current process.
660 * When the "assume" argument is non zero the current thread will assume the
661 * identity of the process represented by the pid argument.
662 * When the assume argument is zero we revert back to our normal identity.
665 settid_with_pid(struct proc
*p
, struct settid_with_pid_args
*uap
, __unused register_t
*retval
)
668 struct uthread
*uthread
= get_bsdthread_info(current_thread());
669 kauth_cred_t my_cred
, my_target_cred
, my_new_cred
;
671 AUDIT_ARG(pid
, uap
->pid
);
672 AUDIT_ARG(value
, uap
->assume
);
674 if (suser(p
->p_ucred
, &p
->p_acflag
) != 0) {
679 * XXX should potentially set per thread security token (there is
681 * XXX it is unclear whether P_SUGID should be st at this point;
682 * XXX in theory, it is being deprecated.
686 * assume argument tells us to assume the identity of the process with the
687 * id passed in the pid argument.
689 if (uap
->assume
!= 0) {
690 /* can't do this if we have already assumed an identity */
691 if ((uthread
->uu_flag
& UT_SETUID
) != 0)
694 target_proc
= pfind(uap
->pid
);
695 /* can't assume the identity of the kernel process */
696 if (target_proc
== NULL
|| target_proc
== kernproc
) {
701 * take a reference on the credential used in our target process then use
702 * it as the identity for our current thread.
704 kauth_cred_ref(uthread
->uu_ucred
);
705 my_cred
= uthread
->uu_ucred
;
706 my_target_cred
= kauth_cred_proc_ref(target_proc
);
707 my_new_cred
= kauth_cred_setuidgid(my_cred
, my_target_cred
->cr_uid
, my_target_cred
->cr_gid
);
708 if (my_cred
!= my_new_cred
)
709 uthread
->uu_ucred
= my_new_cred
;
711 uthread
->uu_flag
|= UT_SETUID
;
713 /* drop our extra references */
714 kauth_cred_unref(&my_cred
);
715 kauth_cred_unref(&my_target_cred
);
720 /* we are reverting back to normal mode of operation where delayed binding
721 * of the process credential sets the credential in the thread (uu_ucred)
723 if ((uthread
->uu_flag
& UT_SETUID
) == 0)
726 /* revert to delayed binding of process credential */
727 my_new_cred
= kauth_cred_proc_ref(p
);
728 kauth_cred_unref(&uthread
->uu_ucred
);
729 uthread
->uu_ucred
= my_new_cred
;
730 uthread
->uu_flag
&= ~UT_SETUID
;
737 setgroups1(struct proc
*p
, u_int gidsetsize
, user_addr_t gidset
, uid_t gmuid
, __unused register_t
*retval
)
740 gid_t newgroups
[NGROUPS
] = { 0 };
742 kauth_cred_t my_cred
, my_new_cred
;
743 struct uthread
*uthread
= get_bsdthread_info(current_thread());
745 if ((error
= suser(p
->p_ucred
, &p
->p_acflag
)))
755 error
= copyin(gidset
,
756 (caddr_t
)newgroups
, ngrp
* sizeof(gid_t
));
762 if ((uthread
->uu_flag
& UT_SETUID
) != 0) {
764 * If this thread is under an assumed identity, set the
765 * supplementary grouplist on the thread credential instead
766 * of the process one. If we were the only reference holder,
767 * the credential is updated in place, otherwise, our reference
768 * is dropped and we get back a different cred with a reference
769 * already held on it. Because this is per-thread, we don't
770 * need the referencing/locking/retry required for per-process.
772 * Hack: this opts into memberd to avoid needing to use a per
773 * thread credential initgroups() instead of setgroups() in
774 * AFP server to address <rdar://4561060>
776 my_cred
= uthread
->uu_ucred
;
777 uthread
->uu_ucred
= kauth_cred_setgroups(my_cred
, &newgroups
[0], ngrp
, my_cred
->cr_gmuid
);
781 * get current credential and take a reference while we muck
785 my_cred
= kauth_cred_proc_ref(p
);
788 * Set the credential with new info. If there is no
789 * change, we get back the same credential we passed
790 * in; if there is a change, we drop the reference on
791 * the credential we passed in. The subsequent
792 * compare is safe, because it is a pointer compare
793 * rather than a contents compare.
795 my_new_cred
= kauth_cred_setgroups(my_cred
, &newgroups
[0], ngrp
, gmuid
);
796 if (my_cred
!= my_new_cred
) {
799 * need to protect for a race where another
800 * thread also changed the credential after we
801 * took our reference. If p_ucred has
802 * changed then we should restart this again
805 if (p
->p_ucred
!= my_cred
) {
807 kauth_cred_unref(&my_new_cred
);
811 p
->p_ucred
= my_new_cred
;
812 p
->p_flag
|= P_SUGID
;
815 /* drop old proc reference or our extra reference */
816 kauth_cred_unref(&my_cred
);
820 AUDIT_ARG(groupset
, p
->p_ucred
->cr_groups
, ngrp
);
821 set_security_token(p
);
828 initgroups(struct proc
*p
, struct initgroups_args
*uap
, __unused register_t
*retval
)
830 return(setgroups1(p
, uap
->gidsetsize
, uap
->gidset
, uap
->gmuid
, retval
));
834 setgroups(struct proc
*p
, struct setgroups_args
*uap
, __unused register_t
*retval
)
836 return(setgroups1(p
, uap
->gidsetsize
, uap
->gidset
, KAUTH_UID_NONE
, retval
));
840 * Set the per-thread/per-process supplementary groups list.
842 #warning XXX implement
844 setsgroups(__unused
struct proc
*p
, __unused
struct setsgroups_args
*uap
, __unused register_t
*retval
)
850 * Set the per-thread/per-process whiteout groups list.
852 #warning XXX implement
854 setwgroups(__unused
struct proc
*p
, __unused
struct setwgroups_args
*uap
, __unused register_t
*retval
)
860 * Check if gid is a member of the group set.
862 * XXX This interface is going away
865 groupmember(gid_t gid
, kauth_cred_t cred
)
869 if (kauth_cred_ismember_gid(cred
, gid
, &is_member
) == 0 && is_member
)
875 * Test whether the specified credentials imply "super-user"
876 * privilege; if so, and we have accounting info, set the flag
877 * indicating use of super-powers.
878 * Returns 0 or error.
880 * XXX This interface is going away
883 suser(kauth_cred_t cred
, u_short
*acflag
)
886 if (!IS_VALID_CRED(cred
))
889 if (kauth_cred_getuid(cred
) == 0) {
900 struct proc
*p
= current_proc();
905 return (suser(p
->p_ucred
, &p
->p_acflag
) == 0);
911 struct proc
*p
= current_proc();
916 return (suser(p
->p_ucred
, &p
->p_acflag
) == 0 ||
917 p
->p_ucred
->cr_ruid
== 0 || p
->p_ucred
->cr_svuid
== 0);
921 * Get login name, if available.
925 getlogin(struct proc
*p
, struct getlogin_args
*uap
, __unused register_t
*retval
)
928 if (uap
->namelen
> sizeof (p
->p_pgrp
->pg_session
->s_login
))
929 uap
->namelen
= sizeof (p
->p_pgrp
->pg_session
->s_login
);
930 return (copyout((caddr_t
) p
->p_pgrp
->pg_session
->s_login
,
931 uap
->namebuf
, uap
->namelen
));
939 setlogin(struct proc
*p
, struct setlogin_args
*uap
, __unused register_t
*retval
)
944 if ((error
= suser(p
->p_ucred
, &p
->p_acflag
)))
947 error
= copyinstr(uap
->namebuf
,
948 (caddr_t
) p
->p_pgrp
->pg_session
->s_login
,
949 sizeof (p
->p_pgrp
->pg_session
->s_login
) - 1, (size_t *)&dummy
);
951 AUDIT_ARG(text
, p
->p_pgrp
->pg_session
->s_login
);
952 else if (error
== ENAMETOOLONG
)
958 /* Set the secrity token of the task with current euid and eguid */
960 * XXX This needs to change to give the task a reference and/or an opaque
964 set_security_token(struct proc
* p
)
966 security_token_t sec_token
;
967 audit_token_t audit_token
;
970 * Don't allow a vfork child to override the parent's token settings
971 * (since they share a task). Instead, the child will just have to
972 * suffer along using the parent's token until the exec(). It's all
973 * undefined behavior anyway, right?
975 if (p
->task
== current_task()) {
977 uthread
= (uthread_t
)get_bsdthread_info(current_thread());
978 if (uthread
->uu_flag
& UT_VFORK
)
982 /* XXX mach_init doesn't have a p_ucred when it calls this function */
983 if (IS_VALID_CRED(p
->p_ucred
)) {
984 sec_token
.val
[0] = kauth_cred_getuid(p
->p_ucred
);
985 sec_token
.val
[1] = p
->p_ucred
->cr_gid
;
987 sec_token
.val
[0] = 0;
988 sec_token
.val
[1] = 0;
992 * The current layout of the Mach audit token explicitly
993 * adds these fields. But nobody should rely on such
994 * a literal representation. Instead, the BSM library
995 * provides a function to convert an audit token into
996 * a BSM subject. Use of that mechanism will isolate
997 * the user of the trailer from future representation
1000 audit_token
.val
[0] = p
->p_ucred
->cr_au
.ai_auid
;
1001 audit_token
.val
[1] = p
->p_ucred
->cr_uid
;
1002 audit_token
.val
[2] = p
->p_ucred
->cr_gid
;
1003 audit_token
.val
[3] = p
->p_ucred
->cr_ruid
;
1004 audit_token
.val
[4] = p
->p_ucred
->cr_rgid
;
1005 audit_token
.val
[5] = p
->p_pid
;
1006 audit_token
.val
[6] = p
->p_ucred
->cr_au
.ai_asid
;
1007 audit_token
.val
[7] = p
->p_ucred
->cr_au
.ai_termid
.port
;
1009 return (host_security_set_task_token(host_security_self(),
1013 (sec_token
.val
[0]) ?
1015 host_priv_self()) != KERN_SUCCESS
);
1020 * Fill in a struct xucred based on a kauth_cred_t.
1024 cru2x(kauth_cred_t cr
, struct xucred
*xcr
)
1027 bzero(xcr
, sizeof(*xcr
));
1028 xcr
->cr_version
= XUCRED_VERSION
;
1029 xcr
->cr_uid
= kauth_cred_getuid(cr
);
1030 xcr
->cr_ngroups
= cr
->cr_ngroups
;
1031 bcopy(cr
->cr_groups
, xcr
->cr_groups
, sizeof(xcr
->cr_groups
));