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

Cache object: b7c1194b8542f7c6d76abf429d606dfd


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