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

Cache object: ed8b5b25c76596d634a8cba9d7a6a7bc


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