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

Cache object: c4e135c591d48800c84de6092ae30e6b


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