2  * Copyright (c) 2000-2008 Apple 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@ 
  29  * Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved 
  32  * Copyright (c) 1982, 1986, 1989, 1990, 1991, 1993 
  33  *      The Regents of the University of California.  All rights reserved. 
  34  * (c) UNIX System Laboratories, Inc. 
  35  * All or some portions of this file are derived from material licensed 
  36  * to the University of California by American Telephone and Telegraph 
  37  * Co. or Unix System Laboratories, Inc. and are reproduced herein with 
  38  * the permission of UNIX System Laboratories, Inc. 
  40  * Redistribution and use in source and binary forms, with or without 
  41  * modification, are permitted provided that the following conditions 
  43  * 1. Redistributions of source code must retain the above copyright 
  44  *    notice, this list of conditions and the following disclaimer. 
  45  * 2. Redistributions in binary form must reproduce the above copyright 
  46  *    notice, this list of conditions and the following disclaimer in the 
  47  *    documentation and/or other materials provided with the distribution. 
  48  * 3. All advertising materials mentioning features or use of this software 
  49  *    must display the following acknowledgement: 
  50  *      This product includes software developed by the University of 
  51  *      California, Berkeley and its contributors. 
  52  * 4. Neither the name of the University nor the names of its contributors 
  53  *    may be used to endorse or promote products derived from this software 
  54  *    without specific prior written permission. 
  56  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 
  57  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
  58  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
  59  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 
  60  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
  61  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
  62  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
  63  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
  64  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
  65  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
  68  *      @(#)kern_prot.c 8.9 (Berkeley) 2/14/95 
  71  * NOTICE: This file was modified by McAfee Research in 2004 to introduce 
  72  * support for mandatory and extensible security protections.  This notice 
  73  * is included in support of clause 2.2 (b) of the Apple Public License, 
  77  * NOTICE: This file was modified by SPARTA, Inc. in 2005 to introduce 
  78  * support for mandatory and extensible security protections.  This notice 
  79  * is included in support of clause 2.2 (b) of the Apple Public License, 
  85  * System calls related to processes and protection 
  88 #include <sys/param.h> 
  90 #include <sys/systm.h> 
  91 #include <sys/ucred.h> 
  92 #include <sys/proc_internal.h> 
  94 #include <sys/kauth.h> 
  95 #include <sys/timeb.h> 
  96 #include <sys/times.h> 
  97 #include <sys/malloc.h> 
  99 #define chgproccnt_ok(p) 1 
 101 #include <security/audit/audit.h> 
 104 #include <security/mac_framework.h> 
 107 #include <sys/mount_internal.h> 
 108 #include <sys/sysproto.h> 
 109 #include <mach/message.h> 
 110 #include <mach/host_security.h> 
 112 #include <kern/host.h> 
 113 #include <kern/task.h>          /* for current_task() */ 
 114 #include <kern/assert.h> 
 118  * Credential debugging; we can track entry into a function that might 
 119  * change a credential, and we can track actual credential changes that 
 122  * Note:        Does *NOT* currently include per-thread credential changes 
 124  *              We don't use kauth_cred_print() in current debugging, but it 
 125  *              can be used if needed when debugging is active. 
 128 #define DEBUG_CRED_ENTER                printf 
 129 #define DEBUG_CRED_CHANGE               printf 
 130 extern void kauth_cred_print(kauth_cred_t cred
); 
 131 #else   /* !DEBUG_CRED */ 
 132 #define DEBUG_CRED_ENTER(fmt, ...)      do {} while (0) 
 133 #define DEBUG_CRED_CHANGE(fmt, ...)     do {} while (0) 
 134 #endif  /* !DEBUG_CRED */ 
 136 #if DEVELOPMENT || DEBUG 
 137 extern void task_importance_update_owner_info(task_t
); 
 144  * Description: (dis)allow this process to hold task, thread, or execption 
 145  *              ports of processes about to exec. 
 147  * Parameters:  uap->flag                       New value for flag 
 149  * Returns:     int                             Previous value of flag 
 151  * XXX:         Belongs in kern_proc.c 
 154 setprivexec(proc_t p
, struct setprivexec_args 
*uap
, int32_t *retval
) 
 156         AUDIT_ARG(value32
, uap
->flag
); 
 157         *retval 
= p
->p_debugger
; 
 158         p
->p_debugger 
= (uap
->flag 
!= 0); 
 166  * Description: get the process ID 
 170  * Returns:     pid_t                           Current process ID 
 172  * XXX:         Belongs in kern_proc.c 
 175 getpid(proc_t p
, __unused 
struct getpid_args 
*uap
, int32_t *retval
) 
 186  * Description: get the parent process ID 
 190  * Returns:     pid_t                           Parent process ID 
 192  * XXX:         Belongs in kern_proc.c 
 195 getppid(proc_t p
, __unused 
struct getppid_args 
*uap
, int32_t *retval
) 
 206  * Description: get the process group ID of the calling process 
 210  * Returns:     pid_t                           Process group ID 
 212  * XXX:         Belongs in kern_proc.c 
 215 getpgrp(proc_t p
, __unused 
struct getpgrp_args 
*uap
, int32_t *retval
) 
 218         *retval 
= p
->p_pgrpid
; 
 226  * Description: Get an arbitary pid's process group id 
 228  * Parameters:  uap->pid                        The target pid 
 231  *              ESRCH                           No such process 
 233  * Notes:       We are permitted to return EPERM in the case that the target 
 234  *              process is not in the same session as the calling process, 
 235  *              which could be a security consideration 
 237  * XXX:         Belongs in kern_proc.c 
 240 getpgid(proc_t p
, struct getpgid_args 
*uap
, int32_t *retval
) 
 249         if ((pt 
= proc_find(uap
->pid
)) == 0) 
 253         *retval 
= pt
->p_pgrpid
; 
 263  * Description: Get an arbitary pid's session leaders process group ID 
 265  * Parameters:  uap->pid                        The target pid 
 268  *              ESRCH                           No such process 
 270  * Notes:       We are permitted to return EPERM in the case that the target 
 271  *              process is not in the same session as the calling process, 
 272  *              which could be a security consideration 
 274  * XXX:         Belongs in kern_proc.c 
 277 getsid(proc_t p
, struct getsid_args 
*uap
, int32_t *retval
) 
 281         struct session 
* sessp
; 
 287         if ((pt 
= proc_find(uap
->pid
)) == 0) 
 291         sessp 
= proc_session(pt
); 
 292         *retval 
= sessp
->s_sid
; 
 304  * Description: get real user ID for caller 
 308  * Returns:     uid_t                           The real uid of the caller 
 311 getuid(__unused proc_t p
, __unused 
struct getuid_args 
*uap
, int32_t *retval
) 
 314         *retval 
= kauth_getruid(); 
 322  * Description: get effective user ID for caller 
 326  * Returns:     uid_t                           The effective uid of the caller 
 329 geteuid(__unused proc_t p
, __unused 
struct geteuid_args 
*uap
, int32_t *retval
) 
 332         *retval 
= kauth_getuid(); 
 340  * Description: Return the per-thread override identity. 
 342  * Parameters:  uap->uidp                       Address of uid_t to get uid 
 343  *              uap->gidp                       Address of gid_t to get gid 
 346  *              ESRCH                           No per thread identity active 
 349 gettid(__unused proc_t p
, struct gettid_args 
*uap
, int32_t *retval
) 
 351         struct uthread 
*uthread 
= get_bsdthread_info(current_thread()); 
 355          * If this thread is not running with an override identity, we can't 
 356          * return one to the caller, so return an error instead. 
 358         if (!(uthread
->uu_flag 
& UT_SETUID
)) 
 361         if ((error 
= suword(uap
->uidp
, kauth_cred_getruid(uthread
->uu_ucred
)))) 
 363         if ((error 
= suword(uap
->gidp
, kauth_cred_getrgid(uthread
->uu_ucred
)))) 
 374  * Description: get the real group ID for the calling process 
 378  * Returns:     gid_t                           The real gid of the caller 
 381 getgid(__unused proc_t p
, __unused 
struct getgid_args 
*uap
, int32_t *retval
) 
 384         *retval 
= kauth_getrgid(); 
 392  * Description: get the effective group ID for the calling process 
 396  * Returns:     gid_t                           The effective gid of the caller 
 398  * Notes:       As an implementation detail, the effective gid is stored as 
 399  *              the first element of the supplementary group list. 
 401  *              This could be implemented in Libc instead because of the above 
 405 getegid(__unused proc_t p
, __unused 
struct getegid_args 
*uap
, int32_t *retval
) 
 408         *retval 
= kauth_getgid(); 
 416  * Description: get the list of supplementary groups for the calling process 
 418  * Parameters:  uap->gidsetsize                 # of gid_t's in user buffer 
 419  *              uap->gidset                     Pointer to user buffer 
 422  *              EINVAL                          User buffer too small 
 423  *      copyout:EFAULT                          User buffer invalid 
 428  * Notes:       The caller may specify a 0 value for gidsetsize, and we will 
 429  *              then return how large a buffer is required (in gid_t's) to 
 430  *              contain the answer at the time of the call.  Otherwise, we 
 431  *              return the number of gid_t's catually copied to user space. 
 433  *              When called with a 0 gidsetsize from a multithreaded program, 
 434  *              there is no guarantee that another thread may not change the 
 435  *              number of supplementary groups, and therefore a subsequent 
 436  *              call could still fail, unless the maximum possible buffer 
 437  *              size is supplied by the user. 
 439  *              As an implementation detail, the effective gid is stored as 
 440  *              the first element of the supplementary group list, and will 
 441  *              be returned by this call. 
 444 getgroups(__unused proc_t p
, struct getgroups_args 
*uap
, int32_t *retval
) 
 451         /* grab reference while we muck around with the credential */ 
 452         cred 
= kauth_cred_get_with_ref(); 
 453         pcred 
= posix_cred_get(cred
); 
 455         if ((ngrp 
= uap
->gidsetsize
) == 0) { 
 456                 *retval 
= pcred
->cr_ngroups
; 
 457                 kauth_cred_unref(&cred
); 
 460         if (ngrp 
< pcred
->cr_ngroups
) { 
 461                 kauth_cred_unref(&cred
); 
 464         ngrp 
= pcred
->cr_ngroups
; 
 465         if ((error 
= copyout((caddr_t
)pcred
->cr_groups
, 
 467                                         ngrp 
* sizeof(gid_t
)))) { 
 468                 kauth_cred_unref(&cred
); 
 471         kauth_cred_unref(&cred
); 
 478  * Return the per-thread/per-process supplementary groups list. 
 480  * XXX implement getsgroups 
 485 getsgroups(__unused proc_t p
, __unused 
struct getsgroups_args 
*uap
, __unused 
int32_t *retval
) 
 491  * Return the per-thread/per-process whiteout groups list. 
 493  * XXX implement getwgroups 
 498 getwgroups(__unused proc_t p
, __unused 
struct getwgroups_args 
*uap
, __unused 
int32_t *retval
) 
 507  * Description: Create a new session and set the process group ID to the 
 513  *              EPERM                           Permission denied 
 515  * Notes:       If the calling process is not the process group leader; there 
 516  *              is no existing process group with its ID, and we are not 
 517  *              currently in vfork, then this function will create a new 
 518  *              session, a new process group, and put the caller in the 
 519  *              process group (as the sole member) and make it the session 
 520  *              leader (as the sole process in the session). 
 522  *              The existing controlling tty (if any) will be dissociated 
 523  *              from the process, and the next non-O_NOCTTY open of a tty 
 524  *              will establish a new controlling tty. 
 526  * XXX:         Belongs in kern_proc.c 
 529 setsid(proc_t p
, __unused 
struct setsid_args 
*uap
, int32_t *retval
) 
 531         struct pgrp 
* pg 
= PGRP_NULL
; 
 533         if (p
->p_pgrpid 
== p
->p_pid 
|| (pg 
= pgfind(p
->p_pid
)) || p
->p_lflag 
& P_LINVFORK
) { 
 538                 /* enter pgrp works with its own pgrp refcount */ 
 539                 (void)enterpgrp(p
, p
->p_pid
, 1); 
 549  * Description: set process group ID for job control 
 551  * Parameters:  uap->pid                        Process to change 
 552  *              uap->pgid                       Process group to join or create 
 555  *              ESRCH                   pid is not the caller or a child of 
 557  *      enterpgrp:ESRCH                 No such process 
 558  *              EACCES                  Permission denied due to exec 
 559  *              EINVAL                  Invalid argument 
 560  *              EPERM                   The target process is not in the same 
 561  *                                      session as the calling process 
 562  *              EPERM                   The target process is a session leader 
 563  *              EPERM                   pid and pgid are not the same, and 
 564  *                                      there is no process in the calling 
 565  *                                      process whose process group ID matches 
 568  * Notes:       This function will cause the target process to either join 
 569  *              an existing process process group, or create a new process 
 570  *              group in the session of the calling process.  It cannot be 
 571  *              used to change the process group ID of a process which is 
 572  *              already a session leader. 
 574  *              If the target pid is 0, the pid of the calling process is 
 575  *              substituted as the new target; if pgid is 0, the target pid 
 576  *              is used as the target process group ID. 
 578  * Legacy:      This system call entry point is also used to implement the 
 579  *              legacy library routine setpgrp(), which under POSIX  
 581  * XXX:         Belongs in kern_proc.c 
 584 setpgid(proc_t curp
, register struct setpgid_args 
*uap
, __unused 
int32_t *retval
) 
 586         proc_t targp 
= PROC_NULL
;       /* target process */ 
 587         struct pgrp 
*pg 
= PGRP_NULL
;    /* target pgrp */ 
 591         struct session 
* curp_sessp 
= SESSION_NULL
; 
 592         struct session 
* targp_sessp 
= SESSION_NULL
; 
 594         curp_sessp 
= proc_session(curp
); 
 596         if (uap
->pid 
!= 0 && uap
->pid 
!= curp
->p_pid
) { 
 597                 if ((targp 
= proc_find(uap
->pid
)) == 0 || !inferior(targp
)) { 
 598                         if (targp 
!= PROC_NULL
) 
 604                 targp_sessp 
= proc_session(targp
); 
 605                 if (targp_sessp 
!= curp_sessp
) { 
 609                 if (targp
->p_flag 
& P_EXEC
) { 
 615                 targp_sessp 
= proc_session(targp
); 
 618         if (SESS_LEADER(targp
, targp_sessp
)) { 
 622         if (targp_sessp 
!= SESSION_NULL
) { 
 623                 session_rele(targp_sessp
); 
 624                 targp_sessp 
= SESSION_NULL
; 
 632                 uap
->pgid 
= targp
->p_pid
; 
 633         else if (uap
->pgid 
!= targp
->p_pid
) { 
 634                 if ((pg 
= pgfind(uap
->pgid
)) == 0){ 
 638                 samesess 
= (pg
->pg_session 
!= curp_sessp
);  
 645         error 
= enterpgrp(targp
, uap
->pgid
, 0); 
 647         if (targp_sessp 
!= SESSION_NULL
) 
 648                 session_rele(targp_sessp
); 
 649         if (curp_sessp 
!= SESSION_NULL
) 
 650                 session_rele(curp_sessp
); 
 660  * Description: Is current process tainted by uid or gid changes system call 
 664  * Returns:     0                               Not tainted 
 667  * Notes:       A process is considered tainted if it was created as a retult 
 668  *              of an execve call from an imnage that had either the SUID or 
 669  *              SGID bit set on the executable, or if it has changed any of its 
 670  *              real, effective, or saved user or group IDs since beginning 
 674 issetugid(proc_t p
, __unused 
struct issetugid_args 
*uap
, int32_t *retval
) 
 677          * Note: OpenBSD sets a P_SUGIDEXEC flag set at execve() time, 
 678          * we use P_SUGID because we consider changing the owners as 
 679          * "tainting" as well. 
 680          * This is significant for procs that start as root and "become" 
 681          * a user without an exec - programs cannot know *everything* 
 682          * that libc *might* have put in their data segment. 
 685         *retval 
= (p
->p_flag 
& P_SUGID
) ? 1 : 0; 
 693  * Description: Set user ID system call 
 695  * Parameters:  uap->uid                        uid to set 
 698  *      suser:EPERM                             Permission denied 
 700  * Notes:       If called by a privileged process, this function will set the 
 701  *              real, effective, and saved uid to the requested value. 
 703  *              If called from an unprivileged process, but uid is equal to the 
 704  *              real or saved uid, then the effective uid will be set to the 
 705  *              requested value, but the real and saved uid will not change. 
 707  *              If the credential is changed as a result of this call, then we 
 708  *              flag the process as having set privilege since the last exec. 
 711 setuid(proc_t p
, struct setuid_args 
*uap
, __unused 
int32_t *retval
) 
 714         uid_t svuid 
= KAUTH_UID_NONE
; 
 715         uid_t ruid 
= KAUTH_UID_NONE
; 
 716         uid_t gmuid 
= KAUTH_UID_NONE
; 
 718         kauth_cred_t my_cred
, my_new_cred
; 
 719         posix_cred_t my_pcred
; 
 723         /* get current credential and take a reference while we muck with it */ 
 724         my_cred 
= kauth_cred_proc_ref(p
); 
 725         my_pcred 
= posix_cred_get(my_cred
); 
 727         DEBUG_CRED_ENTER("setuid (%d/%d): %p %d\n", p
->p_pid
, (p
->p_pptr 
? p
->p_pptr
->p_pid 
: 0), my_cred
, uap
->uid
); 
 731                 if (uid 
!= my_pcred
->cr_ruid 
&&         /* allow setuid(getuid()) */ 
 732                     uid 
!= my_pcred
->cr_svuid 
&&        /* allow setuid(saved uid) */ 
 733                     (error 
= suser(my_cred
, &p
->p_acflag
))) { 
 734                         kauth_cred_unref(&my_cred
); 
 739                  * If we are privileged, then set the saved and real UID too; 
 740                  * otherwise, just set the effective UID 
 742                 if (suser(my_cred
, &p
->p_acflag
) == 0) { 
 746                         svuid 
= KAUTH_UID_NONE
; 
 747                         ruid 
= KAUTH_UID_NONE
; 
 750                  * Only set the gmuid if the current cred has not opt'ed out; 
 751                  * this normally only happens when calling setgroups() instead 
 752                  * of initgroups() to set an explicit group list, or one of the 
 753                  * other group manipulation functions is invoked and results in 
 754                  * a dislocation (i.e. the credential group membership changes 
 755                  * to something other than the default list for the user, as 
 756                  * in entering a group or leaving an exclusion group). 
 758                 if (!(my_pcred
->cr_flags 
& CRF_NOMEMBERD
)) 
 762                  * Set the credential with new info.  If there is no change, 
 763                  * we get back the same credential we passed in; if there is 
 764                  * a change, we drop the reference on the credential we 
 765                  * passed in.  The subsequent compare is safe, because it is 
 766                  * a pointer compare rather than a contents compare. 
 768                 my_new_cred 
= kauth_cred_setresuid(my_cred
, ruid
, uid
, svuid
, gmuid
); 
 769                 if (my_cred 
!= my_new_cred
) { 
 771                         DEBUG_CRED_CHANGE("setuid CH(%d): %p/0x%08x -> %p/0x%08x\n", p
->p_pid
, my_cred
, my_pcred
->cr_flags
, my_new_cred
, posix_cred_get(my_new_cred
)->cr_flags
); 
 774                          * If we're changing the ruid from A to B, we might race with another thread that's setting ruid from B to A. 
 775                          * The current locking mechanisms don't allow us to make the entire credential switch operation atomic, 
 776                          * thus we may be able to change the process credentials from ruid A to B, but get preempted before incrementing the proc 
 777                          * count of B. If a second thread sees the new process credentials and switches back to ruid A, that other thread 
 778                          * may be able to decrement the proc count of B before we can increment it. This results in a panic. 
 779                          * Incrementing the proc count of the target ruid, B, before setting the process credentials prevents this race. 
 781                         if (ruid 
!= KAUTH_UID_NONE 
&& chgproccnt_ok(p
)) { 
 782                                 (void)chgproccnt(ruid
, 1); 
 787                          * We need to protect for a race where another thread 
 788                          * also changed the credential after we took our 
 789                          * reference.  If p_ucred has changed then we should 
 790                          * restart this again with the new cred. 
 792                          * Note: the kauth_cred_setresuid has consumed a reference to my_cred, it p_ucred != my_cred, then my_cred must not be dereferenced! 
 794                         if (p
->p_ucred 
!= my_cred
) { 
 795                                 proc_ucred_unlock(p
); 
 797                                  * We didn't successfully switch to the new ruid, so decrement 
 798                                  * the procs/uid count that we incremented above. 
 800                                 if (ruid 
!= KAUTH_UID_NONE 
&& chgproccnt_ok(p
)) { 
 801                                         (void)chgproccnt(ruid
, -1); 
 803                                 kauth_cred_unref(&my_new_cred
); 
 804                                 my_cred 
= kauth_cred_proc_ref(p
); 
 805                                 my_pcred 
= posix_cred_get(my_cred
); 
 809                         p
->p_ucred 
= my_new_cred
; 
 810                         /* update cred on proc */ 
 811                         PROC_UPDATE_CREDS_ONPROC(p
); 
 813                         OSBitOrAtomic(P_SUGID
, &p
->p_flag
); 
 814                         proc_ucred_unlock(p
); 
 816                          * If we've updated the ruid, decrement the count of procs running 
 817                          * under the previous ruid 
 819                         if (ruid 
!= KAUTH_UID_NONE 
&& chgproccnt_ok(p
)) { 
 820                                 (void)chgproccnt(my_pcred
->cr_ruid
, -1); 
 825         /* Drop old proc reference or our extra reference */ 
 826         kauth_cred_unref(&my_cred
); 
 828         set_security_token(p
); 
 836  * Description: Set effective user ID system call 
 838  * Parameters:  uap->euid                       effective uid to set 
 841  *      suser:EPERM                             Permission denied 
 843  * Notes:       If called by a privileged process, or called from an 
 844  *              unprivileged process but euid is equal to the real or saved 
 845  *              uid, then the effective uid will be set to the requested 
 846  *              value, but the real and saved uid will not change. 
 848  *              If the credential is changed as a result of this call, then we 
 849  *              flag the process as having set privilege since the last exec. 
 852 seteuid(proc_t p
, struct seteuid_args 
*uap
, __unused 
int32_t *retval
) 
 856         kauth_cred_t my_cred
, my_new_cred
; 
 857         posix_cred_t my_pcred
; 
 859         DEBUG_CRED_ENTER("seteuid: %d\n", uap
->euid
); 
 862         AUDIT_ARG(euid
, euid
); 
 864         my_cred 
= kauth_cred_proc_ref(p
); 
 865         my_pcred 
= posix_cred_get(my_cred
); 
 869                 if (euid 
!= my_pcred
->cr_ruid 
&& euid 
!= my_pcred
->cr_svuid 
&& 
 870                         (error 
= suser(my_cred
, &p
->p_acflag
))) { 
 871                         kauth_cred_unref(&my_cred
); 
 876                  * Set the credential with new info.  If there is no change, 
 877                  * we get back the same credential we passed in; if there is 
 878                  * a change, we drop the reference on the credential we 
 879                  * passed in.  The subsequent compare is safe, because it is 
 880                  * a pointer compare rather than a contents compare. 
 882                 my_new_cred 
= kauth_cred_setresuid(my_cred
, KAUTH_UID_NONE
, euid
, KAUTH_UID_NONE
, my_pcred
->cr_gmuid
); 
 884                 if (my_cred 
!= my_new_cred
) { 
 886                         DEBUG_CRED_CHANGE("seteuid CH(%d): %p/0x%08x -> %p/0x%08x\n", p
->p_pid
, my_cred
, my_pcred
->cr_flags
, my_new_cred
, posix_cred_get(my_new_cred
)->cr_flags
); 
 890                          * We need to protect for a race where another thread 
 891                          * also changed the credential after we took our 
 892                          * reference.  If p_ucred has changed then we 
 893                          * should restart this again with the new cred. 
 895                         if (p
->p_ucred 
!= my_cred
) { 
 896                                 proc_ucred_unlock(p
); 
 897                                 kauth_cred_unref(&my_new_cred
); 
 898                                 my_cred 
= kauth_cred_proc_ref(p
); 
 899                                 my_pcred 
= posix_cred_get(my_cred
); 
 903                         p
->p_ucred 
= my_new_cred
; 
 904                         /* update cred on proc */ 
 905                         PROC_UPDATE_CREDS_ONPROC(p
); 
 906                         OSBitOrAtomic(P_SUGID
, &p
->p_flag
); 
 907                         proc_ucred_unlock(p
); 
 911         /* drop old proc reference or our extra reference */ 
 912         kauth_cred_unref(&my_cred
); 
 914         set_security_token(p
); 
 922  * Description: Set real and effective user ID system call 
 924  * Parameters:  uap->ruid                       real uid to set 
 925  *              uap->euid                       effective uid to set 
 928  *      suser:EPERM                             Permission denied 
 930  * Notes:       A value of -1 is a special case indicating that the uid for 
 931  *              which that value is specified not be changed.  If both values 
 932  *              are specified as -1, no action is taken. 
 934  *              If called by a privileged process, the real and effective uid 
 935  *              will be set to the new value(s) specified. 
 937  *              If called from an unprivileged process, the real uid may be 
 938  *              set to the current value of the real uid, or to the current 
 939  *              value of the saved uid.  The effective uid may be set to the 
 940  *              current value of any of the effective, real, or saved uid. 
 942  *              If the newly requested real uid or effective uid does not 
 943  *              match the saved uid, then set the saved uid to the new 
 944  *              effective uid (potentially unrecoverably dropping saved 
 947  *              If the credential is changed as a result of this call, then we 
 948  *              flag the process as having set privilege since the last exec. 
 951 setreuid(proc_t p
, struct setreuid_args 
*uap
, __unused 
int32_t *retval
) 
 955         kauth_cred_t my_cred
, my_new_cred
; 
 956         posix_cred_t my_pcred
; 
 958         DEBUG_CRED_ENTER("setreuid %d %d\n", uap
->ruid
, uap
->euid
); 
 962         if (ruid 
== (uid_t
)-1) 
 963                 ruid 
= KAUTH_UID_NONE
; 
 964         if (euid 
== (uid_t
)-1) 
 965                 euid 
= KAUTH_UID_NONE
; 
 966         AUDIT_ARG(euid
, euid
); 
 967         AUDIT_ARG(ruid
, ruid
); 
 969         my_cred 
= kauth_cred_proc_ref(p
); 
 970         my_pcred 
= posix_cred_get(my_cred
); 
 974                 if (((ruid 
!= KAUTH_UID_NONE 
&&         /* allow no change of ruid */ 
 975                       ruid 
!= my_pcred
->cr_ruid 
&&      /* allow ruid = ruid */ 
 976                       ruid 
!= my_pcred
->cr_uid 
&&       /* allow ruid = euid */ 
 977                       ruid 
!= my_pcred
->cr_svuid
) ||    /* allow ruid = svuid */ 
 978                      (euid 
!= KAUTH_UID_NONE 
&&         /* allow no change of euid */ 
 979                       euid 
!= my_pcred
->cr_uid 
&&       /* allow euid = euid */ 
 980                       euid 
!= my_pcred
->cr_ruid 
&&      /* allow euid = ruid */ 
 981                       euid 
!= my_pcred
->cr_svuid
)) &&   /* allow euid = svuid */ 
 982                     (error 
= suser(my_cred
, &p
->p_acflag
))) { /* allow root user any */ 
 983                         kauth_cred_unref(&my_cred
); 
 988                 uid_t svuid 
= KAUTH_UID_NONE
; 
 990                 new_euid 
= my_pcred
->cr_uid
; 
 992                  * Set the credential with new info.  If there is no change, 
 993                  * we get back the same credential we passed in; if there is 
 994                  * a change, we drop the reference on the credential we 
 995                  * passed in.  The subsequent compare is safe, because it is 
 996                  * a pointer compare rather than a contents compare. 
 998                 if (euid 
!= KAUTH_UID_NONE 
&& my_pcred
->cr_uid 
!= euid
) { 
 999                         /* changing the effective UID */ 
1001                         OSBitOrAtomic(P_SUGID
, &p
->p_flag
); 
1004                  * If the newly requested real uid or effective uid does 
1005                  * not match the saved uid, then set the saved uid to the 
1006                  * new effective uid.  We are protected from escalation 
1007                  * by the prechecking. 
1009                 if (my_pcred
->cr_svuid 
!= uap
->ruid 
&& 
1010                     my_pcred
->cr_svuid 
!= uap
->euid
) { 
1012                         OSBitOrAtomic(P_SUGID
, &p
->p_flag
); 
1015                 my_new_cred 
= kauth_cred_setresuid(my_cred
, ruid
, euid
, svuid
, my_pcred
->cr_gmuid
); 
1017                 if (my_cred 
!= my_new_cred
) { 
1019                         DEBUG_CRED_CHANGE("setreuid CH(%d): %p/0x%08x -> %p/0x%08x\n", p
->p_pid
, my_cred
, my_pcred
->cr_flags
, my_new_cred
, posix_cred_get(my_new_cred
)->cr_flags
); 
1022                          * If we're changing the ruid from A to B, we might race with another thread that's setting ruid from B to A. 
1023                          * The current locking mechanisms don't allow us to make the entire credential switch operation atomic, 
1024                          * thus we may be able to change the process credentials from ruid A to B, but get preempted before incrementing the proc 
1025                          * count of B. If a second thread sees the new process credentials and switches back to ruid A, that other thread 
1026                          * may be able to decrement the proc count of B before we can increment it. This results in a panic. 
1027                          * Incrementing the proc count of the target ruid, B, before setting the process credentials prevents this race. 
1029                         if (ruid 
!= KAUTH_UID_NONE 
&& chgproccnt_ok(p
)) { 
1030                                 (void)chgproccnt(ruid
, 1); 
1035                          * We need to protect for a race where another thread 
1036                          * also changed the credential after we took our 
1037                          * reference.  If p_ucred has changed then we should 
1038                          * restart this again with the new cred. 
1040                          * Note: the kauth_cred_setresuid has consumed a reference to my_cred, it p_ucred != my_cred, then my_cred must not be dereferenced! 
1042                         if (p
->p_ucred 
!= my_cred
) { 
1043                                 proc_ucred_unlock(p
); 
1044                                 if (ruid 
!= KAUTH_UID_NONE 
&& chgproccnt_ok(p
)) { 
1046                                          * We didn't successfully switch to the new ruid, so decrement 
1047                                          * the procs/uid count that we incremented above. 
1049                                         (void)chgproccnt(ruid
, -1); 
1051                                 kauth_cred_unref(&my_new_cred
); 
1052                                 my_cred 
= kauth_cred_proc_ref(p
); 
1053                                 my_pcred 
= posix_cred_get(my_cred
); 
1058                         p
->p_ucred 
= my_new_cred
; 
1059                         /* update cred on proc */ 
1060                         PROC_UPDATE_CREDS_ONPROC(p
); 
1061                         OSBitOrAtomic(P_SUGID
, &p
->p_flag
); 
1062                         proc_ucred_unlock(p
); 
1064                         if (ruid 
!= KAUTH_UID_NONE 
&& chgproccnt_ok(p
)) { 
1066                                  * We switched to a new ruid, so decrement the count of procs running 
1067                                  * under the previous ruid 
1069                                 (void)chgproccnt(my_pcred
->cr_ruid
, -1); 
1074         /* drop old proc reference or our extra reference */ 
1075         kauth_cred_unref(&my_cred
); 
1077         set_security_token(p
); 
1085  * Description: Set group ID system call 
1087  * Parameters:  uap->gid                        gid to set 
1089  * Returns:     0                               Success 
1090  *      suser:EPERM                             Permission denied 
1092  * Notes:       If called by a privileged process, this function will set the 
1093  *              real, effective, and saved gid to the requested value. 
1095  *              If called from an unprivileged process, but gid is equal to the 
1096  *              real or saved gid, then the effective gid will be set to the 
1097  *              requested value, but the real and saved gid will not change. 
1099  *              If the credential is changed as a result of this call, then we 
1100  *              flag the process as having set privilege since the last exec. 
1102  *              As an implementation detail, the effective gid is stored as 
1103  *              the first element of the supplementary group list, and 
1104  *              therefore the effective group list may be reordered to keep 
1105  *              the supplementary group list unchanged. 
1108 setgid(proc_t p
, struct setgid_args 
*uap
, __unused 
int32_t *retval
) 
1111         gid_t rgid 
= KAUTH_GID_NONE
; 
1112         gid_t svgid 
= KAUTH_GID_NONE
; 
1114         kauth_cred_t my_cred
, my_new_cred
; 
1115         posix_cred_t my_pcred
; 
1117         DEBUG_CRED_ENTER("setgid(%d/%d): %d\n", p
->p_pid
, (p
->p_pptr 
? p
->p_pptr
->p_pid 
: 0), uap
->gid
); 
1120         AUDIT_ARG(gid
, gid
); 
1122         /* get current credential and take a reference while we muck with it */ 
1123         my_cred 
= kauth_cred_proc_ref(p
); 
1124         my_pcred 
= posix_cred_get(my_cred
); 
1127                 if (gid 
!= my_pcred
->cr_rgid 
&&         /* allow setgid(getgid()) */ 
1128                     gid 
!= my_pcred
->cr_svgid 
&&        /* allow setgid(saved gid) */ 
1129                     (error 
= suser(my_cred
, &p
->p_acflag
))) { 
1130                         kauth_cred_unref(&my_cred
); 
1135                  * If we are privileged, then set the saved and real GID too; 
1136                  * otherwise, just set the effective GID 
1138                 if (suser(my_cred
,  &p
->p_acflag
) == 0) { 
1142                         svgid 
= KAUTH_GID_NONE
; 
1143                         rgid 
= KAUTH_GID_NONE
; 
1147                  * Set the credential with new info.  If there is no change, 
1148                  * we get back the same credential we passed in; if there is 
1149                  * a change, we drop the reference on the credential we 
1150                  * passed in.  The subsequent compare is safe, because it is 
1151                  * a pointer compare rather than a contents compare. 
1153                 my_new_cred 
= kauth_cred_setresgid(my_cred
, rgid
, gid
, svgid
); 
1154                 if (my_cred 
!= my_new_cred
) { 
1156                         DEBUG_CRED_CHANGE("setgid(CH)%d: %p/0x%08x->%p/0x%08x\n", p
->p_pid
, my_cred
, my_cred
->cr_flags
, my_new_cred
, my_new_cred
->cr_flags
); 
1160                          * We need to protect for a race where another thread 
1161                          * also changed the credential after we took our 
1162                          * reference.  If p_ucred has changed then we 
1163                          * should restart this again with the new cred. 
1165                         if (p
->p_ucred 
!= my_cred
) { 
1166                                 proc_ucred_unlock(p
); 
1167                                 kauth_cred_unref(&my_new_cred
); 
1169                                 my_cred 
= kauth_cred_proc_ref(p
); 
1170                                 my_pcred 
= posix_cred_get(my_cred
); 
1173                         p
->p_ucred 
= my_new_cred
; 
1174                         /* update cred on proc */ 
1175                         PROC_UPDATE_CREDS_ONPROC(p
); 
1176                         OSBitOrAtomic(P_SUGID
, &p
->p_flag
); 
1177                         proc_ucred_unlock(p
); 
1181         /* Drop old proc reference or our extra reference */ 
1182         kauth_cred_unref(&my_cred
); 
1184         set_security_token(p
); 
1192  * Description: Set effective group ID system call 
1194  * Parameters:  uap->egid                       effective gid to set 
1196  * Returns:     0                               Success 
1199  * Notes:       If called by a privileged process, or called from an 
1200  *              unprivileged process but egid is equal to the real or saved 
1201  *              gid, then the effective gid will be set to the requested 
1202  *              value, but the real and saved gid will not change. 
1204  *              If the credential is changed as a result of this call, then we 
1205  *              flag the process as having set privilege since the last exec. 
1207  *              As an implementation detail, the effective gid is stored as 
1208  *              the first element of the supplementary group list, and 
1209  *              therefore the effective group list may be reordered to keep 
1210  *              the supplementary group list unchanged. 
1213 setegid(proc_t p
, struct setegid_args 
*uap
, __unused 
int32_t *retval
) 
1217         kauth_cred_t my_cred
, my_new_cred
; 
1218         posix_cred_t my_pcred
; 
1220         DEBUG_CRED_ENTER("setegid %d\n", uap
->egid
); 
1223         AUDIT_ARG(egid
, egid
); 
1225         /* get current credential and take a reference while we muck with it */ 
1226         my_cred 
= kauth_cred_proc_ref(p
); 
1227         my_pcred 
= posix_cred_get(my_cred
); 
1231                 if (egid 
!= my_pcred
->cr_rgid 
&& 
1232                     egid 
!= my_pcred
->cr_svgid 
&& 
1233                     (error 
= suser(my_cred
, &p
->p_acflag
))) { 
1234                         kauth_cred_unref(&my_cred
); 
1238                  * Set the credential with new info.  If there is no change, 
1239                  * we get back the same credential we passed in; if there is 
1240                  * a change, we drop the reference on the credential we 
1241                  * passed in.  The subsequent compare is safe, because it is 
1242                  * a pointer compare rather than a contents compare. 
1244                 my_new_cred 
= kauth_cred_setresgid(my_cred
, KAUTH_GID_NONE
, egid
, KAUTH_GID_NONE
); 
1245                 if (my_cred 
!= my_new_cred
) { 
1247                         DEBUG_CRED_CHANGE("setegid(CH)%d: %p/0x%08x->%p/0x%08x\n", p
->p_pid
, my_cred
, my_pcred
->cr_flags
, my_new_cred
, posix_cred_get(my_new_cred
)->cr_flags
); 
1251                          * We need to protect for a race where another thread 
1252                          * also changed the credential after we took our 
1253                          * reference.  If p_ucred has changed then we 
1254                          * should restart this again with the new cred. 
1256                         if (p
->p_ucred 
!= my_cred
) { 
1257                                 proc_ucred_unlock(p
); 
1258                                 kauth_cred_unref(&my_new_cred
); 
1260                                 my_cred 
= kauth_cred_proc_ref(p
); 
1261                                 my_pcred 
= posix_cred_get(my_cred
); 
1264                         p
->p_ucred 
= my_new_cred
; 
1265                         /* update cred on proc */ 
1266                         PROC_UPDATE_CREDS_ONPROC(p
); 
1267                         OSBitOrAtomic(P_SUGID
, &p
->p_flag
); 
1268                         proc_ucred_unlock(p
); 
1273         /* Drop old proc reference or our extra reference */ 
1274         kauth_cred_unref(&my_cred
); 
1276         set_security_token(p
); 
1283  * Description: Set real and effective group ID system call 
1285  * Parameters:  uap->rgid                       real gid to set 
1286  *              uap->egid                       effective gid to set 
1288  * Returns:     0                               Success 
1289  *      suser:EPERM                             Permission denied 
1291  * Notes:       A value of -1 is a special case indicating that the gid for 
1292  *              which that value is specified not be changed.  If both values 
1293  *              are specified as -1, no action is taken. 
1295  *              If called by a privileged process, the real and effective gid 
1296  *              will be set to the new value(s) specified. 
1298  *              If called from an unprivileged process, the real gid may be 
1299  *              set to the current value of the real gid, or to the current 
1300  *              value of the saved gid.  The effective gid may be set to the 
1301  *              current value of any of the effective, real, or saved gid. 
1303  *              If the new real and effective gid will not be equal, or the 
1304  *              new real or effective gid is not the same as the saved gid, 
1305  *              then the saved gid will be updated to reflect the new 
1306  *              effective gid (potentially unrecoverably dropping saved 
1309  *              If the credential is changed as a result of this call, then we 
1310  *              flag the process as having set privilege since the last exec. 
1312  *              As an implementation detail, the effective gid is stored as 
1313  *              the first element of the supplementary group list, and 
1314  *              therefore the effective group list may be reordered to keep 
1315  *              the supplementary group list unchanged. 
1318 setregid(proc_t p
, struct setregid_args 
*uap
, __unused 
int32_t *retval
) 
1322         kauth_cred_t my_cred
, my_new_cred
; 
1323         posix_cred_t my_pcred
; 
1325         DEBUG_CRED_ENTER("setregid %d %d\n", uap
->rgid
, uap
->egid
); 
1330         if (rgid 
== (uid_t
)-1) 
1331                 rgid 
= KAUTH_GID_NONE
; 
1332         if (egid 
== (uid_t
)-1) 
1333                 egid 
= KAUTH_GID_NONE
; 
1334         AUDIT_ARG(egid
, egid
); 
1335         AUDIT_ARG(rgid
, rgid
); 
1337         /* get current credential and take a reference while we muck with it */ 
1338         my_cred 
= kauth_cred_proc_ref(p
); 
1339         my_pcred 
= posix_cred_get(my_cred
); 
1343                 if (((rgid 
!= KAUTH_UID_NONE 
&&         /* allow no change of rgid */ 
1344                       rgid 
!= my_pcred
->cr_rgid 
&&      /* allow rgid = rgid */ 
1345                       rgid 
!= my_pcred
->cr_gid 
&&       /* allow rgid = egid */ 
1346                       rgid 
!= my_pcred
->cr_svgid
) ||    /* allow rgid = svgid */ 
1347                      (egid 
!= KAUTH_UID_NONE 
&&         /* allow no change of egid */ 
1348                       egid 
!= my_pcred
->cr_groups
[0] && /* allow no change of egid */ 
1349                       egid 
!= my_pcred
->cr_gid 
&&       /* allow egid = egid */ 
1350                       egid 
!= my_pcred
->cr_rgid 
&&      /* allow egid = rgid */ 
1351                       egid 
!= my_pcred
->cr_svgid
)) &&   /* allow egid = svgid */ 
1352                     (error 
= suser(my_cred
, &p
->p_acflag
))) { /* allow root user any */ 
1353                         kauth_cred_unref(&my_cred
); 
1357                 uid_t new_egid 
= my_pcred
->cr_gid
; 
1358                 uid_t new_rgid 
= my_pcred
->cr_rgid
; 
1359                 uid_t svgid 
= KAUTH_UID_NONE
; 
1363                  * Set the credential with new info.  If there is no change, 
1364                  * we get back the same credential we passed in; if there is 
1365                  * a change, we drop the reference on the credential we 
1366                  * passed in.  The subsequent compare is safe, because it is 
1367                  * a pointer compare rather than a contents compare. 
1369                 if (egid 
!= KAUTH_UID_NONE 
&& my_pcred
->cr_gid 
!= egid
) { 
1370                         /* changing the effective GID */ 
1372                         OSBitOrAtomic(P_SUGID
, &p
->p_flag
); 
1374                 if (rgid 
!= KAUTH_UID_NONE 
&& my_pcred
->cr_rgid 
!= rgid
) { 
1375                         /* changing the real GID */ 
1377                         OSBitOrAtomic(P_SUGID
, &p
->p_flag
); 
1380                  * If the newly requested real gid or effective gid does 
1381                  * not match the saved gid, then set the saved gid to the 
1382                  * new effective gid.  We are protected from escalation 
1383                  * by the prechecking. 
1385                 if (my_pcred
->cr_svgid 
!= uap
->rgid 
&& 
1386                     my_pcred
->cr_svgid 
!= uap
->egid
) { 
1388                         OSBitOrAtomic(P_SUGID
, &p
->p_flag
); 
1391                 my_new_cred 
= kauth_cred_setresgid(my_cred
, rgid
, egid
, svgid
); 
1392                 if (my_cred 
!= my_new_cred
) { 
1394                         DEBUG_CRED_CHANGE("setregid(CH)%d: %p/0x%08x->%p/0x%08x\n", p
->p_pid
, my_cred
, my_pcred
->cr_flags
, my_new_cred
, posix_cred_get(my_new_cred
)->cr_flags
); 
1397                         /* need to protect for a race where another thread 
1398                          * also changed the credential after we took our 
1399                          * reference.  If p_ucred has changed then we 
1400                          * should restart this again with the new cred. 
1402                         if (p
->p_ucred 
!= my_cred
) { 
1403                                 proc_ucred_unlock(p
); 
1404                                 kauth_cred_unref(&my_new_cred
); 
1406                                 my_cred 
= kauth_cred_proc_ref(p
); 
1407                                 my_pcred 
= posix_cred_get(my_cred
); 
1410                         p
->p_ucred 
= my_new_cred
; 
1411                         /* update cred on proc */ 
1412                         PROC_UPDATE_CREDS_ONPROC(p
); 
1413                         OSBitOrAtomic(P_SUGID
, &p
->p_flag
); /* XXX redundant? */ 
1414                         proc_ucred_unlock(p
); 
1418         /* Drop old proc reference or our extra reference */ 
1419         kauth_cred_unref(&my_cred
); 
1421         set_security_token(p
); 
1427  * Set the per-thread override identity.  The first parameter can be the 
1428  * current real UID, KAUTH_UID_NONE, or, if the caller is privileged, it 
1429  * can be any UID.  If it is KAUTH_UID_NONE, then as a special case, this 
1430  * means "revert to the per process credential"; otherwise, if permitted, 
1431  * it changes the effective, real, and saved UIDs and GIDs for the current 
1432  * thread to the requested UID and single GID, and clears all other GIDs. 
1435 settid(proc_t p
, struct settid_args 
*uap
, __unused 
int32_t *retval
) 
1438         struct uthread 
*uthread 
= get_bsdthread_info(current_thread()); 
1444         AUDIT_ARG(uid
, uid
); 
1445         AUDIT_ARG(gid
, gid
); 
1447         if (proc_suser(p
) != 0)  
1450         if (uid 
== KAUTH_UID_NONE
) { 
1452                 /* must already be assuming another identity in order to revert back */ 
1453                 if ((uthread
->uu_flag 
& UT_SETUID
) == 0) 
1456                 /* revert to delayed binding of process credential */ 
1457                 uc 
= kauth_cred_proc_ref(p
); 
1458                 kauth_cred_unref(&uthread
->uu_ucred
); 
1459                 uthread
->uu_ucred 
= uc
; 
1460                 uthread
->uu_flag 
&= ~UT_SETUID
; 
1462                 kauth_cred_t my_cred
, my_new_cred
; 
1464                 /* cannot already be assuming another identity */ 
1465                 if ((uthread
->uu_flag 
& UT_SETUID
) != 0) { 
1470                  * Get a new credential instance from the old if this one 
1471                  * changes; otherwise kauth_cred_setuidgid() returns the 
1472                  * same credential.  We take an extra reference on the 
1473                  * current credential while we muck with it, so we can do 
1474                  * the post-compare for changes by pointer. 
1476                 kauth_cred_ref(uthread
->uu_ucred
);  
1477                 my_cred 
= uthread
->uu_ucred
; 
1478                 my_new_cred 
= kauth_cred_setuidgid(my_cred
, uid
, gid
); 
1479                 if (my_cred 
!= my_new_cred
) 
1480                         uthread
->uu_ucred 
= my_new_cred
; 
1481                 uthread
->uu_flag 
|= UT_SETUID
; 
1483                 /* Drop old uthread reference or our extra reference */ 
1484                 kauth_cred_unref(&my_cred
); 
1487          * XXX should potentially set per thread security token (there is 
1489          * XXX it is unclear whether P_SUGID should be st at this point; 
1490          * XXX in theory, it is being deprecated. 
1497  * Set the per-thread override identity.  Use this system call for a thread to 
1498  * assume the identity of another process or to revert back to normal identity 
1499  * of the current process. 
1501  * When the "assume" argument is non zero the current thread will assume the 
1502  * identity of the process represented by the pid argument. 
1504  * When the assume argument is zero we revert back to our normal identity. 
1507 settid_with_pid(proc_t p
, struct settid_with_pid_args 
*uap
, __unused 
int32_t *retval
) 
1510         struct uthread 
*uthread 
= get_bsdthread_info(current_thread()); 
1511         kauth_cred_t my_cred
, my_target_cred
, my_new_cred
; 
1512         posix_cred_t my_target_pcred
; 
1514         AUDIT_ARG(pid
, uap
->pid
); 
1515         AUDIT_ARG(value32
, uap
->assume
); 
1517         if (proc_suser(p
) != 0) { 
1522          * XXX should potentially set per thread security token (there is 
1524          * XXX it is unclear whether P_SUGID should be st at this point; 
1525          * XXX in theory, it is being deprecated. 
1529          * assume argument tells us to assume the identity of the process with the 
1530          * id passed in the pid argument. 
1532         if (uap
->assume 
!= 0) { 
1533                 /* can't do this if we have already assumed an identity */ 
1534                 if ((uthread
->uu_flag 
& UT_SETUID
) != 0) 
1537                 target_proc 
= proc_find(uap
->pid
); 
1538                 /* can't assume the identity of the kernel process */ 
1539                 if (target_proc 
== NULL 
|| target_proc 
== kernproc
) { 
1540                         if (target_proc
!= NULL
) 
1541                                 proc_rele(target_proc
); 
1546                  * Take a reference on the credential used in our target 
1547                  * process then use it as the identity for our current 
1548                  * thread.  We take an extra reference on the current 
1549                  * credential while we muck with it, so we can do the 
1550                  * post-compare for changes by pointer. 
1552                  * The post-compare is needed for the case that our process 
1553                  * credential has been changed to be identical to our thread 
1554                  * credential following our assumption of a per-thread one, 
1555                  * since the credential cache will maintain a unique instance. 
1557                 kauth_cred_ref(uthread
->uu_ucred
);  
1558                 my_cred 
= uthread
->uu_ucred
; 
1559                 my_target_cred 
= kauth_cred_proc_ref(target_proc
); 
1560                 my_target_pcred 
= posix_cred_get(my_target_cred
); 
1561                 my_new_cred 
= kauth_cred_setuidgid(my_cred
, my_target_pcred
->cr_uid
, my_target_pcred
->cr_gid
); 
1562                 if (my_cred 
!= my_new_cred
) 
1563                         uthread
->uu_ucred 
= my_new_cred
; 
1565                 uthread
->uu_flag 
|= UT_SETUID
; 
1567                 /* Drop old uthread reference or our extra reference */ 
1568                 proc_rele(target_proc
); 
1569                 kauth_cred_unref(&my_cred
); 
1570                 kauth_cred_unref(&my_target_cred
); 
1576          * Otherwise, we are reverting back to normal mode of operation where 
1577          * delayed binding of the process credential sets the credential in 
1578          * the thread (uu_ucred) 
1580         if ((uthread
->uu_flag 
& UT_SETUID
) == 0) 
1583         /* revert to delayed binding of process credential */ 
1584         my_new_cred 
= kauth_cred_proc_ref(p
); 
1585         kauth_cred_unref(&uthread
->uu_ucred
); 
1586         uthread
->uu_ucred 
= my_new_cred
; 
1587         uthread
->uu_flag 
&= ~UT_SETUID
; 
1596  * Description: Internal implementation for both the setgroups and initgroups 
1599  * Parameters:  gidsetsize                      Number of groups in set 
1600  *              gidset                          Pointer to group list 
1601  *              gmuid                           Base gid (initgroups only!) 
1603  * Returns:     0                               Success 
1604  *      suser:EPERM                             Permision denied 
1605  *              EINVAL                          Invalid gidsetsize value 
1606  *      copyin:EFAULT                           Bad gidset or gidsetsize is 
1609  * Notes:       When called from a thread running under an assumed per-thread 
1610  *              identity, this function will operate against the per-thread 
1611  *              credential, rather than against the process credential.  In 
1612  *              this specific case, the process credential is verified to 
1613  *              still be privileged at the time of the call, rather than the 
1614  *              per-thread credential for this operation to be permitted. 
1616  *              This effectively means that setgroups/initigroups calls in 
1617  *              a thread running a per-thread credential should occur *after* 
1618  *              the settid call that created it, not before (unlike setuid, 
1619  *              which must be called after, since it will result in privilege 
1622  *              When called normally (i.e. no per-thread assumed identity), 
1623  *              the per process credential is updated per POSIX. 
1625  *              If the credential is changed as a result of this call, then we 
1626  *              flag the process as having set privilege since the last exec. 
1629 setgroups1(proc_t p
, u_int gidsetsize
, user_addr_t gidset
, uid_t gmuid
, __unused 
int32_t *retval
) 
1632         gid_t   newgroups
[NGROUPS
] = { 0 }; 
1634         kauth_cred_t my_cred
, my_new_cred
; 
1635         struct uthread 
*uthread 
= get_bsdthread_info(current_thread()); 
1637         DEBUG_CRED_ENTER("setgroups1 (%d/%d): %d 0x%016x %d\n", p
->p_pid
, (p
->p_pptr 
? p
->p_pptr
->p_pid 
: 0), gidsetsize
, gidset
, gmuid
); 
1646                 error 
= copyin(gidset
, 
1647                         (caddr_t
)newgroups
, ngrp 
* sizeof(gid_t
)); 
1653         my_cred 
= kauth_cred_proc_ref(p
); 
1654         if ((error 
= suser(my_cred
, &p
->p_acflag
))) { 
1655                 kauth_cred_unref(&my_cred
); 
1659         if ((uthread
->uu_flag 
& UT_SETUID
) != 0) { 
1661                 int my_cred_flags 
= uthread
->uu_ucred
->cr_flags
; 
1662 #endif  /* DEBUG_CRED */ 
1663                 kauth_cred_unref(&my_cred
); 
1666                  * If this thread is under an assumed identity, set the 
1667                  * supplementary grouplist on the thread credential instead 
1668                  * of the process one.  If we were the only reference holder, 
1669                  * the credential is updated in place, otherwise, our reference 
1670                  * is dropped and we get back a different cred with a reference 
1671                  * already held on it.  Because this is per-thread, we don't 
1672                  * need the referencing/locking/retry required for per-process. 
1674                 my_cred 
= uthread
->uu_ucred
; 
1675                 uthread
->uu_ucred 
= kauth_cred_setgroups(my_cred
, &newgroups
[0], ngrp
, gmuid
); 
1677                 if (my_cred 
!= uthread
->uu_ucred
) { 
1678                         DEBUG_CRED_CHANGE("setgroups1(CH)%d: %p/0x%08x->%p/0x%08x\n", p
->p_pid
, my_cred
, my_cred_flags
, uthread
->uu_ucred 
, uthread
->uu_ucred 
->cr_flags
); 
1680 #endif  /* DEBUG_CRED */ 
1684                  * get current credential and take a reference while we muck 
1689                          * Set the credential with new info.  If there is no 
1690                          * change, we get back the same credential we passed 
1691                          * in; if there is a change, we drop the reference on 
1692                          * the credential we passed in.  The subsequent 
1693                          * compare is safe, because it is a pointer compare 
1694                          * rather than a contents compare. 
1696                         my_new_cred 
= kauth_cred_setgroups(my_cred
, &newgroups
[0], ngrp
, gmuid
); 
1697                         if (my_cred 
!= my_new_cred
) { 
1699                                 DEBUG_CRED_CHANGE("setgroups1(CH)%d: %p/0x%08x->%p/0x%08x\n", p
->p_pid
, my_cred
, my_cred
->cr_flags
, my_new_cred
, my_new_cred
->cr_flags
); 
1703                                  * We need to protect for a race where another 
1704                                  * thread also changed the credential after we 
1705                                  * took our reference.  If p_ucred has  
1706                                  * changed then we should restart this again 
1707                                  * with the new cred. 
1709                                 if (p
->p_ucred 
!= my_cred
) { 
1710                                         proc_ucred_unlock(p
); 
1711                                         kauth_cred_unref(&my_new_cred
); 
1712                                         my_cred 
= kauth_cred_proc_ref(p
); 
1716                                 p
->p_ucred 
= my_new_cred
; 
1717                                 /* update cred on proc */ 
1718                                 PROC_UPDATE_CREDS_ONPROC(p
); 
1719                                 OSBitOrAtomic(P_SUGID
, &p
->p_flag
); 
1720                                 proc_ucred_unlock(p
); 
1724                 /* Drop old proc reference or our extra reference */ 
1725                 AUDIT_ARG(groupset
, posix_cred_get(my_cred
)->cr_groups
, ngrp
); 
1726                 kauth_cred_unref(&my_cred
); 
1729                 set_security_token(p
); 
1739  * Description: Initialize the default supplementary groups list and set the 
1740  *              gmuid for use by the external group resolver (if any) 
1742  * Parameters:  uap->gidsetsize                 Number of groups in set 
1743  *              uap->gidset                     Pointer to group list 
1744  *              uap->gmuid                      Base gid 
1746  * Returns:     0                               Success 
1747  *      setgroups1:EPERM                        Permision denied 
1748  *      setgroups1:EINVAL                       Invalid gidsetsize value 
1749  *      setgroups1:EFAULT                       Bad gidset or gidsetsize is 
1751  * Notes:       This function opts *IN* to memberd participation 
1753  *              The normal purpose of this function is for a privileged 
1754  *              process to indicate supplementary groups and identity for 
1755  *              participation in extended group membership resolution prior 
1756  *              to dropping privilege by assuming a specific user identity. 
1758  *              It is the first half of the primary mechanism whereby user 
1759  *              identity is established to the system by programs such as 
1760  *              /usr/bin/login.  The second half is the drop of uid privilege 
1761  *              for a specific uid corresponding to the user. 
1763  * See also:    setgroups1() 
1766 initgroups(proc_t p
, struct initgroups_args 
*uap
, __unused 
int32_t *retval
) 
1768         DEBUG_CRED_ENTER("initgroups\n"); 
1770         return(setgroups1(p
, uap
->gidsetsize
, uap
->gidset
, uap
->gmuid
, retval
)); 
1777  * Description: Initialize the default supplementary groups list 
1779  * Parameters:  gidsetsize                      Number of groups in set 
1780  *              gidset                          Pointer to group list 
1782  * Returns:     0                               Success 
1783  *      setgroups1:EPERM                        Permision denied 
1784  *      setgroups1:EINVAL                       Invalid gidsetsize value 
1785  *      setgroups1:EFAULT                       Bad gidset or gidsetsize is 
1787  * Notes:       This functions opts *OUT* of memberd participation. 
1789  *              This function exists for compatibility with POSIX.  Most user 
1790  *              programs should use initgroups() instead to ensure correct 
1791  *              participation in group membership resolution when utilizing 
1792  *              a directory service for authentication. 
1794  *              It is identical to an initgroups() call with a gmuid argument 
1795  *              of KAUTH_UID_NONE. 
1797  * See also:    setgroups1() 
1800 setgroups(proc_t p
, struct setgroups_args 
*uap
, __unused 
int32_t *retval
) 
1802         DEBUG_CRED_ENTER("setgroups\n"); 
1804         return(setgroups1(p
, uap
->gidsetsize
, uap
->gidset
, KAUTH_UID_NONE
, retval
)); 
1809  * Set the per-thread/per-process supplementary groups list. 
1811  * XXX implement setsgroups 
1816 setsgroups(__unused proc_t p
, __unused 
struct setsgroups_args 
*uap
, __unused 
int32_t *retval
) 
1822  * Set the per-thread/per-process whiteout groups list. 
1824  * XXX implement setwgroups 
1829 setwgroups(__unused proc_t p
, __unused 
struct setwgroups_args 
*uap
, __unused 
int32_t *retval
) 
1836  * Check if gid is a member of the group set. 
1838  * XXX This interface is going away; use kauth_cred_ismember_gid() directly 
1842 groupmember(gid_t gid
, kauth_cred_t cred
) 
1846         if (kauth_cred_ismember_gid(cred
, gid
, &is_member
) == 0 && is_member
) 
1853  * Test whether the specified credentials imply "super-user" 
1854  * privilege; if so, and we have accounting info, set the flag 
1855  * indicating use of super-powers. 
1856  * Returns 0 or error. 
1858  * XXX This interface is going away; use kauth_cred_issuser() directly 
1861  * Note:        This interface exists to implement the "has used privilege" 
1862  *              bit (ASU) in the p_acflags field of the process, which is 
1863  *              only externalized via private sysctl and in process accounting 
1864  *              records.  The flag is technically not required in either case. 
1867 suser(kauth_cred_t cred
, u_short 
*acflag
) 
1870         if (!IS_VALID_CRED(cred
)) 
1873         if (kauth_cred_getuid(cred
) == 0) { 
1885  * Description: Get login name, if available. 
1887  * Parameters:  uap->namebuf                    User buffer for return 
1888  *              uap->namelen                    User buffer length 
1890  * Returns:     0                               Success 
1893  * Notes:       Intended to obtain a string containing the user name of the 
1894  *              user associated with the controlling terminal for the calling 
1897  *              Not very useful on modern systems, due to inherent length 
1898  *              limitations for the static array in the session structure 
1899  *              which is used to store the login name. 
1901  *              Permitted to return NULL 
1903  * XXX:         Belongs in kern_proc.c 
1906 getlogin(proc_t p
, struct getlogin_args 
*uap
, __unused 
int32_t *retval
) 
1908         char buffer
[MAXLOGNAME
+1]; 
1909         struct session 
* sessp
; 
1911         bzero(buffer
, MAXLOGNAME
+1); 
1913         sessp 
= proc_session(p
); 
1915         if (uap
->namelen 
> MAXLOGNAME
) 
1916                 uap
->namelen 
= MAXLOGNAME
; 
1918         if(sessp 
!= SESSION_NULL
) { 
1919                 session_lock(sessp
); 
1920                 bcopy( sessp
->s_login
, buffer
, uap
->namelen
); 
1921                 session_unlock(sessp
); 
1923         session_rele(sessp
); 
1925         return (copyout((caddr_t
)buffer
, uap
->namebuf
, uap
->namelen
)); 
1932  * Description: Set login name. 
1934  * Parameters:  uap->namebuf                    User buffer containing name 
1936  * Returns:     0                               Success 
1937  *      suser:EPERM                             Permission denied 
1938  *      copyinstr:EFAULT                        User buffer invalid 
1939  *      copyinstr:EINVAL                        Supplied name was too long 
1941  * Notes:       This is a utility system call to support getlogin(). 
1943  * XXX:         Belongs in kern_proc.c 
1946 setlogin(proc_t p
, struct setlogin_args 
*uap
, __unused 
int32_t *retval
) 
1950         char buffer
[MAXLOGNAME
+1]; 
1951         struct session 
* sessp
; 
1953         if ((error 
= proc_suser(p
))) 
1956         bzero(&buffer
[0], MAXLOGNAME
+1); 
1959         error 
= copyinstr(uap
->namebuf
, 
1960             (caddr_t
) &buffer
[0], 
1961             MAXLOGNAME 
- 1, (size_t *)&dummy
); 
1963         sessp 
= proc_session(p
); 
1965         if (sessp 
!= SESSION_NULL
) { 
1966                 session_lock(sessp
); 
1967                 bcopy(buffer
, sessp
->s_login
, MAXLOGNAME
); 
1968                 session_unlock(sessp
); 
1969                 session_rele(sessp
); 
1974                 AUDIT_ARG(text
, buffer
); 
1975          } else if (error 
== ENAMETOOLONG
) 
1981 /* Set the secrity token of the task with current euid and eguid */ 
1983  * XXX This needs to change to give the task a reference and/or an opaque 
1987 set_security_token(proc_t p
) 
1989         security_token_t sec_token
; 
1990         audit_token_t    audit_token
; 
1991         kauth_cred_t my_cred
; 
1992         posix_cred_t my_pcred
; 
1993         host_priv_t host_priv
; 
1996          * Don't allow a vfork child to override the parent's token settings 
1997          * (since they share a task).  Instead, the child will just have to 
1998          * suffer along using the parent's token until the exec().  It's all 
1999          * undefined behavior anyway, right? 
2001         if (p
->task 
== current_task()) { 
2003                 uthread 
= (uthread_t
)get_bsdthread_info(current_thread()); 
2004                 if (uthread
->uu_flag 
& UT_VFORK
) 
2008         my_cred 
= kauth_cred_proc_ref(p
); 
2009         my_pcred 
= posix_cred_get(my_cred
); 
2011         /* XXX mach_init doesn't have a p_ucred when it calls this function */ 
2012         if (IS_VALID_CRED(my_cred
)) { 
2013                 sec_token
.val
[0] = kauth_cred_getuid(my_cred
); 
2014                 sec_token
.val
[1] = kauth_cred_getgid(my_cred
); 
2016                 sec_token
.val
[0] = 0; 
2017                 sec_token
.val
[1] = 0; 
2021          * The current layout of the Mach audit token explicitly 
2022          * adds these fields.  But nobody should rely on such 
2023          * a literal representation.  Instead, the BSM library 
2024          * provides a function to convert an audit token into 
2025          * a BSM subject.  Use of that mechanism will isolate 
2026          * the user of the trailer from future representation 
2029         audit_token
.val
[0] = my_cred
->cr_audit
.as_aia_p
->ai_auid
; 
2030         audit_token
.val
[1] = my_pcred
->cr_uid
; 
2031         audit_token
.val
[2] = my_pcred
->cr_gid
; 
2032         audit_token
.val
[3] = my_pcred
->cr_ruid
; 
2033         audit_token
.val
[4] = my_pcred
->cr_rgid
; 
2034         audit_token
.val
[5] = p
->p_pid
; 
2035         audit_token
.val
[6] = my_cred
->cr_audit
.as_aia_p
->ai_asid
; 
2036         audit_token
.val
[7] = p
->p_idversion
; 
2038         host_priv 
= (sec_token
.val
[0]) ? HOST_PRIV_NULL 
: host_priv_self(); 
2040         if (host_priv 
!= HOST_PRIV_NULL 
&& mac_system_check_host_priv(my_cred
)) 
2041                 host_priv 
= HOST_PRIV_NULL
; 
2043         kauth_cred_unref(&my_cred
); 
2045 #if DEVELOPMENT || DEBUG 
2047          * Update the pid an proc name for importance base if any 
2049         task_importance_update_owner_info(p
->task
); 
2052         return (host_security_set_task_token(host_security_self(), 
2056                                            host_priv
) != KERN_SUCCESS
); 
2060 int get_audit_token_pid(audit_token_t 
*audit_token
); 
2063 get_audit_token_pid(audit_token_t 
*audit_token
) 
2065         /* keep in-sync with set_security_token (above) */ 
2067                 return (int)audit_token
->val
[5]; 
2073  * Fill in a struct xucred based on a kauth_cred_t. 
2077 cru2x(kauth_cred_t cr
, struct xucred 
*xcr
) 
2079         posix_cred_t pcr 
= posix_cred_get(cr
); 
2081         bzero(xcr
, sizeof(*xcr
)); 
2082         xcr
->cr_version 
= XUCRED_VERSION
; 
2083         xcr
->cr_uid 
= kauth_cred_getuid(cr
); 
2084         xcr
->cr_ngroups 
= pcr
->cr_ngroups
; 
2085         bcopy(pcr
->cr_groups
, xcr
->cr_groups
, sizeof(xcr
->cr_groups
));