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

Cache object: ce6e708b34b9a4e26d65bb6f01435345


[ 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.