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

Cache object: 73f74bee273bfe463b92ff7bd6d8bc15


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