The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/kern/kern_prot.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Copyright (c) 1982, 1986, 1989, 1990, 1991, 1993
    3  *      The Regents of the University of California.  All rights reserved.
    4  * (c) UNIX System Laboratories, Inc.
    5  * All or some portions of this file are derived from material licensed
    6  * to the University of California by American Telephone and Telegraph
    7  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
    8  * the permission of UNIX System Laboratories, Inc.
    9  * Copyright (c) 2000-2001 Robert N. M. Watson.  All rights reserved.
   10  *
   11  * Redistribution and use in source and binary forms, with or without
   12  * modification, are permitted provided that the following conditions
   13  * are met:
   14  * 1. Redistributions of source code must retain the above copyright
   15  *    notice, this list of conditions and the following disclaimer.
   16  * 2. Redistributions in binary form must reproduce the above copyright
   17  *    notice, this list of conditions and the following disclaimer in the
   18  *    documentation and/or other materials provided with the distribution.
   19  * 3. All advertising materials mentioning features or use of this software
   20  *    must display the following acknowledgement:
   21  *      This product includes software developed by the University of
   22  *      California, Berkeley and its contributors.
   23  * 4. Neither the name of the University nor the names of its contributors
   24  *    may be used to endorse or promote products derived from this software
   25  *    without specific prior written permission.
   26  *
   27  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   28  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   29  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   30  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   31  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   32  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   33  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   34  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   35  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   36  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   37  * SUCH DAMAGE.
   38  *
   39  *      @(#)kern_prot.c 8.6 (Berkeley) 1/21/94
   40  * $FreeBSD: releng/5.0/sys/kern/kern_prot.c 101173 2002-08-01 17:47:56Z rwatson $
   41  */
   42 
   43 /*
   44  * System calls related to processes and protection
   45  */
   46 
   47 #include "opt_compat.h"
   48 #include "opt_mac.h"
   49 
   50 #include <sys/param.h>
   51 #include <sys/systm.h>
   52 #include <sys/acct.h>
   53 #include <sys/kernel.h>
   54 #include <sys/lock.h>
   55 #include <sys/mac.h>
   56 #include <sys/malloc.h>
   57 #include <sys/mutex.h>
   58 #include <sys/sx.h>
   59 #include <sys/proc.h>
   60 #include <sys/sysproto.h>
   61 #include <sys/jail.h>
   62 #include <sys/pioctl.h>
   63 #include <sys/resourcevar.h>
   64 #include <sys/socket.h>
   65 #include <sys/socketvar.h>
   66 #include <sys/sysctl.h>
   67 
   68 static MALLOC_DEFINE(M_CRED, "cred", "credentials");
   69 
   70 SYSCTL_DECL(_security);
   71 SYSCTL_NODE(_security, OID_AUTO, bsd, CTLFLAG_RW, 0,
   72     "BSD security policy");
   73 
   74 #ifndef _SYS_SYSPROTO_H_
   75 struct getpid_args {
   76         int     dummy;
   77 };
   78 #endif
   79 /*
   80  * MPSAFE
   81  */
   82 /* ARGSUSED */
   83 int
   84 getpid(struct thread *td, struct getpid_args *uap)
   85 {
   86         struct proc *p = td->td_proc;
   87         int s;
   88 
   89         s = mtx_lock_giant(kern_giant_proc);
   90         td->td_retval[0] = p->p_pid;
   91 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
   92         PROC_LOCK(p);
   93         td->td_retval[1] = p->p_pptr->p_pid;
   94         PROC_UNLOCK(p);
   95 #endif
   96         mtx_unlock_giant(s);
   97         return (0);
   98 }
   99 
  100 #ifndef _SYS_SYSPROTO_H_
  101 struct getppid_args {
  102         int     dummy;
  103 };
  104 #endif
  105 /*
  106  * MPSAFE
  107  */
  108 /* ARGSUSED */
  109 int
  110 getppid(struct thread *td, struct getppid_args *uap)
  111 {
  112         struct proc *p = td->td_proc;
  113         int s;
  114 
  115         s = mtx_lock_giant(kern_giant_proc);
  116         PROC_LOCK(p);
  117         td->td_retval[0] = p->p_pptr->p_pid;
  118         PROC_UNLOCK(p);
  119         mtx_unlock_giant(s);
  120         return (0);
  121 }
  122 
  123 /*
  124  * Get process group ID; note that POSIX getpgrp takes no parameter.
  125  */
  126 #ifndef _SYS_SYSPROTO_H_
  127 struct getpgrp_args {
  128         int     dummy;
  129 };
  130 #endif
  131 /*
  132  * MPSAFE
  133  */
  134 int
  135 getpgrp(struct thread *td, struct getpgrp_args *uap)
  136 {
  137         struct proc *p = td->td_proc;
  138         int s;
  139 
  140         s = mtx_lock_giant(kern_giant_proc);
  141         PROC_LOCK(p);
  142         td->td_retval[0] = p->p_pgrp->pg_id;
  143         PROC_UNLOCK(p);
  144         mtx_unlock_giant(s);
  145         return (0);
  146 }
  147 
  148 /* Get an arbitary pid's process group id */
  149 #ifndef _SYS_SYSPROTO_H_
  150 struct getpgid_args {
  151         pid_t   pid;
  152 };
  153 #endif
  154 /*
  155  * MPSAFE
  156  */
  157 int
  158 getpgid(struct thread *td, struct getpgid_args *uap)
  159 {
  160         struct proc *p = td->td_proc;
  161         struct proc *pt;
  162         int error;
  163 
  164         mtx_lock(&Giant);
  165         error = 0;
  166         if (uap->pid == 0) {
  167                 PROC_LOCK(p);
  168                 td->td_retval[0] = p->p_pgrp->pg_id;
  169                 PROC_UNLOCK(p);
  170         } else if ((pt = pfind(uap->pid)) == NULL)
  171                 error = ESRCH;
  172         else {
  173                 error = p_cansee(td, pt);
  174                 if (error == 0)
  175                         td->td_retval[0] = pt->p_pgrp->pg_id;
  176                 PROC_UNLOCK(pt);
  177         }
  178         mtx_unlock(&Giant);
  179         return (error);
  180 }
  181 
  182 /*
  183  * Get an arbitary pid's session id.
  184  */
  185 #ifndef _SYS_SYSPROTO_H_
  186 struct getsid_args {
  187         pid_t   pid;
  188 };
  189 #endif
  190 /*
  191  * MPSAFE
  192  */
  193 int
  194 getsid(struct thread *td, struct getsid_args *uap)
  195 {
  196         struct proc *p = td->td_proc;
  197         struct proc *pt;
  198         int error;
  199 
  200         mtx_lock(&Giant);
  201         error = 0;
  202         if (uap->pid == 0) {
  203                 PROC_LOCK(p);
  204                 td->td_retval[0] = p->p_session->s_sid;
  205                 PROC_UNLOCK(p);
  206         } else if ((pt = pfind(uap->pid)) == NULL)
  207                 error = ESRCH;
  208         else {
  209                 error = p_cansee(td, pt);
  210                 if (error == 0)
  211                         td->td_retval[0] = pt->p_session->s_sid;
  212                 PROC_UNLOCK(pt);
  213         }
  214         mtx_unlock(&Giant);
  215         return (error);
  216 }
  217 
  218 #ifndef _SYS_SYSPROTO_H_
  219 struct getuid_args {
  220         int     dummy;
  221 };
  222 #endif
  223 /*
  224  * MPSAFE
  225  */
  226 /* ARGSUSED */
  227 int
  228 getuid(struct thread *td, struct getuid_args *uap)
  229 {
  230 
  231         td->td_retval[0] = td->td_ucred->cr_ruid;
  232 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
  233         td->td_retval[1] = td->td_ucred->cr_uid;
  234 #endif
  235         return (0);
  236 }
  237 
  238 #ifndef _SYS_SYSPROTO_H_
  239 struct geteuid_args {
  240         int     dummy;
  241 };
  242 #endif
  243 /*
  244  * MPSAFE
  245  */
  246 /* ARGSUSED */
  247 int
  248 geteuid(struct thread *td, struct geteuid_args *uap)
  249 {
  250 
  251         td->td_retval[0] = td->td_ucred->cr_uid;
  252         return (0);
  253 }
  254 
  255 #ifndef _SYS_SYSPROTO_H_
  256 struct getgid_args {
  257         int     dummy;
  258 };
  259 #endif
  260 /*
  261  * MPSAFE
  262  */
  263 /* ARGSUSED */
  264 int
  265 getgid(struct thread *td, struct getgid_args *uap)
  266 {
  267 
  268         td->td_retval[0] = td->td_ucred->cr_rgid;
  269 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
  270         td->td_retval[1] = td->td_ucred->cr_groups[0];
  271 #endif
  272         return (0);
  273 }
  274 
  275 /*
  276  * Get effective group ID.  The "egid" is groups[0], and could be obtained
  277  * via getgroups.  This syscall exists because it is somewhat painful to do
  278  * correctly in a library function.
  279  */
  280 #ifndef _SYS_SYSPROTO_H_
  281 struct getegid_args {
  282         int     dummy;
  283 };
  284 #endif
  285 /*
  286  * MPSAFE
  287  */
  288 /* ARGSUSED */
  289 int
  290 getegid(struct thread *td, struct getegid_args *uap)
  291 {
  292 
  293         td->td_retval[0] = td->td_ucred->cr_groups[0];
  294         return (0);
  295 }
  296 
  297 #ifndef _SYS_SYSPROTO_H_
  298 struct getgroups_args {
  299         u_int   gidsetsize;
  300         gid_t   *gidset;
  301 };
  302 #endif
  303 /*
  304  * MPSAFE
  305  */
  306 int
  307 getgroups(struct thread *td, register struct getgroups_args *uap)
  308 {
  309         struct ucred *cred;
  310         u_int ngrp;
  311         int error;
  312 
  313         cred = td->td_ucred;
  314         if ((ngrp = uap->gidsetsize) == 0) {
  315                 td->td_retval[0] = cred->cr_ngroups;
  316                 return (0);
  317         }
  318         if (ngrp < cred->cr_ngroups)
  319                 return (EINVAL);
  320         ngrp = cred->cr_ngroups;
  321         error = copyout(cred->cr_groups, uap->gidset, ngrp * sizeof(gid_t));
  322         if (error == 0)
  323                 td->td_retval[0] = ngrp;
  324         return (error);
  325 }
  326 
  327 #ifndef _SYS_SYSPROTO_H_
  328 struct setsid_args {
  329         int     dummy;
  330 };
  331 #endif
  332 /*
  333  * MPSAFE
  334  */
  335 /* ARGSUSED */
  336 int
  337 setsid(register struct thread *td, struct setsid_args *uap)
  338 {
  339         struct pgrp *pgrp;
  340         int error;
  341         struct proc *p = td->td_proc;
  342         struct pgrp *newpgrp;
  343         struct session *newsess;
  344 
  345         error = 0;
  346         pgrp = NULL;
  347 
  348         MALLOC(newpgrp, struct pgrp *, sizeof(struct pgrp), M_PGRP, M_WAITOK | M_ZERO);
  349         MALLOC(newsess, struct session *, sizeof(struct session), M_SESSION, M_WAITOK | M_ZERO);
  350 
  351         sx_xlock(&proctree_lock);
  352 
  353         if (p->p_pgid == p->p_pid || (pgrp = pgfind(p->p_pid)) != NULL) {
  354                 if (pgrp != NULL)
  355                         PGRP_UNLOCK(pgrp);
  356                 error = EPERM;
  357         } else {
  358                 (void)enterpgrp(p, p->p_pid, newpgrp, newsess);
  359                 td->td_retval[0] = p->p_pid;
  360                 newpgrp = NULL;
  361                 newsess = NULL;
  362         }
  363 
  364         sx_xunlock(&proctree_lock);
  365 
  366         if (newpgrp != NULL)
  367                 FREE(newpgrp, M_PGRP);
  368         if (newsess != NULL)
  369                 FREE(newsess, M_SESSION);
  370 
  371         return (error);
  372 }
  373 
  374 /*
  375  * set process group (setpgid/old setpgrp)
  376  *
  377  * caller does setpgid(targpid, targpgid)
  378  *
  379  * pid must be caller or child of caller (ESRCH)
  380  * if a child
  381  *      pid must be in same session (EPERM)
  382  *      pid can't have done an exec (EACCES)
  383  * if pgid != pid
  384  *      there must exist some pid in same session having pgid (EPERM)
  385  * pid must not be session leader (EPERM)
  386  */
  387 #ifndef _SYS_SYSPROTO_H_
  388 struct setpgid_args {
  389         int     pid;            /* target process id */
  390         int     pgid;           /* target pgrp id */
  391 };
  392 #endif
  393 /*
  394  * MPSAFE
  395  */
  396 /* ARGSUSED */
  397 int
  398 setpgid(struct thread *td, register struct setpgid_args *uap)
  399 {
  400         struct proc *curp = td->td_proc;
  401         register struct proc *targp;    /* target process */
  402         register struct pgrp *pgrp;     /* target pgrp */
  403         int error;
  404         struct pgrp *newpgrp;
  405 
  406         if (uap->pgid < 0)
  407                 return (EINVAL);
  408 
  409         error = 0;
  410 
  411         MALLOC(newpgrp, struct pgrp *, sizeof(struct pgrp), M_PGRP, M_WAITOK | M_ZERO);
  412 
  413         sx_xlock(&proctree_lock);
  414         if (uap->pid != 0 && uap->pid != curp->p_pid) {
  415                 if ((targp = pfind(uap->pid)) == NULL) {
  416                         if (targp)
  417                                 PROC_UNLOCK(targp);
  418                         error = ESRCH;
  419                         goto done;
  420                 }
  421                 if (!inferior(targp)) {
  422                         PROC_UNLOCK(targp);
  423                         error = ESRCH;
  424                         goto done;
  425                 }
  426                 if ((error = p_cansee(curthread, targp))) {
  427                         PROC_UNLOCK(targp);
  428                         goto done;
  429                 }
  430                 if (targp->p_pgrp == NULL ||
  431                     targp->p_session != curp->p_session) {
  432                         PROC_UNLOCK(targp);
  433                         error = EPERM;
  434                         goto done;
  435                 }
  436                 if (targp->p_flag & P_EXEC) {
  437                         PROC_UNLOCK(targp);
  438                         error = EACCES;
  439                         goto done;
  440                 }
  441                 PROC_UNLOCK(targp);
  442         } else
  443                 targp = curp;
  444         if (SESS_LEADER(targp)) {
  445                 error = EPERM;
  446                 goto done;
  447         }
  448         if (uap->pgid == 0)
  449                 uap->pgid = targp->p_pid;
  450         if (uap->pgid == targp->p_pid) {
  451                 if (targp->p_pgid == uap->pgid)
  452                         goto done;
  453                 error = enterpgrp(targp, uap->pgid, newpgrp, NULL);
  454                 if (error == 0)
  455                         newpgrp = NULL;
  456         } else {
  457                 if ((pgrp = pgfind(uap->pgid)) == NULL ||
  458                     pgrp->pg_session != curp->p_session) {
  459                         if (pgrp != NULL)
  460                                 PGRP_UNLOCK(pgrp);
  461                         error = EPERM;
  462                         goto done;
  463                 }
  464                 if (pgrp == targp->p_pgrp) {
  465                         PGRP_UNLOCK(pgrp);
  466                         goto done;
  467                 }
  468                 PGRP_UNLOCK(pgrp);
  469                 error = enterthispgrp(targp, pgrp);
  470         }
  471 done:
  472         sx_xunlock(&proctree_lock);
  473         KASSERT((error == 0) || (newpgrp != NULL),
  474             ("setpgid failed and newpgrp is NULL"));
  475         if (newpgrp != NULL)
  476                 FREE(newpgrp, M_PGRP);
  477         return (error);
  478 }
  479 
  480 /*
  481  * Use the clause in B.4.2.2 that allows setuid/setgid to be 4.2/4.3BSD
  482  * compatible.  It says that setting the uid/gid to euid/egid is a special
  483  * case of "appropriate privilege".  Once the rules are expanded out, this
  484  * basically means that setuid(nnn) sets all three id's, in all permitted
  485  * cases unless _POSIX_SAVED_IDS is enabled.  In that case, setuid(getuid())
  486  * does not set the saved id - this is dangerous for traditional BSD
  487  * programs.  For this reason, we *really* do not want to set
  488  * _POSIX_SAVED_IDS and do not want to clear POSIX_APPENDIX_B_4_2_2.
  489  */
  490 #define POSIX_APPENDIX_B_4_2_2
  491 
  492 #ifndef _SYS_SYSPROTO_H_
  493 struct setuid_args {
  494         uid_t   uid;
  495 };
  496 #endif
  497 /*
  498  * MPSAFE
  499  */
  500 /* ARGSUSED */
  501 int
  502 setuid(struct thread *td, struct setuid_args *uap)
  503 {
  504         struct proc *p = td->td_proc;
  505         struct ucred *newcred, *oldcred;
  506         uid_t uid;
  507         struct uidinfo *uip;
  508         int error;
  509 
  510         mtx_lock(&Giant);
  511         uid = uap->uid;
  512         newcred = crget();
  513         uip = uifind(uid);
  514         PROC_LOCK(p);
  515         oldcred = p->p_ucred;
  516 
  517         /*
  518          * See if we have "permission" by POSIX 1003.1 rules.
  519          *
  520          * Note that setuid(geteuid()) is a special case of
  521          * "appropriate privileges" in appendix B.4.2.2.  We need
  522          * to use this clause to be compatible with traditional BSD
  523          * semantics.  Basically, it means that "setuid(xx)" sets all
  524          * three id's (assuming you have privs).
  525          *
  526          * Notes on the logic.  We do things in three steps.
  527          * 1: We determine if the euid is going to change, and do EPERM
  528          *    right away.  We unconditionally change the euid later if this
  529          *    test is satisfied, simplifying that part of the logic.
  530          * 2: We determine if the real and/or saved uids are going to
  531          *    change.  Determined by compile options.
  532          * 3: Change euid last. (after tests in #2 for "appropriate privs")
  533          */
  534         if (uid != oldcred->cr_ruid &&          /* allow setuid(getuid()) */
  535 #ifdef _POSIX_SAVED_IDS
  536             uid != oldcred->cr_svuid &&         /* allow setuid(saved gid) */
  537 #endif
  538 #ifdef POSIX_APPENDIX_B_4_2_2   /* Use BSD-compat clause from B.4.2.2 */
  539             uid != oldcred->cr_uid &&           /* allow setuid(geteuid()) */
  540 #endif
  541             (error = suser_cred(oldcred, PRISON_ROOT)) != 0) {
  542                 PROC_UNLOCK(p);
  543                 uifree(uip);
  544                 crfree(newcred);
  545                 mtx_unlock(&Giant);
  546                 return (error);
  547         }
  548 
  549         /*
  550          * Copy credentials so other references do not see our changes.
  551          */
  552         crcopy(newcred, oldcred);
  553 #ifdef _POSIX_SAVED_IDS
  554         /*
  555          * Do we have "appropriate privileges" (are we root or uid == euid)
  556          * If so, we are changing the real uid and/or saved uid.
  557          */
  558         if (
  559 #ifdef POSIX_APPENDIX_B_4_2_2   /* Use the clause from B.4.2.2 */
  560             uid == oldcred->cr_uid ||
  561 #endif
  562             suser_cred(oldcred, PRISON_ROOT) == 0) /* we are using privs */
  563 #endif
  564         {
  565                 /*
  566                  * Set the real uid and transfer proc count to new user.
  567                  */
  568                 if (uid != oldcred->cr_ruid) {
  569                         change_ruid(newcred, uip);
  570                         setsugid(p);
  571                 }
  572                 /*
  573                  * Set saved uid
  574                  *
  575                  * XXX always set saved uid even if not _POSIX_SAVED_IDS, as
  576                  * the security of seteuid() depends on it.  B.4.2.2 says it
  577                  * is important that we should do this.
  578                  */
  579                 if (uid != oldcred->cr_svuid) {
  580                         change_svuid(newcred, uid);
  581                         setsugid(p);
  582                 }
  583         }
  584 
  585         /*
  586          * In all permitted cases, we are changing the euid.
  587          */
  588         if (uid != oldcred->cr_uid) {
  589                 change_euid(newcred, uip);
  590                 setsugid(p);
  591         }
  592         p->p_ucred = newcred;
  593         PROC_UNLOCK(p);
  594         uifree(uip);
  595         crfree(oldcred);
  596         mtx_unlock(&Giant);
  597         return (0);
  598 }
  599 
  600 #ifndef _SYS_SYSPROTO_H_
  601 struct seteuid_args {
  602         uid_t   euid;
  603 };
  604 #endif
  605 /*
  606  * MPSAFE
  607  */
  608 /* ARGSUSED */
  609 int
  610 seteuid(struct thread *td, struct seteuid_args *uap)
  611 {
  612         struct proc *p = td->td_proc;
  613         struct ucred *newcred, *oldcred;
  614         uid_t euid;
  615         struct uidinfo *euip;
  616         int error;
  617 
  618         euid = uap->euid;
  619         mtx_lock(&Giant);
  620         newcred = crget();
  621         euip = uifind(euid);
  622         PROC_LOCK(p);
  623         oldcred = p->p_ucred;
  624         if (euid != oldcred->cr_ruid &&         /* allow seteuid(getuid()) */
  625             euid != oldcred->cr_svuid &&        /* allow seteuid(saved uid) */
  626             (error = suser_cred(oldcred, PRISON_ROOT)) != 0) {
  627                 PROC_UNLOCK(p);
  628                 uifree(euip);
  629                 crfree(newcred);
  630                 mtx_unlock(&Giant);
  631                 return (error);
  632         }
  633         /*
  634          * Everything's okay, do it.  Copy credentials so other references do
  635          * not see our changes.
  636          */
  637         crcopy(newcred, oldcred);
  638         if (oldcred->cr_uid != euid) {
  639                 change_euid(newcred, euip);
  640                 setsugid(p);
  641         }
  642         p->p_ucred = newcred;
  643         PROC_UNLOCK(p);
  644         uifree(euip);
  645         crfree(oldcred);
  646         mtx_unlock(&Giant);
  647         return (0);
  648 }
  649 
  650 #ifndef _SYS_SYSPROTO_H_
  651 struct setgid_args {
  652         gid_t   gid;
  653 };
  654 #endif
  655 /*
  656  * MPSAFE
  657  */
  658 /* ARGSUSED */
  659 int
  660 setgid(struct thread *td, struct setgid_args *uap)
  661 {
  662         struct proc *p = td->td_proc;
  663         struct ucred *newcred, *oldcred;
  664         gid_t gid;
  665         int error;
  666 
  667         gid = uap->gid;
  668         mtx_lock(&Giant);
  669         newcred = crget();
  670         PROC_LOCK(p);
  671         oldcred = p->p_ucred;
  672 
  673         /*
  674          * See if we have "permission" by POSIX 1003.1 rules.
  675          *
  676          * Note that setgid(getegid()) is a special case of
  677          * "appropriate privileges" in appendix B.4.2.2.  We need
  678          * to use this clause to be compatible with traditional BSD
  679          * semantics.  Basically, it means that "setgid(xx)" sets all
  680          * three id's (assuming you have privs).
  681          *
  682          * For notes on the logic here, see setuid() above.
  683          */
  684         if (gid != oldcred->cr_rgid &&          /* allow setgid(getgid()) */
  685 #ifdef _POSIX_SAVED_IDS
  686             gid != oldcred->cr_svgid &&         /* allow setgid(saved gid) */
  687 #endif
  688 #ifdef POSIX_APPENDIX_B_4_2_2   /* Use BSD-compat clause from B.4.2.2 */
  689             gid != oldcred->cr_groups[0] && /* allow setgid(getegid()) */
  690 #endif
  691             (error = suser_cred(oldcred, PRISON_ROOT)) != 0) {
  692                 PROC_UNLOCK(p);
  693                 crfree(newcred);
  694                 mtx_unlock(&Giant);
  695                 return (error);
  696         }
  697 
  698         crcopy(newcred, oldcred);
  699 #ifdef _POSIX_SAVED_IDS
  700         /*
  701          * Do we have "appropriate privileges" (are we root or gid == egid)
  702          * If so, we are changing the real uid and saved gid.
  703          */
  704         if (
  705 #ifdef POSIX_APPENDIX_B_4_2_2   /* use the clause from B.4.2.2 */
  706             gid == oldcred->cr_groups[0] ||
  707 #endif
  708             suser_cred(oldcred, PRISON_ROOT) == 0) /* we are using privs */
  709 #endif
  710         {
  711                 /*
  712                  * Set real gid
  713                  */
  714                 if (oldcred->cr_rgid != gid) {
  715                         change_rgid(newcred, gid);
  716                         setsugid(p);
  717                 }
  718                 /*
  719                  * Set saved gid
  720                  *
  721                  * XXX always set saved gid even if not _POSIX_SAVED_IDS, as
  722                  * the security of setegid() depends on it.  B.4.2.2 says it
  723                  * is important that we should do this.
  724                  */
  725                 if (oldcred->cr_svgid != gid) {
  726                         change_svgid(newcred, gid);
  727                         setsugid(p);
  728                 }
  729         }
  730         /*
  731          * In all cases permitted cases, we are changing the egid.
  732          * Copy credentials so other references do not see our changes.
  733          */
  734         if (oldcred->cr_groups[0] != gid) {
  735                 change_egid(newcred, gid);
  736                 setsugid(p);
  737         }
  738         p->p_ucred = newcred;
  739         PROC_UNLOCK(p);
  740         crfree(oldcred);
  741         mtx_unlock(&Giant);
  742         return (0);
  743 }
  744 
  745 #ifndef _SYS_SYSPROTO_H_
  746 struct setegid_args {
  747         gid_t   egid;
  748 };
  749 #endif
  750 /*
  751  * MPSAFE
  752  */
  753 /* ARGSUSED */
  754 int
  755 setegid(struct thread *td, struct setegid_args *uap)
  756 {
  757         struct proc *p = td->td_proc;
  758         struct ucred *newcred, *oldcred;
  759         gid_t egid;
  760         int error;
  761 
  762         egid = uap->egid;
  763         mtx_lock(&Giant);
  764         newcred = crget();
  765         PROC_LOCK(p);
  766         oldcred = p->p_ucred;
  767         if (egid != oldcred->cr_rgid &&         /* allow setegid(getgid()) */
  768             egid != oldcred->cr_svgid &&        /* allow setegid(saved gid) */
  769             (error = suser_cred(oldcred, PRISON_ROOT)) != 0) {
  770                 PROC_UNLOCK(p);
  771                 crfree(newcred);
  772                 mtx_unlock(&Giant);
  773                 return (error);
  774         }
  775         crcopy(newcred, oldcred);
  776         if (oldcred->cr_groups[0] != egid) {
  777                 change_egid(newcred, egid);
  778                 setsugid(p);
  779         }
  780         p->p_ucred = newcred;
  781         PROC_UNLOCK(p);
  782         crfree(oldcred);
  783         mtx_unlock(&Giant);
  784         return (0);
  785 }
  786 
  787 #ifndef _SYS_SYSPROTO_H_
  788 struct setgroups_args {
  789         u_int   gidsetsize;
  790         gid_t   *gidset;
  791 };
  792 #endif
  793 /*
  794  * MPSAFE
  795  */
  796 /* ARGSUSED */
  797 int
  798 setgroups(struct thread *td, struct setgroups_args *uap)
  799 {
  800         struct proc *p = td->td_proc;
  801         struct ucred *newcred, *tempcred, *oldcred;
  802         u_int ngrp;
  803         int error;
  804 
  805         ngrp = uap->gidsetsize;
  806         if (ngrp > NGROUPS)
  807                 return (EINVAL);
  808         mtx_lock(&Giant);
  809         tempcred = crget();
  810         error = copyin(uap->gidset, tempcred->cr_groups, ngrp * sizeof(gid_t));
  811         if (error != 0) {
  812                 crfree(tempcred);
  813                 mtx_unlock(&Giant);
  814                 return (error);
  815         }
  816         newcred = crget();
  817         PROC_LOCK(p);
  818         oldcred = p->p_ucred;
  819         error = suser_cred(oldcred, PRISON_ROOT);
  820         if (error) {
  821                 PROC_UNLOCK(p);
  822                 crfree(newcred);
  823                 crfree(tempcred);
  824                 mtx_unlock(&Giant);
  825                 return (error);
  826         }
  827                 
  828         /*
  829          * XXX A little bit lazy here.  We could test if anything has
  830          * changed before crcopy() and setting P_SUGID.
  831          */
  832         crcopy(newcred, oldcred);
  833         if (ngrp < 1) {
  834                 /*
  835                  * setgroups(0, NULL) is a legitimate way of clearing the
  836                  * groups vector on non-BSD systems (which generally do not
  837                  * have the egid in the groups[0]).  We risk security holes
  838                  * when running non-BSD software if we do not do the same.
  839                  */
  840                 newcred->cr_ngroups = 1;
  841         } else {
  842                 bcopy(tempcred->cr_groups, newcred->cr_groups,
  843                     ngrp * sizeof(gid_t));
  844                 newcred->cr_ngroups = ngrp;
  845         }
  846         setsugid(p);
  847         p->p_ucred = newcred;
  848         PROC_UNLOCK(p);
  849         crfree(tempcred);
  850         crfree(oldcred);
  851         mtx_unlock(&Giant);
  852         return (0);
  853 }
  854 
  855 #ifndef _SYS_SYSPROTO_H_
  856 struct setreuid_args {
  857         uid_t   ruid;
  858         uid_t   euid;
  859 };
  860 #endif
  861 /*
  862  * MPSAFE
  863  */
  864 /* ARGSUSED */
  865 int
  866 setreuid(register struct thread *td, struct setreuid_args *uap)
  867 {
  868         struct proc *p = td->td_proc;
  869         struct ucred *newcred, *oldcred;
  870         uid_t euid, ruid;
  871         struct uidinfo *euip, *ruip;
  872         int error;
  873 
  874         euid = uap->euid;
  875         ruid = uap->ruid;
  876         mtx_lock(&Giant);
  877         newcred = crget();
  878         euip = uifind(euid);
  879         ruip = uifind(ruid);
  880         PROC_LOCK(p);
  881         oldcred = p->p_ucred;
  882         if (((ruid != (uid_t)-1 && ruid != oldcred->cr_ruid &&
  883               ruid != oldcred->cr_svuid) ||
  884              (euid != (uid_t)-1 && euid != oldcred->cr_uid &&
  885               euid != oldcred->cr_ruid && euid != oldcred->cr_svuid)) &&
  886             (error = suser_cred(oldcred, PRISON_ROOT)) != 0) {
  887                 PROC_UNLOCK(p);
  888                 uifree(ruip);
  889                 uifree(euip);
  890                 crfree(newcred);
  891                 mtx_unlock(&Giant);
  892                 return (error);
  893         }
  894         crcopy(newcred, oldcred);
  895         if (euid != (uid_t)-1 && oldcred->cr_uid != euid) {
  896                 change_euid(newcred, euip);
  897                 setsugid(p);
  898         }
  899         if (ruid != (uid_t)-1 && oldcred->cr_ruid != ruid) {
  900                 change_ruid(newcred, ruip);
  901                 setsugid(p);
  902         }
  903         if ((ruid != (uid_t)-1 || newcred->cr_uid != newcred->cr_ruid) &&
  904             newcred->cr_svuid != newcred->cr_uid) {
  905                 change_svuid(newcred, newcred->cr_uid);
  906                 setsugid(p);
  907         }
  908         p->p_ucred = newcred;
  909         PROC_UNLOCK(p);
  910         uifree(ruip);
  911         uifree(euip);
  912         crfree(oldcred);
  913         mtx_unlock(&Giant);
  914         return (0);
  915 }
  916 
  917 #ifndef _SYS_SYSPROTO_H_
  918 struct setregid_args {
  919         gid_t   rgid;
  920         gid_t   egid;
  921 };
  922 #endif
  923 /*
  924  * MPSAFE
  925  */
  926 /* ARGSUSED */
  927 int
  928 setregid(register struct thread *td, struct setregid_args *uap)
  929 {
  930         struct proc *p = td->td_proc;
  931         struct ucred *newcred, *oldcred;
  932         gid_t egid, rgid;
  933         int error;
  934 
  935         egid = uap->egid;
  936         rgid = uap->rgid;
  937         mtx_lock(&Giant);
  938         newcred = crget();
  939         PROC_LOCK(p);
  940         oldcred = p->p_ucred;
  941         if (((rgid != (gid_t)-1 && rgid != oldcred->cr_rgid &&
  942             rgid != oldcred->cr_svgid) ||
  943              (egid != (gid_t)-1 && egid != oldcred->cr_groups[0] &&
  944              egid != oldcred->cr_rgid && egid != oldcred->cr_svgid)) &&
  945             (error = suser_cred(oldcred, PRISON_ROOT)) != 0) {
  946                 PROC_UNLOCK(p);
  947                 crfree(newcred);
  948                 mtx_unlock(&Giant);
  949                 return (error);
  950         }
  951 
  952         crcopy(newcred, oldcred);
  953         if (egid != (gid_t)-1 && oldcred->cr_groups[0] != egid) {
  954                 change_egid(newcred, egid);
  955                 setsugid(p);
  956         }
  957         if (rgid != (gid_t)-1 && oldcred->cr_rgid != rgid) {
  958                 change_rgid(newcred, rgid);
  959                 setsugid(p);
  960         }
  961         if ((rgid != (gid_t)-1 || newcred->cr_groups[0] != newcred->cr_rgid) &&
  962             newcred->cr_svgid != newcred->cr_groups[0]) {
  963                 change_svgid(newcred, newcred->cr_groups[0]);
  964                 setsugid(p);
  965         }
  966         p->p_ucred = newcred;
  967         PROC_UNLOCK(p);
  968         crfree(oldcred);
  969         mtx_unlock(&Giant);
  970         return (0);
  971 }
  972 
  973 /*
  974  * setresuid(ruid, euid, suid) is like setreuid except control over the
  975  * saved uid is explicit.
  976  */
  977 
  978 #ifndef _SYS_SYSPROTO_H_
  979 struct setresuid_args {
  980         uid_t   ruid;
  981         uid_t   euid;
  982         uid_t   suid;
  983 };
  984 #endif
  985 /*
  986  * MPSAFE
  987  */
  988 /* ARGSUSED */
  989 int
  990 setresuid(register struct thread *td, struct setresuid_args *uap)
  991 {
  992         struct proc *p = td->td_proc;
  993         struct ucred *newcred, *oldcred;
  994         uid_t euid, ruid, suid;
  995         struct uidinfo *euip, *ruip;
  996         int error;
  997 
  998         euid = uap->euid;
  999         ruid = uap->ruid;
 1000         suid = uap->suid;
 1001         mtx_lock(&Giant);
 1002         newcred = crget();
 1003         euip = uifind(euid);
 1004         ruip = uifind(ruid);
 1005         PROC_LOCK(p);
 1006         oldcred = p->p_ucred;
 1007         if (((ruid != (uid_t)-1 && ruid != oldcred->cr_ruid &&
 1008              ruid != oldcred->cr_svuid &&
 1009               ruid != oldcred->cr_uid) ||
 1010              (euid != (uid_t)-1 && euid != oldcred->cr_ruid &&
 1011             euid != oldcred->cr_svuid &&
 1012               euid != oldcred->cr_uid) ||
 1013              (suid != (uid_t)-1 && suid != oldcred->cr_ruid &&
 1014             suid != oldcred->cr_svuid &&
 1015               suid != oldcred->cr_uid)) &&
 1016             (error = suser_cred(oldcred, PRISON_ROOT)) != 0) {
 1017                 PROC_UNLOCK(p);
 1018                 uifree(ruip);
 1019                 uifree(euip);
 1020                 crfree(newcred);
 1021                 mtx_unlock(&Giant);
 1022                 return (error);
 1023         }
 1024 
 1025         crcopy(newcred, oldcred);
 1026         if (euid != (uid_t)-1 && oldcred->cr_uid != euid) {
 1027                 change_euid(newcred, euip);
 1028                 setsugid(p);
 1029         }
 1030         if (ruid != (uid_t)-1 && oldcred->cr_ruid != ruid) {
 1031                 change_ruid(newcred, ruip);
 1032                 setsugid(p);
 1033         }
 1034         if (suid != (uid_t)-1 && oldcred->cr_svuid != suid) {
 1035                 change_svuid(newcred, suid);
 1036                 setsugid(p);
 1037         }
 1038         p->p_ucred = newcred;
 1039         PROC_UNLOCK(p);
 1040         uifree(ruip);
 1041         uifree(euip);
 1042         crfree(oldcred);
 1043         mtx_unlock(&Giant);
 1044         return (0);
 1045 }
 1046 
 1047 /*
 1048  * setresgid(rgid, egid, sgid) is like setregid except control over the
 1049  * saved gid is explicit.
 1050  */
 1051 
 1052 #ifndef _SYS_SYSPROTO_H_
 1053 struct setresgid_args {
 1054         gid_t   rgid;
 1055         gid_t   egid;
 1056         gid_t   sgid;
 1057 };
 1058 #endif
 1059 /*
 1060  * MPSAFE
 1061  */
 1062 /* ARGSUSED */
 1063 int
 1064 setresgid(register struct thread *td, struct setresgid_args *uap)
 1065 {
 1066         struct proc *p = td->td_proc;
 1067         struct ucred *newcred, *oldcred;
 1068         gid_t egid, rgid, sgid;
 1069         int error;
 1070 
 1071         egid = uap->egid;
 1072         rgid = uap->rgid;
 1073         sgid = uap->sgid;
 1074         mtx_lock(&Giant);
 1075         newcred = crget();
 1076         PROC_LOCK(p);
 1077         oldcred = p->p_ucred;
 1078         if (((rgid != (gid_t)-1 && rgid != oldcred->cr_rgid &&
 1079               rgid != oldcred->cr_svgid &&
 1080               rgid != oldcred->cr_groups[0]) ||
 1081              (egid != (gid_t)-1 && egid != oldcred->cr_rgid &&
 1082               egid != oldcred->cr_svgid &&
 1083               egid != oldcred->cr_groups[0]) ||
 1084              (sgid != (gid_t)-1 && sgid != oldcred->cr_rgid &&
 1085               sgid != oldcred->cr_svgid &&
 1086               sgid != oldcred->cr_groups[0])) &&
 1087             (error = suser_cred(oldcred, PRISON_ROOT)) != 0) {
 1088                 PROC_UNLOCK(p);
 1089                 crfree(newcred);
 1090                 mtx_unlock(&Giant);
 1091                 return (error);
 1092         }
 1093 
 1094         crcopy(newcred, oldcred);
 1095         if (egid != (gid_t)-1 && oldcred->cr_groups[0] != egid) {
 1096                 change_egid(newcred, egid);
 1097                 setsugid(p);
 1098         }
 1099         if (rgid != (gid_t)-1 && oldcred->cr_rgid != rgid) {
 1100                 change_rgid(newcred, rgid);
 1101                 setsugid(p);
 1102         }
 1103         if (sgid != (gid_t)-1 && oldcred->cr_svgid != sgid) {
 1104                 change_svgid(newcred, sgid);
 1105                 setsugid(p);
 1106         }
 1107         p->p_ucred = newcred;
 1108         PROC_UNLOCK(p);
 1109         crfree(oldcred);
 1110         mtx_unlock(&Giant);
 1111         return (0);
 1112 }
 1113 
 1114 #ifndef _SYS_SYSPROTO_H_
 1115 struct getresuid_args {
 1116         uid_t   *ruid;
 1117         uid_t   *euid;
 1118         uid_t   *suid;
 1119 };
 1120 #endif
 1121 /*
 1122  * MPSAFE
 1123  */
 1124 /* ARGSUSED */
 1125 int
 1126 getresuid(register struct thread *td, struct getresuid_args *uap)
 1127 {
 1128         struct ucred *cred;
 1129         int error1 = 0, error2 = 0, error3 = 0;
 1130 
 1131         cred = td->td_ucred;
 1132         if (uap->ruid)
 1133                 error1 = copyout(&cred->cr_ruid,
 1134                     uap->ruid, sizeof(cred->cr_ruid));
 1135         if (uap->euid)
 1136                 error2 = copyout(&cred->cr_uid,
 1137                     uap->euid, sizeof(cred->cr_uid));
 1138         if (uap->suid)
 1139                 error3 = copyout(&cred->cr_svuid,
 1140                     uap->suid, sizeof(cred->cr_svuid));
 1141         return (error1 ? error1 : error2 ? error2 : error3);
 1142 }
 1143 
 1144 #ifndef _SYS_SYSPROTO_H_
 1145 struct getresgid_args {
 1146         gid_t   *rgid;
 1147         gid_t   *egid;
 1148         gid_t   *sgid;
 1149 };
 1150 #endif
 1151 /*
 1152  * MPSAFE
 1153  */
 1154 /* ARGSUSED */
 1155 int
 1156 getresgid(register struct thread *td, struct getresgid_args *uap)
 1157 {
 1158         struct ucred *cred;
 1159         int error1 = 0, error2 = 0, error3 = 0;
 1160 
 1161         cred = td->td_ucred;
 1162         if (uap->rgid)
 1163                 error1 = copyout(&cred->cr_rgid,
 1164                     uap->rgid, sizeof(cred->cr_rgid));
 1165         if (uap->egid)
 1166                 error2 = copyout(&cred->cr_groups[0],
 1167                     uap->egid, sizeof(cred->cr_groups[0]));
 1168         if (uap->sgid)
 1169                 error3 = copyout(&cred->cr_svgid,
 1170                     uap->sgid, sizeof(cred->cr_svgid));
 1171         return (error1 ? error1 : error2 ? error2 : error3);
 1172 }
 1173 
 1174 #ifndef _SYS_SYSPROTO_H_
 1175 struct issetugid_args {
 1176         int dummy;
 1177 };
 1178 #endif
 1179 /*
 1180  * NOT MPSAFE?
 1181  */
 1182 /* ARGSUSED */
 1183 int
 1184 issetugid(register struct thread *td, struct issetugid_args *uap)
 1185 {
 1186         struct proc *p = td->td_proc;
 1187 
 1188         /*
 1189          * Note: OpenBSD sets a P_SUGIDEXEC flag set at execve() time,
 1190          * we use P_SUGID because we consider changing the owners as
 1191          * "tainting" as well.
 1192          * This is significant for procs that start as root and "become"
 1193          * a user without an exec - programs cannot know *everything*
 1194          * that libc *might* have put in their data segment.
 1195          */
 1196         PROC_LOCK(p);
 1197         td->td_retval[0] = (p->p_flag & P_SUGID) ? 1 : 0;
 1198         PROC_UNLOCK(p);
 1199         return (0);
 1200 }
 1201 
 1202 /*
 1203  * MPSAFE
 1204  */
 1205 int
 1206 __setugid(struct thread *td, struct __setugid_args *uap)
 1207 {
 1208 #ifdef REGRESSION
 1209         struct proc *p;
 1210 
 1211         p = td->td_proc;
 1212         switch (uap->flag) {
 1213         case 0:
 1214                 mtx_lock(&Giant);
 1215                 PROC_LOCK(p);
 1216                 p->p_flag &= ~P_SUGID;
 1217                 PROC_UNLOCK(p);
 1218                 mtx_unlock(&Giant);
 1219                 return (0);
 1220         case 1:
 1221                 mtx_lock(&Giant);
 1222                 PROC_LOCK(p);
 1223                 p->p_flag |= P_SUGID;
 1224                 PROC_UNLOCK(p);
 1225                 mtx_unlock(&Giant);
 1226                 return (0);
 1227         default:
 1228                 return (EINVAL);
 1229         }
 1230 #else /* !REGRESSION */
 1231 
 1232         return (ENOSYS);
 1233 #endif /* REGRESSION */
 1234 }
 1235 
 1236 /*
 1237  * Check if gid is a member of the group set.
 1238  *
 1239  * MPSAFE (cred must be held)
 1240  */
 1241 int
 1242 groupmember(gid_t gid, struct ucred *cred)
 1243 {
 1244         register gid_t *gp;
 1245         gid_t *egp;
 1246 
 1247         egp = &(cred->cr_groups[cred->cr_ngroups]);
 1248         for (gp = cred->cr_groups; gp < egp; gp++)
 1249                 if (*gp == gid)
 1250                         return (1);
 1251         return (0);
 1252 }
 1253 
 1254 /*
 1255  * `suser_enabled' (which can be set by the security.suser_enabled
 1256  * sysctl) determines whether the system 'super-user' policy is in effect.
 1257  * If it is nonzero, an effective uid of 0 connotes special privilege,
 1258  * overriding many mandatory and discretionary protections.  If it is zero,
 1259  * uid 0 is offered no special privilege in the kernel security policy.
 1260  * Setting it to zero may seriously impact the functionality of many
 1261  * existing userland programs, and should not be done without careful
 1262  * consideration of the consequences.
 1263  */
 1264 int     suser_enabled = 1;
 1265 SYSCTL_INT(_security_bsd, OID_AUTO, suser_enabled, CTLFLAG_RW,
 1266     &suser_enabled, 0, "processes with uid 0 have privilege");
 1267 TUNABLE_INT("security.bsd.suser_enabled", &suser_enabled);
 1268 
 1269 /*
 1270  * Test whether the specified credentials imply "super-user" privilege.
 1271  * Return 0 or EPERM.  The flag argument is currently used only to
 1272  * specify jail interaction.
 1273  */
 1274 int
 1275 suser_cred(struct ucred *cred, int flag)
 1276 {
 1277 
 1278         if (!suser_enabled)
 1279                 return (EPERM);
 1280         if (cred->cr_uid != 0)
 1281                 return (EPERM);
 1282         if (jailed(cred) && !(flag & PRISON_ROOT))
 1283                 return (EPERM);
 1284         return (0);
 1285 }
 1286 
 1287 /*
 1288  * Shortcut to hide contents of struct td and struct proc from the
 1289  * caller, promoting binary compatibility.
 1290  */
 1291 int
 1292 suser(struct thread *td)
 1293 {
 1294 
 1295         return (suser_cred(td->td_ucred, 0));
 1296 }
 1297 
 1298 /*
 1299  * Test the active securelevel against a given level.  securelevel_gt()
 1300  * implements (securelevel > level).  securelevel_ge() implements
 1301  * (securelevel >= level).  Note that the logic is inverted -- these
 1302  * functions return EPERM on "success" and 0 on "failure".
 1303  *
 1304  * MPSAFE
 1305  */
 1306 int
 1307 securelevel_gt(struct ucred *cr, int level)
 1308 {
 1309         int active_securelevel;
 1310 
 1311         active_securelevel = securelevel;
 1312         KASSERT(cr != NULL, ("securelevel_gt: null cr"));
 1313         if (cr->cr_prison != NULL) {
 1314                 mtx_lock(&cr->cr_prison->pr_mtx);
 1315                 active_securelevel = imax(cr->cr_prison->pr_securelevel,
 1316                     active_securelevel);
 1317                 mtx_unlock(&cr->cr_prison->pr_mtx);
 1318         }
 1319         return (active_securelevel > level ? EPERM : 0);
 1320 }
 1321 
 1322 int
 1323 securelevel_ge(struct ucred *cr, int level)
 1324 {
 1325         int active_securelevel;
 1326 
 1327         active_securelevel = securelevel;
 1328         KASSERT(cr != NULL, ("securelevel_ge: null cr"));
 1329         if (cr->cr_prison != NULL) {
 1330                 mtx_lock(&cr->cr_prison->pr_mtx);
 1331                 active_securelevel = imax(cr->cr_prison->pr_securelevel,
 1332                     active_securelevel);
 1333                 mtx_unlock(&cr->cr_prison->pr_mtx);
 1334         }
 1335         return (active_securelevel >= level ? EPERM : 0);
 1336 }
 1337 
 1338 /*
 1339  * 'see_other_uids' determines whether or not visibility of processes
 1340  * and sockets with credentials holding different real uids is possible
 1341  * using a variety of system MIBs.
 1342  * XXX: data declarations should be together near the beginning of the file.
 1343  */
 1344 static int      see_other_uids = 1;
 1345 SYSCTL_INT(_security_bsd, OID_AUTO, see_other_uids, CTLFLAG_RW,
 1346     &see_other_uids, 0,
 1347     "Unprivileged processes may see subjects/objects with different real uid");
 1348 
 1349 /*-
 1350  * Determine if u1 "can see" the subject specified by u2, according to the
 1351  * 'see_other_uids' policy.
 1352  * Returns: 0 for permitted, ESRCH otherwise
 1353  * Locks: none
 1354  * References: *u1 and *u2 must not change during the call
 1355  *             u1 may equal u2, in which case only one reference is required
 1356  */
 1357 static int
 1358 cr_seeotheruids(struct ucred *u1, struct ucred *u2)
 1359 {
 1360 
 1361         if (!see_other_uids && u1->cr_ruid != u2->cr_ruid) {
 1362                 if (suser_cred(u1, PRISON_ROOT) != 0)
 1363                         return (ESRCH);
 1364         }
 1365         return (0);
 1366 }
 1367 
 1368 /*-
 1369  * Determine if u1 "can see" the subject specified by u2.
 1370  * Returns: 0 for permitted, an errno value otherwise
 1371  * Locks: none
 1372  * References: *u1 and *u2 must not change during the call
 1373  *             u1 may equal u2, in which case only one reference is required
 1374  */
 1375 int
 1376 cr_cansee(struct ucred *u1, struct ucred *u2)
 1377 {
 1378         int error;
 1379 
 1380         if ((error = prison_check(u1, u2)))
 1381                 return (error);
 1382 #ifdef MAC
 1383         if ((error = mac_check_cred_visible(u1, u2)))
 1384                 return (error);
 1385 #endif
 1386         if ((error = cr_seeotheruids(u1, u2)))
 1387                 return (error);
 1388         return (0);
 1389 }
 1390 
 1391 /*-
 1392  * Determine if td "can see" the subject specified by p.
 1393  * Returns: 0 for permitted, an errno value otherwise
 1394  * Locks: Sufficient locks to protect p->p_ucred must be held.  td really
 1395  *        should be curthread.
 1396  * References: td and p must be valid for the lifetime of the call
 1397  */
 1398 int
 1399 p_cansee(struct thread *td, struct proc *p)
 1400 {
 1401 
 1402         /* Wrap cr_cansee() for all functionality. */
 1403         KASSERT(td == curthread, ("%s: td not curthread", __func__));
 1404         PROC_LOCK_ASSERT(p, MA_OWNED);
 1405         return (cr_cansee(td->td_ucred, p->p_ucred));
 1406 }
 1407 
 1408 /*-
 1409  * Determine whether cred may deliver the specified signal to proc.
 1410  * Returns: 0 for permitted, an errno value otherwise.
 1411  * Locks: A lock must be held for proc.
 1412  * References: cred and proc must be valid for the lifetime of the call.
 1413  */
 1414 int
 1415 cr_cansignal(struct ucred *cred, struct proc *proc, int signum)
 1416 {
 1417         int error;
 1418 
 1419         PROC_LOCK_ASSERT(proc, MA_OWNED);
 1420         /*
 1421          * Jail semantics limit the scope of signalling to proc in the
 1422          * same jail as cred, if cred is in jail.
 1423          */
 1424         error = prison_check(cred, proc->p_ucred);
 1425         if (error)
 1426                 return (error);
 1427 #ifdef MAC
 1428         if ((error = mac_check_proc_signal(cred, proc, signum)))
 1429                 return (error);
 1430 #endif
 1431         error = cr_seeotheruids(cred, proc->p_ucred);
 1432         if (error)
 1433                 return (error);
 1434 
 1435         /*
 1436          * UNIX signal semantics depend on the status of the P_SUGID
 1437          * bit on the target process.  If the bit is set, then additional
 1438          * restrictions are placed on the set of available signals.
 1439          */
 1440         if (proc->p_flag & P_SUGID) {
 1441                 switch (signum) {
 1442                 case 0:
 1443                 case SIGKILL:
 1444                 case SIGINT:
 1445                 case SIGTERM:
 1446                 case SIGSTOP:
 1447                 case SIGTTIN:
 1448                 case SIGTTOU:
 1449                 case SIGTSTP:
 1450                 case SIGHUP:
 1451                 case SIGUSR1:
 1452                 case SIGUSR2:
 1453                         /*
 1454                          * Generally, permit job and terminal control
 1455                          * signals.
 1456                          */
 1457                         break;
 1458                 default:
 1459                         /* Not permitted without privilege. */
 1460                         error = suser_cred(cred, PRISON_ROOT);
 1461                         if (error)
 1462                                 return (error);
 1463                 }
 1464         }
 1465 
 1466         /*
 1467          * Generally, the target credential's ruid or svuid must match the
 1468          * subject credential's ruid or euid.
 1469          */
 1470         if (cred->cr_ruid != proc->p_ucred->cr_ruid &&
 1471             cred->cr_ruid != proc->p_ucred->cr_svuid &&
 1472             cred->cr_uid != proc->p_ucred->cr_ruid &&
 1473             cred->cr_uid != proc->p_ucred->cr_svuid) {
 1474                 /* Not permitted without privilege. */
 1475                 error = suser_cred(cred, PRISON_ROOT);
 1476                 if (error)
 1477                         return (error);
 1478         }
 1479 
 1480         return (0);
 1481 }
 1482 
 1483 
 1484 /*-
 1485  * Determine whether td may deliver the specified signal to p.
 1486  * Returns: 0 for permitted, an errno value otherwise
 1487  * Locks: Sufficient locks to protect various components of td and p
 1488  *        must be held.  td must be curthread, and a lock must be
 1489  *        held for p.
 1490  * References: td and p must be valid for the lifetime of the call
 1491  */
 1492 int
 1493 p_cansignal(struct thread *td, struct proc *p, int signum)
 1494 {
 1495 
 1496         KASSERT(td == curthread, ("%s: td not curthread", __func__));
 1497         PROC_LOCK_ASSERT(p, MA_OWNED);
 1498         if (td->td_proc == p)
 1499                 return (0);
 1500 
 1501         /*
 1502          * UNIX signalling semantics require that processes in the same
 1503          * session always be able to deliver SIGCONT to one another,
 1504          * overriding the remaining protections.
 1505          */
 1506         /* XXX: This will require an additional lock of some sort. */
 1507         if (signum == SIGCONT && td->td_proc->p_session == p->p_session)
 1508                 return (0);
 1509 
 1510         return (cr_cansignal(td->td_ucred, p, signum));
 1511 }
 1512 
 1513 /*-
 1514  * Determine whether td may reschedule p.
 1515  * Returns: 0 for permitted, an errno value otherwise
 1516  * Locks: Sufficient locks to protect various components of td and p
 1517  *        must be held.  td must be curthread, and a lock must
 1518  *        be held for p.
 1519  * References: td and p must be valid for the lifetime of the call
 1520  */
 1521 int
 1522 p_cansched(struct thread *td, struct proc *p)
 1523 {
 1524         int error;
 1525 
 1526         KASSERT(td == curthread, ("%s: td not curthread", __func__));
 1527         PROC_LOCK_ASSERT(p, MA_OWNED);
 1528         if (td->td_proc == p)
 1529                 return (0);
 1530         if ((error = prison_check(td->td_ucred, p->p_ucred)))
 1531                 return (error);
 1532 #ifdef MAC
 1533         if ((error = mac_check_proc_sched(td->td_ucred, p)))
 1534                 return (error);
 1535 #endif
 1536         if ((error = cr_seeotheruids(td->td_ucred, p->p_ucred)))
 1537                 return (error);
 1538         if (td->td_ucred->cr_ruid == p->p_ucred->cr_ruid)
 1539                 return (0);
 1540         if (td->td_ucred->cr_uid == p->p_ucred->cr_ruid)
 1541                 return (0);
 1542         if (suser_cred(td->td_ucred, PRISON_ROOT) == 0)
 1543                 return (0);
 1544 
 1545 #ifdef CAPABILITIES
 1546         if (!cap_check(NULL, td, CAP_SYS_NICE, PRISON_ROOT))
 1547                 return (0);
 1548 #endif
 1549 
 1550         return (EPERM);
 1551 }
 1552 
 1553 /*
 1554  * The 'unprivileged_proc_debug' flag may be used to disable a variety of
 1555  * unprivileged inter-process debugging services, including some procfs
 1556  * functionality, ptrace(), and ktrace().  In the past, inter-process
 1557  * debugging has been involved in a variety of security problems, and sites
 1558  * not requiring the service might choose to disable it when hardening
 1559  * systems.
 1560  *
 1561  * XXX: Should modifying and reading this variable require locking?
 1562  * XXX: data declarations should be together near the beginning of the file.
 1563  */
 1564 static int      unprivileged_proc_debug = 1;
 1565 SYSCTL_INT(_security_bsd, OID_AUTO, unprivileged_proc_debug, CTLFLAG_RW,
 1566     &unprivileged_proc_debug, 0,
 1567     "Unprivileged processes may use process debugging facilities");
 1568 
 1569 /*-
 1570  * Determine whether td may debug p.
 1571  * Returns: 0 for permitted, an errno value otherwise
 1572  * Locks: Sufficient locks to protect various components of td and p
 1573  *        must be held.  td must be curthread, and a lock must
 1574  *        be held for p.
 1575  * References: td and p must be valid for the lifetime of the call
 1576  */
 1577 int
 1578 p_candebug(struct thread *td, struct proc *p)
 1579 {
 1580         int credentialchanged, error, grpsubset, i, uidsubset;
 1581 
 1582         KASSERT(td == curthread, ("%s: td not curthread", __func__));
 1583         PROC_LOCK_ASSERT(p, MA_OWNED);
 1584         if (!unprivileged_proc_debug) {
 1585                 error = suser_cred(td->td_ucred, PRISON_ROOT);
 1586                 if (error)
 1587                         return (error);
 1588         }
 1589         if (td->td_proc == p)
 1590                 return (0);
 1591         if ((error = prison_check(td->td_ucred, p->p_ucred)))
 1592                 return (error);
 1593 #ifdef MAC
 1594         if ((error = mac_check_proc_debug(td->td_ucred, p)))
 1595                 return (error);
 1596 #endif
 1597         if ((error = cr_seeotheruids(td->td_ucred, p->p_ucred)))
 1598                 return (error);
 1599 
 1600         /*
 1601          * Is p's group set a subset of td's effective group set?  This
 1602          * includes p's egid, group access list, rgid, and svgid.
 1603          */
 1604         grpsubset = 1;
 1605         for (i = 0; i < p->p_ucred->cr_ngroups; i++) {
 1606                 if (!groupmember(p->p_ucred->cr_groups[i], td->td_ucred)) {
 1607                         grpsubset = 0;
 1608                         break;
 1609                 }
 1610         }
 1611         grpsubset = grpsubset &&
 1612             groupmember(p->p_ucred->cr_rgid, td->td_ucred) &&
 1613             groupmember(p->p_ucred->cr_svgid, td->td_ucred);
 1614 
 1615         /*
 1616          * Are the uids present in p's credential equal to td's
 1617          * effective uid?  This includes p's euid, svuid, and ruid.
 1618          */
 1619         uidsubset = (td->td_ucred->cr_uid == p->p_ucred->cr_uid &&
 1620             td->td_ucred->cr_uid == p->p_ucred->cr_svuid &&
 1621             td->td_ucred->cr_uid == p->p_ucred->cr_ruid);
 1622 
 1623         /*
 1624          * Has the credential of the process changed since the last exec()?
 1625          */
 1626         credentialchanged = (p->p_flag & P_SUGID);
 1627 
 1628         /*
 1629          * If p's gids aren't a subset, or the uids aren't a subset,
 1630          * or the credential has changed, require appropriate privilege
 1631          * for td to debug p.  For POSIX.1e capabilities, this will
 1632          * require CAP_SYS_PTRACE.
 1633          */
 1634         if (!grpsubset || !uidsubset || credentialchanged) {
 1635                 error = suser_cred(td->td_ucred, PRISON_ROOT);
 1636                 if (error)
 1637                         return (error);
 1638         }
 1639 
 1640         /* Can't trace init when securelevel > 0. */
 1641         if (p == initproc) {
 1642                 error = securelevel_gt(td->td_ucred, 0);
 1643                 if (error)
 1644                         return (error);
 1645         }
 1646 
 1647         /*
 1648          * Can't trace a process that's currently exec'ing.
 1649          * XXX: Note, this is not a security policy decision, it's a
 1650          * basic correctness/functionality decision.  Therefore, this check
 1651          * should be moved to the caller's of p_candebug().
 1652          */
 1653         if ((p->p_flag & P_INEXEC) != 0)
 1654                 return (EAGAIN);
 1655 
 1656         return (0);
 1657 }
 1658 
 1659 /*-
 1660  * Determine whether the subject represented by cred can "see" a socket.
 1661  * Returns: 0 for permitted, ENOENT otherwise.
 1662  */
 1663 int
 1664 cr_canseesocket(struct ucred *cred, struct socket *so)
 1665 {
 1666         int error;
 1667 
 1668         error = prison_check(cred, so->so_cred);
 1669         if (error)
 1670                 return (ENOENT);
 1671 #ifdef MAC
 1672         error = mac_check_socket_visible(cred, so);
 1673         if (error)
 1674                 return (error);
 1675 #endif
 1676         if (cr_seeotheruids(cred, so->so_cred))
 1677                 return (ENOENT);
 1678 
 1679         return (0);
 1680 }
 1681 
 1682 /*
 1683  * Allocate a zeroed cred structure.
 1684  */
 1685 struct ucred *
 1686 crget(void)
 1687 {
 1688         register struct ucred *cr;
 1689 
 1690         MALLOC(cr, struct ucred *, sizeof(*cr), M_CRED, M_WAITOK | M_ZERO);
 1691         cr->cr_ref = 1;
 1692         cr->cr_mtxp = mtx_pool_find(cr);
 1693 #ifdef MAC
 1694         mac_init_cred(cr);
 1695 #endif
 1696         return (cr);
 1697 }
 1698 
 1699 /*
 1700  * Claim another reference to a ucred structure.
 1701  */
 1702 struct ucred *
 1703 crhold(struct ucred *cr)
 1704 {
 1705 
 1706         mtx_lock(cr->cr_mtxp);
 1707         cr->cr_ref++;
 1708         mtx_unlock(cr->cr_mtxp);
 1709         return (cr);
 1710 }
 1711 
 1712 /*
 1713  * Free a cred structure.
 1714  * Throws away space when ref count gets to 0.
 1715  */
 1716 void
 1717 crfree(struct ucred *cr)
 1718 {
 1719         struct mtx *mtxp = cr->cr_mtxp;
 1720 
 1721         mtx_lock(mtxp);
 1722         KASSERT(cr->cr_ref > 0, ("bad ucred refcount: %d", cr->cr_ref));
 1723         if (--cr->cr_ref == 0) {
 1724                 /*
 1725                  * Some callers of crget(), such as nfs_statfs(),
 1726                  * allocate a temporary credential, but don't
 1727                  * allocate a uidinfo structure.
 1728                  */
 1729                 mtx_unlock(mtxp);
 1730                 mtx_lock(&Giant);
 1731                 if (cr->cr_uidinfo != NULL)
 1732                         uifree(cr->cr_uidinfo);
 1733                 if (cr->cr_ruidinfo != NULL)
 1734                         uifree(cr->cr_ruidinfo);
 1735                 /*
 1736                  * Free a prison, if any.
 1737                  */
 1738                 if (jailed(cr))
 1739                         prison_free(cr->cr_prison);
 1740 #ifdef MAC
 1741                 mac_destroy_cred(cr);
 1742 #endif
 1743                 FREE(cr, M_CRED);
 1744                 mtx_unlock(&Giant);
 1745         } else {
 1746                 mtx_unlock(mtxp);
 1747         }
 1748 }
 1749 
 1750 /*
 1751  * Check to see if this ucred is shared.
 1752  */
 1753 int
 1754 crshared(struct ucred *cr)
 1755 {
 1756         int shared;
 1757 
 1758         mtx_lock(cr->cr_mtxp);
 1759         shared = (cr->cr_ref > 1);
 1760         mtx_unlock(cr->cr_mtxp);
 1761         return (shared);
 1762 }
 1763 
 1764 /*
 1765  * Copy a ucred's contents from a template.  Does not block.
 1766  */
 1767 void
 1768 crcopy(struct ucred *dest, struct ucred *src)
 1769 {
 1770 
 1771         KASSERT(crshared(dest) == 0, ("crcopy of shared ucred"));
 1772         bcopy(&src->cr_startcopy, &dest->cr_startcopy,
 1773             (unsigned)((caddr_t)&src->cr_endcopy -
 1774                 (caddr_t)&src->cr_startcopy));
 1775         uihold(dest->cr_uidinfo);
 1776         uihold(dest->cr_ruidinfo);
 1777         if (jailed(dest))
 1778                 prison_hold(dest->cr_prison);
 1779 #ifdef MAC
 1780         mac_create_cred(src, dest);
 1781 #endif
 1782 }
 1783 
 1784 /*
 1785  * Dup cred struct to a new held one.
 1786  */
 1787 struct ucred *
 1788 crdup(struct ucred *cr)
 1789 {
 1790         struct ucred *newcr;
 1791 
 1792         newcr = crget();
 1793         crcopy(newcr, cr);
 1794         return (newcr);
 1795 }
 1796 
 1797 #ifdef DIAGNOSTIC
 1798 void
 1799 cred_free_thread(struct thread *td)
 1800 {
 1801         struct ucred *cred;
 1802 
 1803         cred = td->td_ucred;
 1804         td->td_ucred = NULL;
 1805         if (cred != NULL)
 1806                 crfree(cred);
 1807 }
 1808 #endif
 1809 
 1810 /*
 1811  * Fill in a struct xucred based on a struct ucred.
 1812  */
 1813 void
 1814 cru2x(struct ucred *cr, struct xucred *xcr)
 1815 {
 1816 
 1817         bzero(xcr, sizeof(*xcr));
 1818         xcr->cr_version = XUCRED_VERSION;
 1819         xcr->cr_uid = cr->cr_uid;
 1820         xcr->cr_ngroups = cr->cr_ngroups;
 1821         bcopy(cr->cr_groups, xcr->cr_groups, sizeof(cr->cr_groups));
 1822 }
 1823 
 1824 /*
 1825  * small routine to swap a thread's current ucred for the correct one
 1826  * taken from the process.
 1827  */
 1828 void
 1829 cred_update_thread(struct thread *td)
 1830 {
 1831         struct proc *p;
 1832         struct ucred *cred;
 1833 
 1834         p = td->td_proc;
 1835         cred = td->td_ucred;
 1836         mtx_lock(&Giant);
 1837         PROC_LOCK(p);
 1838         td->td_ucred = crhold(p->p_ucred);
 1839         PROC_UNLOCK(p);
 1840         if (cred != NULL)
 1841                 crfree(cred);
 1842         mtx_unlock(&Giant);
 1843 }
 1844 
 1845 /*
 1846  * Get login name, if available.
 1847  */
 1848 #ifndef _SYS_SYSPROTO_H_
 1849 struct getlogin_args {
 1850         char    *namebuf;
 1851         u_int   namelen;
 1852 };
 1853 #endif
 1854 /*
 1855  * MPSAFE
 1856  */
 1857 /* ARGSUSED */
 1858 int
 1859 getlogin(struct thread *td, struct getlogin_args *uap)
 1860 {
 1861         int error;
 1862         char login[MAXLOGNAME];
 1863         struct proc *p = td->td_proc;
 1864 
 1865         if (uap->namelen > MAXLOGNAME)
 1866                 uap->namelen = MAXLOGNAME;
 1867         PROC_LOCK(p);
 1868         SESS_LOCK(p->p_session);
 1869         bcopy(p->p_session->s_login, login, uap->namelen);
 1870         SESS_UNLOCK(p->p_session);
 1871         PROC_UNLOCK(p);
 1872         error = copyout(login, uap->namebuf, uap->namelen);
 1873         return(error);
 1874 }
 1875 
 1876 /*
 1877  * Set login name.
 1878  */
 1879 #ifndef _SYS_SYSPROTO_H_
 1880 struct setlogin_args {
 1881         char    *namebuf;
 1882 };
 1883 #endif
 1884 /*
 1885  * MPSAFE
 1886  */
 1887 /* ARGSUSED */
 1888 int
 1889 setlogin(struct thread *td, struct setlogin_args *uap)
 1890 {
 1891         struct proc *p = td->td_proc;
 1892         int error;
 1893         char logintmp[MAXLOGNAME];
 1894 
 1895         error = suser_cred(td->td_ucred, PRISON_ROOT);
 1896         if (error)
 1897                 return (error);
 1898         error = copyinstr(uap->namebuf, logintmp, sizeof(logintmp), NULL);
 1899         if (error == ENAMETOOLONG)
 1900                 error = EINVAL;
 1901         else if (!error) {
 1902                 PROC_LOCK(p);
 1903                 SESS_LOCK(p->p_session);
 1904                 (void) memcpy(p->p_session->s_login, logintmp,
 1905                     sizeof(logintmp));
 1906                 SESS_UNLOCK(p->p_session);
 1907                 PROC_UNLOCK(p);
 1908         }
 1909         return (error);
 1910 }
 1911 
 1912 void
 1913 setsugid(struct proc *p)
 1914 {
 1915 
 1916         PROC_LOCK_ASSERT(p, MA_OWNED);
 1917         p->p_flag |= P_SUGID;
 1918         if (!(p->p_pfsflags & PF_ISUGID))
 1919                 p->p_stops = 0;
 1920 }
 1921 
 1922 /*-
 1923  * Change a process's effective uid.
 1924  * Side effects: newcred->cr_uid and newcred->cr_uidinfo will be modified.
 1925  * References: newcred must be an exclusive credential reference for the
 1926  *             duration of the call.
 1927  */
 1928 void
 1929 change_euid(struct ucred *newcred, struct uidinfo *euip)
 1930 {
 1931 
 1932         newcred->cr_uid = euip->ui_uid;
 1933         uihold(euip);
 1934         uifree(newcred->cr_uidinfo);
 1935         newcred->cr_uidinfo = euip;
 1936 }
 1937 
 1938 /*-
 1939  * Change a process's effective gid.
 1940  * Side effects: newcred->cr_gid will be modified.
 1941  * References: newcred must be an exclusive credential reference for the
 1942  *             duration of the call.
 1943  */
 1944 void
 1945 change_egid(struct ucred *newcred, gid_t egid)
 1946 {
 1947 
 1948         newcred->cr_groups[0] = egid;
 1949 }
 1950 
 1951 /*-
 1952  * Change a process's real uid.
 1953  * Side effects: newcred->cr_ruid will be updated, newcred->cr_ruidinfo
 1954  *               will be updated, and the old and new cr_ruidinfo proc
 1955  *               counts will be updated.
 1956  * References: newcred must be an exclusive credential reference for the
 1957  *             duration of the call.
 1958  */
 1959 void
 1960 change_ruid(struct ucred *newcred, struct uidinfo *ruip)
 1961 {
 1962 
 1963         (void)chgproccnt(newcred->cr_ruidinfo, -1, 0);
 1964         newcred->cr_ruid = ruip->ui_uid;
 1965         uihold(ruip);
 1966         uifree(newcred->cr_ruidinfo);
 1967         newcred->cr_ruidinfo = ruip;
 1968         (void)chgproccnt(newcred->cr_ruidinfo, 1, 0);
 1969 }
 1970 
 1971 /*-
 1972  * Change a process's real gid.
 1973  * Side effects: newcred->cr_rgid will be updated.
 1974  * References: newcred must be an exclusive credential reference for the
 1975  *             duration of the call.
 1976  */
 1977 void
 1978 change_rgid(struct ucred *newcred, gid_t rgid)
 1979 {
 1980 
 1981         newcred->cr_rgid = rgid;
 1982 }
 1983 
 1984 /*-
 1985  * Change a process's saved uid.
 1986  * Side effects: newcred->cr_svuid will be updated.
 1987  * References: newcred must be an exclusive credential reference for the
 1988  *             duration of the call.
 1989  */
 1990 void
 1991 change_svuid(struct ucred *newcred, uid_t svuid)
 1992 {
 1993 
 1994         newcred->cr_svuid = svuid;
 1995 }
 1996 
 1997 /*-
 1998  * Change a process's saved gid.
 1999  * Side effects: newcred->cr_svgid will be updated.
 2000  * References: newcred must be an exclusive credential reference for the
 2001  *             duration of the call.
 2002  */
 2003 void
 2004 change_svgid(struct ucred *newcred, gid_t svgid)
 2005 {
 2006 
 2007         newcred->cr_svgid = svgid;
 2008 }

Cache object: cea2fcd8eaead7d38b9a5bd239208ebb


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.