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  -  FREEBSD10  -  FREEBSD9  -  FREEBSD92  -  FREEBSD91  -  FREEBSD90  -  FREEBSD8  -  FREEBSD82  -  FREEBSD81  -  FREEBSD80  -  FREEBSD7  -  FREEBSD74  -  FREEBSD73  -  FREEBSD72  -  FREEBSD71  -  FREEBSD70  -  FREEBSD6  -  FREEBSD64  -  FREEBSD63  -  FREEBSD62  -  FREEBSD61  -  FREEBSD60  -  FREEBSD5  -  FREEBSD55  -  FREEBSD54  -  FREEBSD53  -  FREEBSD52  -  FREEBSD51  -  FREEBSD50  -  FREEBSD4  -  FREEBSD3  -  FREEBSD22  -  cheribsd  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1  -  FREEBSD-LIBC  -  FREEBSD8-LIBC  -  FREEBSD7-LIBC  -  FREEBSD6-LIBC  -  GLIBC27 
SearchContext: -  none  -  3  -  10 

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

Cache object: 909ee7502f6b8812f133ce91a636c93a


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