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

Cache object: 0787588e6cfa13e13bad466beb3cc64a


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