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  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  * 3. All advertising materials mentioning features or use of this software
   19  *    must display the following acknowledgement:
   20  *      This product includes software developed by the University of
   21  *      California, Berkeley and its contributors.
   22  * 4. Neither the name of the University nor the names of its contributors
   23  *    may be used to endorse or promote products derived from this software
   24  *    without specific prior written permission.
   25  *
   26  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   27  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   29  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   30  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   31  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   32  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   33  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   35  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   36  * SUCH DAMAGE.
   37  *
   38  *      @(#)kern_prot.c 8.6 (Berkeley) 1/21/94
   39  * $FreeBSD$
   40  */
   41 
   42 /*
   43  * System calls related to processes and protection
   44  */
   45 
   46 #include "opt_compat.h"
   47 
   48 #include <sys/param.h>
   49 #include <sys/acct.h>
   50 #include <sys/systm.h>
   51 #include <sys/sysproto.h>
   52 #include <sys/kernel.h>
   53 #include <sys/proc.h>
   54 #include <sys/malloc.h>
   55 #include <sys/pioctl.h>
   56 #include <sys/resourcevar.h>
   57 
   58 static MALLOC_DEFINE(M_CRED, "cred", "credentials");
   59 
   60 #ifndef _SYS_SYSPROTO_H_
   61 struct getpid_args {
   62         int     dummy;
   63 };
   64 #endif
   65 
   66 /*
   67  * NOT MP SAFE due to p_pptr access
   68  */
   69 /* ARGSUSED */
   70 int
   71 getpid(p, uap)
   72         struct proc *p;
   73         struct getpid_args *uap;
   74 {
   75 
   76         p->p_retval[0] = p->p_pid;
   77 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
   78         p->p_retval[1] = p->p_pptr->p_pid;
   79 #endif
   80         return (0);
   81 }
   82 
   83 #ifndef _SYS_SYSPROTO_H_
   84 struct getppid_args {
   85         int     dummy;
   86 };
   87 #endif
   88 /* ARGSUSED */
   89 int
   90 getppid(p, uap)
   91         struct proc *p;
   92         struct getppid_args *uap;
   93 {
   94 
   95         p->p_retval[0] = p->p_pptr->p_pid;
   96         return (0);
   97 }
   98 
   99 /* 
  100  * Get process group ID; note that POSIX getpgrp takes no parameter 
  101  *
  102  * MP SAFE
  103  */
  104 #ifndef _SYS_SYSPROTO_H_
  105 struct getpgrp_args {
  106         int     dummy;
  107 };
  108 #endif
  109 
  110 int
  111 getpgrp(p, uap)
  112         struct proc *p;
  113         struct getpgrp_args *uap;
  114 {
  115 
  116         p->p_retval[0] = p->p_pgrp->pg_id;
  117         return (0);
  118 }
  119 
  120 /* Get an arbitary pid's process group id */
  121 #ifndef _SYS_SYSPROTO_H_
  122 struct getpgid_args {
  123         pid_t   pid;
  124 };
  125 #endif
  126 
  127 int
  128 getpgid(p, uap)
  129         struct proc *p;
  130         struct getpgid_args *uap;
  131 {
  132         struct proc *pt;
  133 
  134         pt = p;
  135         if (uap->pid == 0)
  136                 goto found;
  137 
  138         if ((pt = pfind(uap->pid)) == 0)
  139                 return ESRCH;
  140 found:
  141         p->p_retval[0] = pt->p_pgrp->pg_id;
  142         return 0;
  143 }
  144 
  145 /*
  146  * Get an arbitary pid's session id.
  147  */
  148 #ifndef _SYS_SYSPROTO_H_
  149 struct getsid_args {
  150         pid_t   pid;
  151 };
  152 #endif
  153 
  154 int
  155 getsid(p, uap)
  156         struct proc *p;
  157         struct getsid_args *uap;
  158 {
  159         struct proc *pt;
  160 
  161         pt = p;
  162         if (uap->pid == 0)
  163                 goto found;
  164 
  165         if ((pt = pfind(uap->pid)) == 0)
  166                 return ESRCH;
  167 found:
  168         p->p_retval[0] = pt->p_session->s_sid;
  169         return 0;
  170 }
  171 
  172 
  173 /*
  174  * getuid() - MP SAFE
  175  */
  176 #ifndef _SYS_SYSPROTO_H_
  177 struct getuid_args {
  178         int     dummy;
  179 };
  180 #endif
  181 
  182 /* ARGSUSED */
  183 int
  184 getuid(p, uap)
  185         struct proc *p;
  186         struct getuid_args *uap;
  187 {
  188 
  189         p->p_retval[0] = p->p_cred->p_ruid;
  190 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
  191         p->p_retval[1] = p->p_ucred->cr_uid;
  192 #endif
  193         return (0);
  194 }
  195 
  196 /*
  197  * geteuid() - MP SAFE
  198  */
  199 #ifndef _SYS_SYSPROTO_H_
  200 struct geteuid_args {
  201         int     dummy;
  202 };
  203 #endif
  204 
  205 /* ARGSUSED */
  206 int
  207 geteuid(p, uap)
  208         struct proc *p;
  209         struct geteuid_args *uap;
  210 {
  211 
  212         p->p_retval[0] = p->p_ucred->cr_uid;
  213         return (0);
  214 }
  215 
  216 /*
  217  * getgid() - MP SAFE
  218  */
  219 #ifndef _SYS_SYSPROTO_H_
  220 struct getgid_args {
  221         int     dummy;
  222 };
  223 #endif
  224 
  225 /* ARGSUSED */
  226 int
  227 getgid(p, uap)
  228         struct proc *p;
  229         struct getgid_args *uap;
  230 {
  231 
  232         p->p_retval[0] = p->p_cred->p_rgid;
  233 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
  234         p->p_retval[1] = p->p_ucred->cr_groups[0];
  235 #endif
  236         return (0);
  237 }
  238 
  239 /*
  240  * Get effective group ID.  The "egid" is groups[0], and could be obtained
  241  * via getgroups.  This syscall exists because it is somewhat painful to do
  242  * correctly in a library function.
  243  */
  244 #ifndef _SYS_SYSPROTO_H_
  245 struct getegid_args {
  246         int     dummy;
  247 };
  248 #endif
  249 
  250 /* ARGSUSED */
  251 int
  252 getegid(p, uap)
  253         struct proc *p;
  254         struct getegid_args *uap;
  255 {
  256 
  257         p->p_retval[0] = p->p_ucred->cr_groups[0];
  258         return (0);
  259 }
  260 
  261 #ifndef _SYS_SYSPROTO_H_
  262 struct getgroups_args {
  263         u_int   gidsetsize;
  264         gid_t   *gidset;
  265 };
  266 #endif
  267 int
  268 getgroups(p, uap)
  269         struct proc *p;
  270         register struct getgroups_args *uap;
  271 {
  272         register struct pcred *pc = p->p_cred;
  273         register u_int ngrp;
  274         int error;
  275 
  276         if ((ngrp = uap->gidsetsize) == 0) {
  277                 p->p_retval[0] = pc->pc_ucred->cr_ngroups;
  278                 return (0);
  279         }
  280         if (ngrp < pc->pc_ucred->cr_ngroups)
  281                 return (EINVAL);
  282         ngrp = pc->pc_ucred->cr_ngroups;
  283         if ((error = copyout((caddr_t)pc->pc_ucred->cr_groups,
  284             (caddr_t)uap->gidset, ngrp * sizeof(gid_t))))
  285                 return (error);
  286         p->p_retval[0] = ngrp;
  287         return (0);
  288 }
  289 
  290 #ifndef _SYS_SYSPROTO_H_
  291 struct setsid_args {
  292         int     dummy;
  293 };
  294 #endif
  295 
  296 /* ARGSUSED */
  297 int
  298 setsid(p, uap)
  299         register struct proc *p;
  300         struct setsid_args *uap;
  301 {
  302 
  303         if (p->p_pgid == p->p_pid || pgfind(p->p_pid)) {
  304                 return (EPERM);
  305         } else {
  306                 (void)enterpgrp(p, p->p_pid, 1);
  307                 p->p_retval[0] = p->p_pid;
  308                 return (0);
  309         }
  310 }
  311 
  312 /*
  313  * set process group (setpgid/old setpgrp)
  314  *
  315  * caller does setpgid(targpid, targpgid)
  316  *
  317  * pid must be caller or child of caller (ESRCH)
  318  * if a child
  319  *      pid must be in same session (EPERM)
  320  *      pid can't have done an exec (EACCES)
  321  * if pgid != pid
  322  *      there must exist some pid in same session having pgid (EPERM)
  323  * pid must not be session leader (EPERM)
  324  */
  325 #ifndef _SYS_SYSPROTO_H_
  326 struct setpgid_args {
  327         int     pid;    /* target process id */
  328         int     pgid;   /* target pgrp id */
  329 };
  330 #endif
  331 /* ARGSUSED */
  332 int
  333 setpgid(curp, uap)
  334         struct proc *curp;
  335         register struct setpgid_args *uap;
  336 {
  337         register struct proc *targp;            /* target process */
  338         register struct pgrp *pgrp;             /* target pgrp */
  339 
  340         if (uap->pgid < 0)
  341                 return (EINVAL);
  342         if (uap->pid != 0 && uap->pid != curp->p_pid) {
  343                 if ((targp = pfind(uap->pid)) == 0 || !inferior(targp))
  344                         return (ESRCH);
  345                 if (targp->p_pgrp == NULL ||  targp->p_session != curp->p_session)
  346                         return (EPERM);
  347                 if (targp->p_flag & P_EXEC)
  348                         return (EACCES);
  349         } else
  350                 targp = curp;
  351         if (SESS_LEADER(targp))
  352                 return (EPERM);
  353         if (uap->pgid == 0)
  354                 uap->pgid = targp->p_pid;
  355         else if (uap->pgid != targp->p_pid)
  356                 if ((pgrp = pgfind(uap->pgid)) == 0 ||
  357                     pgrp->pg_session != curp->p_session)
  358                         return (EPERM);
  359         return (enterpgrp(targp, uap->pgid, 0));
  360 }
  361 
  362 /*
  363  * Use the clause in B.4.2.2 that allows setuid/setgid to be 4.2/4.3BSD
  364  * compatable.  It says that setting the uid/gid to euid/egid is a special
  365  * case of "appropriate privilege".  Once the rules are expanded out, this
  366  * basically means that setuid(nnn) sets all three id's, in all permitted
  367  * cases unless _POSIX_SAVED_IDS is enabled.  In that case, setuid(getuid())
  368  * does not set the saved id - this is dangerous for traditional BSD
  369  * programs.  For this reason, we *really* do not want to set
  370  * _POSIX_SAVED_IDS and do not want to clear POSIX_APPENDIX_B_4_2_2.
  371  */
  372 #define POSIX_APPENDIX_B_4_2_2
  373 
  374 #ifndef _SYS_SYSPROTO_H_
  375 struct setuid_args {
  376         uid_t   uid;
  377 };
  378 #endif
  379 /* ARGSUSED */
  380 int
  381 setuid(p, uap)
  382         struct proc *p;
  383         struct setuid_args *uap;
  384 {
  385         register struct pcred *pc = p->p_cred;
  386         register uid_t uid;
  387         int error;
  388 
  389         /*
  390          * See if we have "permission" by POSIX 1003.1 rules.
  391          *
  392          * Note that setuid(geteuid()) is a special case of 
  393          * "appropriate privileges" in appendix B.4.2.2.  We need
  394          * to use this clause to be compatable with traditional BSD
  395          * semantics.  Basically, it means that "setuid(xx)" sets all
  396          * three id's (assuming you have privs).
  397          *
  398          * Notes on the logic.  We do things in three steps.
  399          * 1: We determine if the euid is going to change, and do EPERM
  400          *    right away.  We unconditionally change the euid later if this
  401          *    test is satisfied, simplifying that part of the logic.
  402          * 2: We determine if the real and/or saved uid's are going to
  403          *    change.  Determined by compile options.
  404          * 3: Change euid last. (after tests in #2 for "appropriate privs")
  405          */
  406         uid = uap->uid;
  407         if (uid != pc->p_ruid &&                /* allow setuid(getuid()) */
  408 #ifdef _POSIX_SAVED_IDS
  409             uid != pc->p_svuid &&               /* allow setuid(saved gid) */
  410 #endif
  411 #ifdef POSIX_APPENDIX_B_4_2_2   /* Use BSD-compat clause from B.4.2.2 */
  412             uid != pc->pc_ucred->cr_uid &&      /* allow setuid(geteuid()) */
  413 #endif
  414             (error = suser_xxx(0, p, PRISON_ROOT)))
  415                 return (error);
  416 
  417 #ifdef _POSIX_SAVED_IDS
  418         /*
  419          * Do we have "appropriate privileges" (are we root or uid == euid)
  420          * If so, we are changing the real uid and/or saved uid.
  421          */
  422         if (
  423 #ifdef POSIX_APPENDIX_B_4_2_2   /* Use the clause from B.4.2.2 */
  424             uid == pc->pc_ucred->cr_uid ||
  425 #endif
  426             suser_xxx(0, p, PRISON_ROOT) == 0) /* we are using privs */
  427 #endif
  428         {
  429                 /*
  430                  * Set the real uid and transfer proc count to new user.
  431                  */
  432                 if (uid != pc->p_ruid) {
  433                         change_ruid(p, uid);
  434                         setsugid(p);
  435                 }
  436                 /*
  437                  * Set saved uid
  438                  *
  439                  * XXX always set saved uid even if not _POSIX_SAVED_IDS, as
  440                  * the security of seteuid() depends on it.  B.4.2.2 says it
  441                  * is important that we should do this.
  442                  */
  443                 if (pc->p_svuid != uid) {
  444                         pc->p_svuid = uid;
  445                         setsugid(p);
  446                 }
  447         }
  448 
  449         /*
  450          * In all permitted cases, we are changing the euid.
  451          * Copy credentials so other references do not see our changes.
  452          */
  453         if (pc->pc_ucred->cr_uid != uid) {
  454                 change_euid(p, uid);
  455                 setsugid(p);
  456         }
  457         return (0);
  458 }
  459 
  460 #ifndef _SYS_SYSPROTO_H_
  461 struct seteuid_args {
  462         uid_t   euid;
  463 };
  464 #endif
  465 /* ARGSUSED */
  466 int
  467 seteuid(p, uap)
  468         struct proc *p;
  469         struct seteuid_args *uap;
  470 {
  471         register struct pcred *pc = p->p_cred;
  472         register uid_t euid;
  473         int error;
  474 
  475         euid = uap->euid;
  476         if (euid != pc->p_ruid &&               /* allow seteuid(getuid()) */
  477             euid != pc->p_svuid &&              /* allow seteuid(saved uid) */
  478             (error = suser_xxx(0, p, PRISON_ROOT)))
  479                 return (error);
  480         /*
  481          * Everything's okay, do it.  Copy credentials so other references do
  482          * not see our changes.
  483          */
  484         if (pc->pc_ucred->cr_uid != euid) {
  485                 change_euid(p, euid);
  486                 setsugid(p);
  487         }
  488         return (0);
  489 }
  490 
  491 #ifndef _SYS_SYSPROTO_H_
  492 struct setgid_args {
  493         gid_t   gid;
  494 };
  495 #endif
  496 /* ARGSUSED */
  497 int
  498 setgid(p, uap)
  499         struct proc *p;
  500         struct setgid_args *uap;
  501 {
  502         register struct pcred *pc = p->p_cred;
  503         register gid_t gid;
  504         int error;
  505 
  506         /*
  507          * See if we have "permission" by POSIX 1003.1 rules.
  508          *
  509          * Note that setgid(getegid()) is a special case of
  510          * "appropriate privileges" in appendix B.4.2.2.  We need
  511          * to use this clause to be compatable with traditional BSD
  512          * semantics.  Basically, it means that "setgid(xx)" sets all
  513          * three id's (assuming you have privs).
  514          *
  515          * For notes on the logic here, see setuid() above.
  516          */
  517         gid = uap->gid;
  518         if (gid != pc->p_rgid &&                /* allow setgid(getgid()) */
  519 #ifdef _POSIX_SAVED_IDS
  520             gid != pc->p_svgid &&               /* allow setgid(saved gid) */
  521 #endif
  522 #ifdef POSIX_APPENDIX_B_4_2_2   /* Use BSD-compat clause from B.4.2.2 */
  523             gid != pc->pc_ucred->cr_groups[0] && /* allow setgid(getegid()) */
  524 #endif
  525             (error = suser_xxx(0, p, PRISON_ROOT)))
  526                 return (error);
  527 
  528 #ifdef _POSIX_SAVED_IDS
  529         /*
  530          * Do we have "appropriate privileges" (are we root or gid == egid)
  531          * If so, we are changing the real uid and saved gid.
  532          */
  533         if (
  534 #ifdef POSIX_APPENDIX_B_4_2_2   /* use the clause from B.4.2.2 */
  535             gid == pc->pc_ucred->cr_groups[0] ||
  536 #endif
  537             suser_xxx(0, p, PRISON_ROOT) == 0) /* we are using privs */
  538 #endif
  539         {
  540                 /*
  541                  * Set real gid
  542                  */
  543                 if (pc->p_rgid != gid) {
  544                         pc->p_rgid = gid;
  545                         setsugid(p);
  546                 }
  547                 /*
  548                  * Set saved gid
  549                  *
  550                  * XXX always set saved gid even if not _POSIX_SAVED_IDS, as
  551                  * the security of setegid() depends on it.  B.4.2.2 says it
  552                  * is important that we should do this.
  553                  */
  554                 if (pc->p_svgid != gid) {
  555                         pc->p_svgid = gid;
  556                         setsugid(p);
  557                 }
  558         }
  559         /*
  560          * In all cases permitted cases, we are changing the egid.
  561          * Copy credentials so other references do not see our changes.
  562          */
  563         if (pc->pc_ucred->cr_groups[0] != gid) {
  564                 pc->pc_ucred = crcopy(pc->pc_ucred);
  565                 pc->pc_ucred->cr_groups[0] = gid;
  566                 setsugid(p);
  567         }
  568         return (0);
  569 }
  570 
  571 #ifndef _SYS_SYSPROTO_H_
  572 struct setegid_args {
  573         gid_t   egid;
  574 };
  575 #endif
  576 /* ARGSUSED */
  577 int
  578 setegid(p, uap)
  579         struct proc *p;
  580         struct setegid_args *uap;
  581 {
  582         register struct pcred *pc = p->p_cred;
  583         register gid_t egid;
  584         int error;
  585 
  586         egid = uap->egid;
  587         if (egid != pc->p_rgid &&               /* allow setegid(getgid()) */
  588             egid != pc->p_svgid &&              /* allow setegid(saved gid) */
  589             (error = suser_xxx(0, p, PRISON_ROOT)))
  590                 return (error);
  591         if (pc->pc_ucred->cr_groups[0] != egid) {
  592                 pc->pc_ucred = crcopy(pc->pc_ucred);
  593                 pc->pc_ucred->cr_groups[0] = egid;
  594                 setsugid(p);
  595         }
  596         return (0);
  597 }
  598 
  599 #ifndef _SYS_SYSPROTO_H_
  600 struct setgroups_args {
  601         u_int   gidsetsize;
  602         gid_t   *gidset;
  603 };
  604 #endif
  605 /* ARGSUSED */
  606 int
  607 setgroups(p, uap)
  608         struct proc *p;
  609         struct setgroups_args *uap;
  610 {
  611         register struct pcred *pc = p->p_cred;
  612         register u_int ngrp;
  613         int error;
  614 
  615         if ((error = suser_xxx(0, p, PRISON_ROOT)))
  616                 return (error);
  617         ngrp = uap->gidsetsize;
  618         if (ngrp > NGROUPS)
  619                 return (EINVAL);
  620         /*
  621          * XXX A little bit lazy here.  We could test if anything has
  622          * changed before crcopy() and setting P_SUGID.
  623          */
  624         pc->pc_ucred = crcopy(pc->pc_ucred);
  625         if (ngrp < 1) {
  626                 /*
  627                  * setgroups(0, NULL) is a legitimate way of clearing the
  628                  * groups vector on non-BSD systems (which generally do not
  629                  * have the egid in the groups[0]).  We risk security holes
  630                  * when running non-BSD software if we do not do the same.
  631                  */
  632                 pc->pc_ucred->cr_ngroups = 1;
  633         } else {
  634                 if ((error = copyin((caddr_t)uap->gidset,
  635                     (caddr_t)pc->pc_ucred->cr_groups, ngrp * sizeof(gid_t))))
  636                         return (error);
  637                 pc->pc_ucred->cr_ngroups = ngrp;
  638         }
  639         setsugid(p);
  640         return (0);
  641 }
  642 
  643 #ifndef _SYS_SYSPROTO_H_
  644 struct setreuid_args {
  645         uid_t   ruid;
  646         uid_t   euid;
  647 };
  648 #endif
  649 /* ARGSUSED */
  650 int
  651 setreuid(p, uap)
  652         register struct proc *p;
  653         struct setreuid_args *uap;
  654 {
  655         register struct pcred *pc = p->p_cred;
  656         register uid_t ruid, euid;
  657         int error;
  658 
  659         ruid = uap->ruid;
  660         euid = uap->euid;
  661         if (((ruid != (uid_t)-1 && ruid != pc->p_ruid && ruid != pc->p_svuid) ||
  662              (euid != (uid_t)-1 && euid != pc->pc_ucred->cr_uid &&
  663              euid != pc->p_ruid && euid != pc->p_svuid)) &&
  664             (error = suser_xxx(0, p, PRISON_ROOT)) != 0)
  665                 return (error);
  666 
  667         if (euid != (uid_t)-1 && pc->pc_ucred->cr_uid != euid) {
  668                 change_euid(p, euid);
  669                 setsugid(p);
  670         }
  671         if (ruid != (uid_t)-1 && pc->p_ruid != ruid) {
  672                 change_ruid(p, ruid);
  673                 setsugid(p);
  674         }
  675         if ((ruid != (uid_t)-1 || pc->pc_ucred->cr_uid != pc->p_ruid) &&
  676             pc->p_svuid != pc->pc_ucred->cr_uid) {
  677                 pc->p_svuid = pc->pc_ucred->cr_uid;
  678                 setsugid(p);
  679         }
  680         return (0);
  681 }
  682 
  683 #ifndef _SYS_SYSPROTO_H_
  684 struct setregid_args {
  685         gid_t   rgid;
  686         gid_t   egid;
  687 };
  688 #endif
  689 /* ARGSUSED */
  690 int
  691 setregid(p, uap)
  692         register struct proc *p;
  693         struct setregid_args *uap;
  694 {
  695         register struct pcred *pc = p->p_cred;
  696         register gid_t rgid, egid;
  697         int error;
  698 
  699         rgid = uap->rgid;
  700         egid = uap->egid;
  701         if (((rgid != (gid_t)-1 && rgid != pc->p_rgid && rgid != pc->p_svgid) ||
  702              (egid != (gid_t)-1 && egid != pc->pc_ucred->cr_groups[0] &&
  703              egid != pc->p_rgid && egid != pc->p_svgid)) &&
  704             (error = suser_xxx(0, p, PRISON_ROOT)) != 0)
  705                 return (error);
  706 
  707         if (egid != (gid_t)-1 && pc->pc_ucred->cr_groups[0] != egid) {
  708                 pc->pc_ucred = crcopy(pc->pc_ucred);
  709                 pc->pc_ucred->cr_groups[0] = egid;
  710                 setsugid(p);
  711         }
  712         if (rgid != (gid_t)-1 && pc->p_rgid != rgid) {
  713                 pc->p_rgid = rgid;
  714                 setsugid(p);
  715         }
  716         if ((rgid != (gid_t)-1 || pc->pc_ucred->cr_groups[0] != pc->p_rgid) &&
  717             pc->p_svgid != pc->pc_ucred->cr_groups[0]) {
  718                 pc->p_svgid = pc->pc_ucred->cr_groups[0];
  719                 setsugid(p);
  720         }
  721         return (0);
  722 }
  723 
  724 /*
  725  * setresuid(ruid, euid, suid) is like setreuid except control over the
  726  * saved uid is explicit.
  727  */
  728 
  729 #ifndef _SYS_SYSPROTO_H_
  730 struct setresuid_args {
  731         uid_t   ruid;
  732         uid_t   euid;
  733         uid_t   suid;
  734 };
  735 #endif
  736 /* ARGSUSED */
  737 int
  738 setresuid(p, uap)
  739         register struct proc *p;
  740         struct setresuid_args *uap;
  741 {
  742         register struct pcred *pc = p->p_cred;
  743         register uid_t ruid, euid, suid;
  744         int error;
  745 
  746         ruid = uap->ruid;
  747         euid = uap->euid;
  748         suid = uap->suid;
  749         if (((ruid != (uid_t)-1 && ruid != pc->p_ruid && ruid != pc->p_svuid &&
  750               ruid != pc->pc_ucred->cr_uid) ||
  751              (euid != (uid_t)-1 && euid != pc->p_ruid && euid != pc->p_svuid &&
  752               euid != pc->pc_ucred->cr_uid) ||
  753              (suid != (uid_t)-1 && suid != pc->p_ruid && suid != pc->p_svuid &&
  754               suid != pc->pc_ucred->cr_uid)) &&
  755             (error = suser_xxx(0, p, PRISON_ROOT)) != 0)
  756                 return (error);
  757         if (euid != (uid_t)-1 && pc->pc_ucred->cr_uid != euid) {
  758                 change_euid(p, euid);
  759                 setsugid(p);
  760         }
  761         if (ruid != (uid_t)-1 && pc->p_ruid != ruid) {
  762                 change_ruid(p, ruid);
  763                 setsugid(p);
  764         }
  765         if (suid != (uid_t)-1 && pc->p_svuid != suid) {
  766                 pc->p_svuid = suid;
  767                 setsugid(p);
  768         }
  769         return (0);
  770 }
  771 
  772 /*
  773  * setresgid(rgid, egid, sgid) is like setregid except control over the
  774  * saved gid is explicit.
  775  */
  776 
  777 #ifndef _SYS_SYSPROTO_H_
  778 struct setresgid_args {
  779         gid_t   rgid;
  780         gid_t   egid;
  781         gid_t   sgid;
  782 };
  783 #endif
  784 /* ARGSUSED */
  785 int
  786 setresgid(p, uap)
  787         register struct proc *p;
  788         struct setresgid_args *uap;
  789 {
  790         register struct pcred *pc = p->p_cred;
  791         register gid_t rgid, egid, sgid;
  792         int error;
  793 
  794         rgid = uap->rgid;
  795         egid = uap->egid;
  796         sgid = uap->sgid;
  797         if (((rgid != (gid_t)-1 && rgid != pc->p_rgid && rgid != pc->p_svgid &&
  798               rgid != pc->pc_ucred->cr_groups[0]) ||
  799              (egid != (gid_t)-1 && egid != pc->p_rgid && egid != pc->p_svgid &&
  800               egid != pc->pc_ucred->cr_groups[0]) ||
  801              (sgid != (gid_t)-1 && sgid != pc->p_rgid && sgid != pc->p_svgid &&
  802               sgid != pc->pc_ucred->cr_groups[0])) &&
  803             (error = suser_xxx(0, p, PRISON_ROOT)) != 0)
  804                 return (error);
  805 
  806         if (egid != (gid_t)-1 && pc->pc_ucred->cr_groups[0] != egid) {
  807                 pc->pc_ucred = crcopy(pc->pc_ucred);
  808                 pc->pc_ucred->cr_groups[0] = egid;
  809                 setsugid(p);
  810         }
  811         if (rgid != (gid_t)-1 && pc->p_rgid != rgid) {
  812                 pc->p_rgid = rgid;
  813                 setsugid(p);
  814         }
  815         if (sgid != (gid_t)-1 && pc->p_svgid != sgid) {
  816                 pc->p_svgid = sgid;
  817                 setsugid(p);
  818         }
  819         return (0);
  820 }
  821 
  822 #ifndef _SYS_SYSPROTO_H_
  823 struct getresuid_args {
  824         uid_t   *ruid;
  825         uid_t   *euid;
  826         uid_t   *suid;
  827 };
  828 #endif
  829 /* ARGSUSED */
  830 int
  831 getresuid(p, uap)
  832         register struct proc *p;
  833         struct getresuid_args *uap;
  834 {
  835         struct pcred *pc = p->p_cred;
  836         int error1 = 0, error2 = 0, error3 = 0;
  837 
  838         if (uap->ruid)
  839                 error1 = copyout((caddr_t)&pc->p_ruid,
  840                     (caddr_t)uap->ruid, sizeof(pc->p_ruid));
  841         if (uap->euid)
  842                 error2 = copyout((caddr_t)&pc->pc_ucred->cr_uid,
  843                     (caddr_t)uap->euid, sizeof(pc->pc_ucred->cr_uid));
  844         if (uap->suid)
  845                 error3 = copyout((caddr_t)&pc->p_svuid,
  846                     (caddr_t)uap->suid, sizeof(pc->p_svuid));
  847         return error1 ? error1 : (error2 ? error2 : error3);
  848 }
  849 
  850 #ifndef _SYS_SYSPROTO_H_
  851 struct getresgid_args {
  852         gid_t   *rgid;
  853         gid_t   *egid;
  854         gid_t   *sgid;
  855 };
  856 #endif
  857 /* ARGSUSED */
  858 int
  859 getresgid(p, uap)
  860         register struct proc *p;
  861         struct getresgid_args *uap;
  862 {
  863         struct pcred *pc = p->p_cred;
  864         int error1 = 0, error2 = 0, error3 = 0;
  865 
  866         if (uap->rgid)
  867                 error1 = copyout((caddr_t)&pc->p_rgid,
  868                     (caddr_t)uap->rgid, sizeof(pc->p_rgid));
  869         if (uap->egid)
  870                 error2 = copyout((caddr_t)&pc->pc_ucred->cr_groups[0],
  871                     (caddr_t)uap->egid, sizeof(pc->pc_ucred->cr_groups[0]));
  872         if (uap->sgid)
  873                 error3 = copyout((caddr_t)&pc->p_svgid,
  874                     (caddr_t)uap->sgid, sizeof(pc->p_svgid));
  875         return error1 ? error1 : (error2 ? error2 : error3);
  876 }
  877 
  878 
  879 #ifndef _SYS_SYSPROTO_H_
  880 struct issetugid_args {
  881         int dummy;
  882 };
  883 #endif
  884 /* ARGSUSED */
  885 int
  886 issetugid(p, uap)
  887         register struct proc *p;
  888         struct issetugid_args *uap;
  889 {
  890         /*
  891          * Note: OpenBSD sets a P_SUGIDEXEC flag set at execve() time,
  892          * we use P_SUGID because we consider changing the owners as
  893          * "tainting" as well.
  894          * This is significant for procs that start as root and "become"
  895          * a user without an exec - programs cannot know *everything*
  896          * that libc *might* have put in their data segment.
  897          */
  898         p->p_retval[0] = (p->p_flag & P_SUGID) ? 1 : 0;
  899         return (0);
  900 }
  901 
  902 /*
  903  * Check if gid is a member of the group set.
  904  */
  905 int
  906 groupmember(gid, cred)
  907         gid_t gid;
  908         register struct ucred *cred;
  909 {
  910         register gid_t *gp;
  911         gid_t *egp;
  912 
  913         egp = &(cred->cr_groups[cred->cr_ngroups]);
  914         for (gp = cred->cr_groups; gp < egp; gp++)
  915                 if (*gp == gid)
  916                         return (1);
  917         return (0);
  918 }
  919 
  920 /*
  921  * Test whether the specified credentials imply "super-user"
  922  * privilege; if so, and we have accounting info, set the flag
  923  * indicating use of super-powers.
  924  * Returns 0 or error.
  925  */
  926 int
  927 suser(p)
  928         struct proc *p;
  929 {
  930         return suser_xxx(0, p, 0);
  931 }
  932 
  933 int
  934 suser_xxx(cred, proc, flag)
  935         struct ucred *cred;
  936         struct proc *proc;
  937         int flag;
  938 {
  939         if (!cred && !proc) {
  940                 printf("suser_xxx(): THINK!\n");
  941                 return (EPERM);
  942         }
  943         if (!cred) 
  944                 cred = proc->p_ucred;
  945         if (cred->cr_uid != 0) 
  946                 return (EPERM);
  947         if (proc && proc->p_prison && !(flag & PRISON_ROOT))
  948                 return (EPERM);
  949         if (proc)
  950                 proc->p_acflag |= ASU;
  951         return (0);
  952 }
  953 
  954 /*
  955  * Return zero if p1 can fondle p2, return errno (EPERM/ESRCH) otherwise.
  956  */
  957 
  958 int
  959 p_trespass(struct proc *p1, struct proc *p2)
  960 {
  961 
  962         if (p1 == p2)
  963                 return (0);
  964         if (!PRISON_CHECK(p1, p2))
  965                 return (ESRCH);
  966         if (p1->p_cred->p_ruid == p2->p_cred->p_ruid)
  967                 return (0);
  968         if (p1->p_ucred->cr_uid == p2->p_cred->p_ruid)
  969                 return (0);
  970         if (p1->p_cred->p_ruid == p2->p_ucred->cr_uid)
  971                 return (0);
  972         if (p1->p_ucred->cr_uid == p2->p_ucred->cr_uid)
  973                 return (0);
  974         if (!suser_xxx(0, p1, PRISON_ROOT))
  975                 return (0);
  976         return (EPERM);
  977 }
  978 
  979 /*
  980  * Allocate a zeroed cred structure.
  981  */
  982 struct ucred *
  983 crget()
  984 {
  985         register struct ucred *cr;
  986 
  987         MALLOC(cr, struct ucred *, sizeof(*cr), M_CRED, M_WAITOK);
  988         bzero((caddr_t)cr, sizeof(*cr));
  989         cr->cr_ref = 1;
  990         return (cr);
  991 }
  992 
  993 /*
  994  * Claim another reference to a ucred structure
  995  */
  996 void
  997 crhold(cr) 
  998         struct ucred *cr;
  999 {
 1000         cr->cr_ref++;
 1001 }
 1002 
 1003 /*
 1004  * Free a cred structure.
 1005  * Throws away space when ref count gets to 0.
 1006  */
 1007 void
 1008 crfree(cr)
 1009         struct ucred *cr;
 1010 {
 1011         int s;
 1012 
 1013         s = splhigh();
 1014         if (cr->cr_ref == 0)
 1015                 panic("Freeing already free credential! %p", cr);
 1016         
 1017         if (--cr->cr_ref == 0) {
 1018                 /*
 1019                  * Some callers of crget(), such as nfs_statfs(),
 1020                  * allocate a temporary credential, but don't
 1021                  * allocate a uidinfo structure.
 1022                  */
 1023                 if (cr->cr_uidinfo != NULL)
 1024                         uifree(cr->cr_uidinfo);
 1025                 FREE((caddr_t)cr, M_CRED);
 1026         }
 1027         splx(s);
 1028 }
 1029 
 1030 /*
 1031  * Copy cred structure to a new one and free the old one.
 1032  */
 1033 struct ucred *
 1034 crcopy(cr)
 1035         struct ucred *cr;
 1036 {
 1037         struct ucred *newcr;
 1038 
 1039         if (cr->cr_ref == 1)
 1040                 return (cr);
 1041         newcr = crget();
 1042         *newcr = *cr;
 1043         uihold(newcr->cr_uidinfo);
 1044         crfree(cr);
 1045         newcr->cr_ref = 1;
 1046         return (newcr);
 1047 }
 1048 
 1049 /*
 1050  * Dup cred struct to a new held one.
 1051  */
 1052 struct ucred *
 1053 crdup(cr)
 1054         struct ucred *cr;
 1055 {
 1056         struct ucred *newcr;
 1057 
 1058         newcr = crget();
 1059         *newcr = *cr;
 1060         uihold(newcr->cr_uidinfo);
 1061         newcr->cr_ref = 1;
 1062         return (newcr);
 1063 }
 1064 
 1065 /*
 1066  * Fill in a struct xucred based on a struct ucred.
 1067  */
 1068 void
 1069 cru2x(cr, xcr)
 1070         struct ucred *cr;
 1071         struct xucred *xcr;
 1072 {
 1073 
 1074         bzero(xcr, sizeof(*xcr));
 1075         xcr->cr_version = XUCRED_VERSION;
 1076         xcr->cr_uid = cr->cr_uid;
 1077         xcr->cr_ngroups = cr->cr_ngroups;
 1078         bcopy(cr->cr_groups, xcr->cr_groups, sizeof(cr->cr_groups));
 1079 }
 1080 
 1081 /*
 1082  * Get login name, if available.
 1083  */
 1084 #ifndef _SYS_SYSPROTO_H_
 1085 struct getlogin_args {
 1086         char    *namebuf;
 1087         u_int   namelen;
 1088 };
 1089 #endif
 1090 /* ARGSUSED */
 1091 int
 1092 getlogin(p, uap)
 1093         struct proc *p;
 1094         struct getlogin_args *uap;
 1095 {
 1096 
 1097         if (uap->namelen > MAXLOGNAME)
 1098                 uap->namelen = MAXLOGNAME;
 1099         return (copyout((caddr_t) p->p_pgrp->pg_session->s_login,
 1100             (caddr_t) uap->namebuf, uap->namelen));
 1101 }
 1102 
 1103 /*
 1104  * Set login name.
 1105  */
 1106 #ifndef _SYS_SYSPROTO_H_
 1107 struct setlogin_args {
 1108         char    *namebuf;
 1109 };
 1110 #endif
 1111 /* ARGSUSED */
 1112 int
 1113 setlogin(p, uap)
 1114         struct proc *p;
 1115         struct setlogin_args *uap;
 1116 {
 1117         int error;
 1118         char logintmp[MAXLOGNAME];
 1119 
 1120         if ((error = suser_xxx(0, p, PRISON_ROOT)))
 1121                 return (error);
 1122         error = copyinstr((caddr_t) uap->namebuf, (caddr_t) logintmp,
 1123             sizeof(logintmp), (size_t *)0);
 1124         if (error == ENAMETOOLONG)
 1125                 error = EINVAL;
 1126         else if (!error)
 1127                 (void) memcpy(p->p_pgrp->pg_session->s_login, logintmp,
 1128                     sizeof(logintmp));
 1129         return (error);
 1130 }
 1131 
 1132 void
 1133 setsugid(p)
 1134         struct proc *p;
 1135 {
 1136         p->p_flag |= P_SUGID;
 1137         if (!(p->p_pfsflags & PF_ISUGID))
 1138                 p->p_stops = 0;
 1139 }
 1140 
 1141 /*
 1142  * Helper function to change the effective uid of a process
 1143  */
 1144 void
 1145 change_euid(p, euid)
 1146         struct  proc *p;
 1147         uid_t   euid;
 1148 {
 1149         struct  pcred *pc;
 1150         struct  uidinfo *uip;
 1151 
 1152         pc = p->p_cred;
 1153         /*
 1154          * crcopy is essentially a NOP if ucred has a reference count
 1155          * of 1, which is true if it has already been copied.
 1156          */
 1157         pc->pc_ucred = crcopy(pc->pc_ucred);
 1158         uip = pc->pc_ucred->cr_uidinfo;
 1159         pc->pc_ucred->cr_uid = euid;
 1160         pc->pc_ucred->cr_uidinfo = uifind(euid);
 1161         uifree(uip);
 1162 }
 1163 
 1164 /*
 1165  * Helper function to change the real uid of a process
 1166  *
 1167  * The per-uid process count for this process is transfered from
 1168  * the old uid to the new uid.
 1169  */
 1170 void
 1171 change_ruid(p, ruid)
 1172         struct  proc *p;
 1173         uid_t   ruid;
 1174 {
 1175         struct  pcred *pc;
 1176         struct  uidinfo *uip;
 1177 
 1178         pc = p->p_cred;
 1179         (void)chgproccnt(pc->p_uidinfo, -1, 0);
 1180         uip = pc->p_uidinfo;
 1181         /* It is assumed that pcred is not shared between processes */
 1182         pc->p_ruid = ruid;
 1183         pc->p_uidinfo = uifind(ruid);
 1184         (void)chgproccnt(pc->p_uidinfo, 1, 0);
 1185         uifree(uip);
 1186 }

Cache object: 57b29e8f5b0c94f584dfce5dd6f10815


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