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/unistd.h>
   56 #include <sys/pioctl.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 /* ARGSUSED */
   67 int
   68 getpid(p, uap)
   69         struct proc *p;
   70         struct getpid_args *uap;
   71 {
   72 
   73         p->p_retval[0] = p->p_pid;
   74 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
   75         p->p_retval[1] = p->p_pptr->p_pid;
   76 #endif
   77         return (0);
   78 }
   79 
   80 #ifndef _SYS_SYSPROTO_H_
   81 struct getppid_args {
   82         int     dummy;
   83 };
   84 #endif
   85 /* ARGSUSED */
   86 int
   87 getppid(p, uap)
   88         struct proc *p;
   89         struct getppid_args *uap;
   90 {
   91 
   92         p->p_retval[0] = p->p_pptr->p_pid;
   93         return (0);
   94 }
   95 
   96 /* Get process group ID; note that POSIX getpgrp takes no parameter */
   97 #ifndef _SYS_SYSPROTO_H_
   98 struct getpgrp_args {
   99         int     dummy;
  100 };
  101 #endif
  102 
  103 int
  104 getpgrp(p, uap)
  105         struct proc *p;
  106         struct getpgrp_args *uap;
  107 {
  108 
  109         p->p_retval[0] = p->p_pgrp->pg_id;
  110         return (0);
  111 }
  112 
  113 /* Get an arbitary pid's process group id */
  114 #ifndef _SYS_SYSPROTO_H_
  115 struct getpgid_args {
  116         pid_t   pid;
  117 };
  118 #endif
  119 
  120 int
  121 getpgid(p, uap)
  122         struct proc *p;
  123         struct getpgid_args *uap;
  124 {
  125         struct proc *pt;
  126 
  127         pt = p;
  128         if (uap->pid == 0)
  129                 goto found;
  130 
  131         if ((pt = pfind(uap->pid)) == 0)
  132                 return ESRCH;
  133 found:
  134         p->p_retval[0] = pt->p_pgrp->pg_id;
  135         return 0;
  136 }
  137 
  138 /*
  139  * Get an arbitary pid's session id.
  140  */
  141 #ifndef _SYS_SYSPROTO_H_
  142 struct getsid_args {
  143         pid_t   pid;
  144 };
  145 #endif
  146 
  147 int
  148 getsid(p, uap)
  149         struct proc *p;
  150         struct getsid_args *uap;
  151 {
  152         struct proc *pt;
  153 
  154         pt = p;
  155         if (uap->pid == 0)
  156                 goto found;
  157 
  158         if ((pt == pfind(uap->pid)) == 0)
  159                 return ESRCH;
  160 found:
  161         p->p_retval[0] = pt->p_session->s_sid;
  162         return 0;
  163 }
  164 
  165 
  166 #ifndef _SYS_SYSPROTO_H_
  167 struct getuid_args {
  168         int     dummy;
  169 };
  170 #endif
  171 
  172 /* ARGSUSED */
  173 int
  174 getuid(p, uap)
  175         struct proc *p;
  176         struct getuid_args *uap;
  177 {
  178 
  179         p->p_retval[0] = p->p_cred->p_ruid;
  180 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
  181         p->p_retval[1] = p->p_ucred->cr_uid;
  182 #endif
  183         return (0);
  184 }
  185 
  186 #ifndef _SYS_SYSPROTO_H_
  187 struct geteuid_args {
  188         int     dummy;
  189 };
  190 #endif
  191 
  192 /* ARGSUSED */
  193 int
  194 geteuid(p, uap)
  195         struct proc *p;
  196         struct geteuid_args *uap;
  197 {
  198 
  199         p->p_retval[0] = p->p_ucred->cr_uid;
  200         return (0);
  201 }
  202 
  203 #ifndef _SYS_SYSPROTO_H_
  204 struct getgid_args {
  205         int     dummy;
  206 };
  207 #endif
  208 
  209 /* ARGSUSED */
  210 int
  211 getgid(p, uap)
  212         struct proc *p;
  213         struct getgid_args *uap;
  214 {
  215 
  216         p->p_retval[0] = p->p_cred->p_rgid;
  217 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
  218         p->p_retval[1] = p->p_ucred->cr_groups[0];
  219 #endif
  220         return (0);
  221 }
  222 
  223 /*
  224  * Get effective group ID.  The "egid" is groups[0], and could be obtained
  225  * via getgroups.  This syscall exists because it is somewhat painful to do
  226  * correctly in a library function.
  227  */
  228 #ifndef _SYS_SYSPROTO_H_
  229 struct getegid_args {
  230         int     dummy;
  231 };
  232 #endif
  233 
  234 /* ARGSUSED */
  235 int
  236 getegid(p, uap)
  237         struct proc *p;
  238         struct getegid_args *uap;
  239 {
  240 
  241         p->p_retval[0] = p->p_ucred->cr_groups[0];
  242         return (0);
  243 }
  244 
  245 #ifndef _SYS_SYSPROTO_H_
  246 struct getgroups_args {
  247         u_int   gidsetsize;
  248         gid_t   *gidset;
  249 };
  250 #endif
  251 int
  252 getgroups(p, uap)
  253         struct proc *p;
  254         register struct getgroups_args *uap;
  255 {
  256         register struct pcred *pc = p->p_cred;
  257         register u_int ngrp;
  258         int error;
  259 
  260         if ((ngrp = uap->gidsetsize) == 0) {
  261                 p->p_retval[0] = pc->pc_ucred->cr_ngroups;
  262                 return (0);
  263         }
  264         if (ngrp < pc->pc_ucred->cr_ngroups)
  265                 return (EINVAL);
  266         ngrp = pc->pc_ucred->cr_ngroups;
  267         if ((error = copyout((caddr_t)pc->pc_ucred->cr_groups,
  268             (caddr_t)uap->gidset, ngrp * sizeof(gid_t))))
  269                 return (error);
  270         p->p_retval[0] = ngrp;
  271         return (0);
  272 }
  273 
  274 #ifndef _SYS_SYSPROTO_H_
  275 struct setsid_args {
  276         int     dummy;
  277 };
  278 #endif
  279 
  280 /* ARGSUSED */
  281 int
  282 setsid(p, uap)
  283         register struct proc *p;
  284         struct setsid_args *uap;
  285 {
  286 
  287         if (p->p_pgid == p->p_pid || pgfind(p->p_pid)) {
  288                 return (EPERM);
  289         } else {
  290                 (void)enterpgrp(p, p->p_pid, 1);
  291                 p->p_retval[0] = p->p_pid;
  292                 return (0);
  293         }
  294 }
  295 
  296 /*
  297  * set process group (setpgid/old setpgrp)
  298  *
  299  * caller does setpgid(targpid, targpgid)
  300  *
  301  * pid must be caller or child of caller (ESRCH)
  302  * if a child
  303  *      pid must be in same session (EPERM)
  304  *      pid can't have done an exec (EACCES)
  305  * if pgid != pid
  306  *      there must exist some pid in same session having pgid (EPERM)
  307  * pid must not be session leader (EPERM)
  308  */
  309 #ifndef _SYS_SYSPROTO_H_
  310 struct setpgid_args {
  311         int     pid;    /* target process id */
  312         int     pgid;   /* target pgrp id */
  313 };
  314 #endif
  315 /* ARGSUSED */
  316 int
  317 setpgid(curp, uap)
  318         struct proc *curp;
  319         register struct setpgid_args *uap;
  320 {
  321         register struct proc *targp;            /* target process */
  322         register struct pgrp *pgrp;             /* target pgrp */
  323 
  324         if (uap->pgid < 0)
  325                 return (EINVAL);
  326         if (uap->pid != 0 && uap->pid != curp->p_pid) {
  327                 if ((targp = pfind(uap->pid)) == 0 || !inferior(targp))
  328                         return (ESRCH);
  329                 if (targp->p_pgrp == NULL ||  targp->p_session != curp->p_session)
  330                         return (EPERM);
  331                 if (targp->p_flag & P_EXEC)
  332                         return (EACCES);
  333         } else
  334                 targp = curp;
  335         if (SESS_LEADER(targp))
  336                 return (EPERM);
  337         if (uap->pgid == 0)
  338                 uap->pgid = targp->p_pid;
  339         else if (uap->pgid != targp->p_pid)
  340                 if ((pgrp = pgfind(uap->pgid)) == 0 ||
  341                     pgrp->pg_session != curp->p_session)
  342                         return (EPERM);
  343         return (enterpgrp(targp, uap->pgid, 0));
  344 }
  345 
  346 /*
  347  * Use the clause in B.4.2.2 that allows setuid/setgid to be 4.2/4.3BSD
  348  * compatable.  It says that setting the uid/gid to euid/egid is a special
  349  * case of "appropriate privilege".  Once the rules are expanded out, this
  350  * basically means that setuid(nnn) sets all three id's, in all permitted
  351  * cases unless _POSIX_SAVED_IDS is enabled.  In that case, setuid(getuid())
  352  * does not set the saved id - this is dangerous for traditional BSD
  353  * programs.  For this reason, we *really* do not want to set
  354  * _POSIX_SAVED_IDS and do not want to clear POSIX_APPENDIX_B_4_2_2.
  355  */
  356 #define POSIX_APPENDIX_B_4_2_2
  357 
  358 #ifndef _SYS_SYSPROTO_H_
  359 struct setuid_args {
  360         uid_t   uid;
  361 };
  362 #endif
  363 /* ARGSUSED */
  364 int
  365 setuid(p, uap)
  366         struct proc *p;
  367         struct setuid_args *uap;
  368 {
  369         register struct pcred *pc = p->p_cred;
  370         register uid_t uid;
  371         int error;
  372 
  373         /*
  374          * See if we have "permission" by POSIX 1003.1 rules.
  375          *
  376          * Note that setuid(geteuid()) is a special case of 
  377          * "appropriate privileges" in appendix B.4.2.2.  We need
  378          * to use this clause to be compatable with traditional BSD
  379          * semantics.  Basically, it means that "setuid(xx)" sets all
  380          * three id's (assuming you have privs).
  381          *
  382          * Notes on the logic.  We do things in three steps.
  383          * 1: We determine if the euid is going to change, and do EPERM
  384          *    right away.  We unconditionally change the euid later if this
  385          *    test is satisfied, simplifying that part of the logic.
  386          * 2: We determine if the real and/or saved uid's are going to
  387          *    change.  Determined by compile options.
  388          * 3: Change euid last. (after tests in #2 for "appropriate privs")
  389          */
  390         uid = uap->uid;
  391         if (uid != pc->p_ruid &&                /* allow setuid(getuid()) */
  392 #ifdef _POSIX_SAVED_IDS
  393             uid != pc->p_svuid &&               /* allow setuid(saved gid) */
  394 #endif
  395 #ifdef POSIX_APPENDIX_B_4_2_2   /* Use BSD-compat clause from B.4.2.2 */
  396             uid != pc->pc_ucred->cr_uid &&      /* allow setuid(geteuid()) */
  397 #endif
  398             (error = suser(pc->pc_ucred, &p->p_acflag)))
  399                 return (error);
  400 
  401 #ifdef _POSIX_SAVED_IDS
  402         /*
  403          * Do we have "appropriate privileges" (are we root or uid == euid)
  404          * If so, we are changing the real uid and/or saved uid.
  405          */
  406         if (
  407 #ifdef POSIX_APPENDIX_B_4_2_2   /* Use the clause from B.4.2.2 */
  408             uid == pc->pc_ucred->cr_uid ||
  409 #endif
  410             suser(pc->pc_ucred, &p->p_acflag) == 0) /* we are using privs */
  411 #endif
  412         {
  413                 /*
  414                  * Transfer proc count to new user.
  415                  */
  416                 if (uid != pc->p_ruid) {
  417                         (void)chgproccnt(pc->p_ruid, -1);
  418                         (void)chgproccnt(uid, 1);
  419                 }
  420                 /*
  421                  * Set real uid
  422                  */
  423                 if (uid != pc->p_ruid) {
  424                         pc->p_ruid = uid;
  425                         setsugid(p);
  426                 }
  427                 /*
  428                  * Set saved uid
  429                  *
  430                  * XXX always set saved uid even if not _POSIX_SAVED_IDS, as
  431                  * the security of seteuid() depends on it.  B.4.2.2 says it
  432                  * is important that we should do this.
  433                  */
  434                 if (pc->p_svuid != uid) {
  435                         pc->p_svuid = uid;
  436                         setsugid(p);
  437                 }
  438         }
  439 
  440         /*
  441          * In all permitted cases, we are changing the euid.
  442          * Copy credentials so other references do not see our changes.
  443          */
  444         if (pc->pc_ucred->cr_uid != uid) {
  445                 pc->pc_ucred = crcopy(pc->pc_ucred);
  446                 pc->pc_ucred->cr_uid = uid;
  447                 setsugid(p);
  448         }
  449         return (0);
  450 }
  451 
  452 #ifndef _SYS_SYSPROTO_H_
  453 struct seteuid_args {
  454         uid_t   euid;
  455 };
  456 #endif
  457 /* ARGSUSED */
  458 int
  459 seteuid(p, uap)
  460         struct proc *p;
  461         struct seteuid_args *uap;
  462 {
  463         register struct pcred *pc = p->p_cred;
  464         register uid_t euid;
  465         int error;
  466 
  467         euid = uap->euid;
  468         if (euid != pc->p_ruid &&               /* allow seteuid(getuid()) */
  469             euid != pc->p_svuid &&              /* allow seteuid(saved uid) */
  470             (error = suser(pc->pc_ucred, &p->p_acflag)))
  471                 return (error);
  472         /*
  473          * Everything's okay, do it.  Copy credentials so other references do
  474          * not see our changes.
  475          */
  476         if (pc->pc_ucred->cr_uid != euid) {
  477                 pc->pc_ucred = crcopy(pc->pc_ucred);
  478                 pc->pc_ucred->cr_uid = euid;
  479                 setsugid(p);
  480         }
  481         return (0);
  482 }
  483 
  484 #ifndef _SYS_SYSPROTO_H_
  485 struct setgid_args {
  486         gid_t   gid;
  487 };
  488 #endif
  489 /* ARGSUSED */
  490 int
  491 setgid(p, uap)
  492         struct proc *p;
  493         struct setgid_args *uap;
  494 {
  495         register struct pcred *pc = p->p_cred;
  496         register gid_t gid;
  497         int error;
  498 
  499         /*
  500          * See if we have "permission" by POSIX 1003.1 rules.
  501          *
  502          * Note that setgid(getegid()) is a special case of
  503          * "appropriate privileges" in appendix B.4.2.2.  We need
  504          * to use this clause to be compatable with traditional BSD
  505          * semantics.  Basically, it means that "setgid(xx)" sets all
  506          * three id's (assuming you have privs).
  507          *
  508          * For notes on the logic here, see setuid() above.
  509          */
  510         gid = uap->gid;
  511         if (gid != pc->p_rgid &&                /* allow setgid(getgid()) */
  512 #ifdef _POSIX_SAVED_IDS
  513             gid != pc->p_svgid &&               /* allow setgid(saved gid) */
  514 #endif
  515 #ifdef POSIX_APPENDIX_B_4_2_2   /* Use BSD-compat clause from B.4.2.2 */
  516             gid != pc->pc_ucred->cr_groups[0] && /* allow setgid(getegid()) */
  517 #endif
  518             (error = suser(pc->pc_ucred, &p->p_acflag)))
  519                 return (error);
  520 
  521 #ifdef _POSIX_SAVED_IDS
  522         /*
  523          * Do we have "appropriate privileges" (are we root or gid == egid)
  524          * If so, we are changing the real uid and saved gid.
  525          */
  526         if (
  527 #ifdef POSIX_APPENDIX_B_4_2_2   /* use the clause from B.4.2.2 */
  528             gid == pc->pc_ucred->cr_groups[0] ||
  529 #endif
  530             suser(pc->pc_ucred, &p->p_acflag) == 0) /* we are using privs */
  531 #endif
  532         {
  533                 /*
  534                  * Set real gid
  535                  */
  536                 if (pc->p_rgid != gid) {
  537                         pc->p_rgid = gid;
  538                         setsugid(p);
  539                 }
  540                 /*
  541                  * Set saved gid
  542                  *
  543                  * XXX always set saved gid even if not _POSIX_SAVED_IDS, as
  544                  * the security of setegid() depends on it.  B.4.2.2 says it
  545                  * is important that we should do this.
  546                  */
  547                 if (pc->p_svgid != gid) {
  548                         pc->p_svgid = gid;
  549                         setsugid(p);
  550                 }
  551         }
  552         /*
  553          * In all cases permitted cases, we are changing the egid.
  554          * Copy credentials so other references do not see our changes.
  555          */
  556         if (pc->pc_ucred->cr_groups[0] != gid) {
  557                 pc->pc_ucred = crcopy(pc->pc_ucred);
  558                 pc->pc_ucred->cr_groups[0] = gid;
  559                 setsugid(p);
  560         }
  561         return (0);
  562 }
  563 
  564 #ifndef _SYS_SYSPROTO_H_
  565 struct setegid_args {
  566         gid_t   egid;
  567 };
  568 #endif
  569 /* ARGSUSED */
  570 int
  571 setegid(p, uap)
  572         struct proc *p;
  573         struct setegid_args *uap;
  574 {
  575         register struct pcred *pc = p->p_cred;
  576         register gid_t egid;
  577         int error;
  578 
  579         egid = uap->egid;
  580         if (egid != pc->p_rgid &&               /* allow setegid(getgid()) */
  581             egid != pc->p_svgid &&              /* allow setegid(saved gid) */
  582             (error = suser(pc->pc_ucred, &p->p_acflag)))
  583                 return (error);
  584         if (pc->pc_ucred->cr_groups[0] != egid) {
  585                 pc->pc_ucred = crcopy(pc->pc_ucred);
  586                 pc->pc_ucred->cr_groups[0] = egid;
  587                 setsugid(p);
  588         }
  589         return (0);
  590 }
  591 
  592 #ifndef _SYS_SYSPROTO_H_
  593 struct setgroups_args {
  594         u_int   gidsetsize;
  595         gid_t   *gidset;
  596 };
  597 #endif
  598 /* ARGSUSED */
  599 int
  600 setgroups(p, uap)
  601         struct proc *p;
  602         struct setgroups_args *uap;
  603 {
  604         register struct pcred *pc = p->p_cred;
  605         register u_int ngrp;
  606         int error;
  607 
  608         if ((error = suser(pc->pc_ucred, &p->p_acflag)))
  609                 return (error);
  610         ngrp = uap->gidsetsize;
  611         if (ngrp > NGROUPS)
  612                 return (EINVAL);
  613         /*
  614          * XXX A little bit lazy here.  We could test if anything has
  615          * changed before crcopy() and setting P_SUGID.
  616          */
  617         pc->pc_ucred = crcopy(pc->pc_ucred);
  618         if (ngrp < 1) {
  619                 /*
  620                  * setgroups(0, NULL) is a legitimate way of clearing the
  621                  * groups vector on non-BSD systems (which generally do not
  622                  * have the egid in the groups[0]).  We risk security holes
  623                  * when running non-BSD software if we do not do the same.
  624                  */
  625                 pc->pc_ucred->cr_ngroups = 1;
  626         } else {
  627                 if ((error = copyin((caddr_t)uap->gidset,
  628                     (caddr_t)pc->pc_ucred->cr_groups, ngrp * sizeof(gid_t))))
  629                         return (error);
  630                 pc->pc_ucred->cr_ngroups = ngrp;
  631         }
  632         setsugid(p);
  633         return (0);
  634 }
  635 
  636 #ifndef _SYS_SYSPROTO_H_
  637 struct setreuid_args {
  638         uid_t   ruid;
  639         uid_t   euid;
  640 };
  641 #endif
  642 /* ARGSUSED */
  643 int
  644 setreuid(p, uap)
  645         register struct proc *p;
  646         struct setreuid_args *uap;
  647 {
  648         register struct pcred *pc = p->p_cred;
  649         register uid_t ruid, euid;
  650         int error;
  651 
  652         ruid = uap->ruid;
  653         euid = uap->euid;
  654         if ((ruid != (uid_t)-1 && ruid != pc->p_ruid && ruid != pc->p_svuid ||
  655              euid != (uid_t)-1 && euid != pc->pc_ucred->cr_uid &&
  656              euid != pc->p_ruid && euid != pc->p_svuid) &&
  657             (error = suser(pc->pc_ucred, &p->p_acflag)))
  658                 return (error);
  659 
  660         if (euid != (uid_t)-1 && pc->pc_ucred->cr_uid != euid) {
  661                 pc->pc_ucred = crcopy(pc->pc_ucred);
  662                 pc->pc_ucred->cr_uid = euid;
  663                 setsugid(p);
  664         }
  665         if (ruid != (uid_t)-1 && pc->p_ruid != ruid) {
  666                 (void)chgproccnt(pc->p_ruid, -1);
  667                 (void)chgproccnt(ruid, 1);
  668                 pc->p_ruid = ruid;
  669                 setsugid(p);
  670         }
  671         if ((ruid != (uid_t)-1 || pc->pc_ucred->cr_uid != pc->p_ruid) &&
  672             pc->p_svuid != pc->pc_ucred->cr_uid) {
  673                 pc->p_svuid = pc->pc_ucred->cr_uid;
  674                 setsugid(p);
  675         }
  676         return (0);
  677 }
  678 
  679 #ifndef _SYS_SYSPROTO_H_
  680 struct setregid_args {
  681         gid_t   rgid;
  682         gid_t   egid;
  683 };
  684 #endif
  685 /* ARGSUSED */
  686 int
  687 setregid(p, uap)
  688         register struct proc *p;
  689         struct setregid_args *uap;
  690 {
  691         register struct pcred *pc = p->p_cred;
  692         register gid_t rgid, egid;
  693         int error;
  694 
  695         rgid = uap->rgid;
  696         egid = uap->egid;
  697         if ((rgid != (gid_t)-1 && rgid != pc->p_rgid && rgid != pc->p_svgid ||
  698              egid != (gid_t)-1 && egid != pc->pc_ucred->cr_groups[0] &&
  699              egid != pc->p_rgid && egid != pc->p_svgid) &&
  700             (error = suser(pc->pc_ucred, &p->p_acflag)))
  701                 return (error);
  702 
  703         if (egid != (gid_t)-1 && pc->pc_ucred->cr_groups[0] != egid) {
  704                 pc->pc_ucred = crcopy(pc->pc_ucred);
  705                 pc->pc_ucred->cr_groups[0] = egid;
  706                 setsugid(p);
  707         }
  708         if (rgid != (gid_t)-1 && pc->p_rgid != rgid) {
  709                 pc->p_rgid = rgid;
  710                 setsugid(p);
  711         }
  712         if ((rgid != (gid_t)-1 || pc->pc_ucred->cr_groups[0] != pc->p_rgid) &&
  713             pc->p_svgid != pc->pc_ucred->cr_groups[0]) {
  714                 pc->p_svgid = pc->pc_ucred->cr_groups[0];
  715                 setsugid(p);
  716         }
  717         return (0);
  718 }
  719 
  720 #ifndef _SYS_SYSPROTO_H_
  721 struct issetugid_args {
  722         int dummy;
  723 };
  724 #endif
  725 /* ARGSUSED */
  726 int
  727 issetugid(p, uap)
  728         register struct proc *p;
  729         struct issetugid_args *uap;
  730 {
  731         /*
  732          * Note: OpenBSD sets a P_SUGIDEXEC flag set at execve() time,
  733          * we use P_SUGID because we consider changing the owners as
  734          * "tainting" as well.
  735          * This is significant for procs that start as root and "become"
  736          * a user without an exec - programs cannot know *everything*
  737          * that libc *might* have put in their data segment.
  738          */
  739         if (p->p_flag & P_SUGID)
  740                 return (1);
  741         return (0);
  742 }
  743 
  744 /*
  745  * Check if gid is a member of the group set.
  746  */
  747 int
  748 groupmember(gid, cred)
  749         gid_t gid;
  750         register struct ucred *cred;
  751 {
  752         register gid_t *gp;
  753         gid_t *egp;
  754 
  755         egp = &(cred->cr_groups[cred->cr_ngroups]);
  756         for (gp = cred->cr_groups; gp < egp; gp++)
  757                 if (*gp == gid)
  758                         return (1);
  759         return (0);
  760 }
  761 
  762 /*
  763  * Test whether the specified credentials imply "super-user"
  764  * privilege; if so, and we have accounting info, set the flag
  765  * indicating use of super-powers.
  766  * Returns 0 or error.
  767  */
  768 int
  769 suser(cred, acflag)
  770         struct ucred *cred;
  771         u_short *acflag;
  772 {
  773         if (cred->cr_uid == 0) {
  774                 if (acflag)
  775                         *acflag |= ASU;
  776                 return (0);
  777         }
  778         return (EPERM);
  779 }
  780 
  781 /*
  782  * Allocate a zeroed cred structure.
  783  */
  784 struct ucred *
  785 crget()
  786 {
  787         register struct ucred *cr;
  788 
  789         MALLOC(cr, struct ucred *, sizeof(*cr), M_CRED, M_WAITOK);
  790         bzero((caddr_t)cr, sizeof(*cr));
  791         cr->cr_ref = 1;
  792         return (cr);
  793 }
  794 
  795 /*
  796  * Free a cred structure.
  797  * Throws away space when ref count gets to 0.
  798  */
  799 void
  800 crfree(cr)
  801         struct ucred *cr;
  802 {
  803         if (--cr->cr_ref == 0)
  804                 FREE((caddr_t)cr, M_CRED);
  805 }
  806 
  807 /*
  808  * Copy cred structure to a new one and free the old one.
  809  */
  810 struct ucred *
  811 crcopy(cr)
  812         struct ucred *cr;
  813 {
  814         struct ucred *newcr;
  815 
  816         if (cr->cr_ref == 1)
  817                 return (cr);
  818         newcr = crget();
  819         *newcr = *cr;
  820         crfree(cr);
  821         newcr->cr_ref = 1;
  822         return (newcr);
  823 }
  824 
  825 /*
  826  * Dup cred struct to a new held one.
  827  */
  828 struct ucred *
  829 crdup(cr)
  830         struct ucred *cr;
  831 {
  832         struct ucred *newcr;
  833 
  834         newcr = crget();
  835         *newcr = *cr;
  836         newcr->cr_ref = 1;
  837         return (newcr);
  838 }
  839 
  840 /*
  841  * Get login name, if available.
  842  */
  843 #ifndef _SYS_SYSPROTO_H_
  844 struct getlogin_args {
  845         char    *namebuf;
  846         u_int   namelen;
  847 };
  848 #endif
  849 /* ARGSUSED */
  850 int
  851 getlogin(p, uap)
  852         struct proc *p;
  853         struct getlogin_args *uap;
  854 {
  855 
  856         if (uap->namelen > MAXLOGNAME)
  857                 uap->namelen = MAXLOGNAME;
  858         return (copyout((caddr_t) p->p_pgrp->pg_session->s_login,
  859             (caddr_t) uap->namebuf, uap->namelen));
  860 }
  861 
  862 /*
  863  * Set login name.
  864  */
  865 #ifndef _SYS_SYSPROTO_H_
  866 struct setlogin_args {
  867         char    *namebuf;
  868 };
  869 #endif
  870 /* ARGSUSED */
  871 int
  872 setlogin(p, uap)
  873         struct proc *p;
  874         struct setlogin_args *uap;
  875 {
  876         int error;
  877         char logintmp[MAXLOGNAME];
  878 
  879         if ((error = suser(p->p_ucred, &p->p_acflag)))
  880                 return (error);
  881         error = copyinstr((caddr_t) uap->namebuf, (caddr_t) logintmp,
  882             sizeof(logintmp), (size_t *)0);
  883         if (error == ENAMETOOLONG)
  884                 error = EINVAL;
  885         else if (!error)
  886                 (void) memcpy(p->p_pgrp->pg_session->s_login, logintmp,
  887                     sizeof(logintmp));
  888         return (error);
  889 }
  890 
  891 void
  892 setsugid(p)
  893      struct proc *p;
  894 {
  895         p->p_flag |= P_SUGID;
  896         if (!(p->p_pfsflags & PF_ISUGID))
  897                 p->p_stops = 0;
  898 }

Cache object: a51aa370e5678af8c94caa13fed75f5e


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