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

Cache object: 1ed11a9824ba21816461223e0abc1812


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