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

Cache object: d3815b613b91f761e2b77babdc878d73


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