The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/kern/kern_prot.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 4487cb58e5b4a4870e6ae145a8f88fa9


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