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-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-2  -  FREEBSD-11-1  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-4  -  FREEBSD-10-3  -  FREEBSD-10-2  -  FREEBSD-10-1  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-3  -  FREEBSD-9-2  -  FREEBSD-9-1  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-4  -  FREEBSD-8-3  -  FREEBSD-8-2  -  FREEBSD-8-1  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-4  -  FREEBSD-7-3  -  FREEBSD-7-2  -  FREEBSD-7-1  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-4  -  FREEBSD-6-3  -  FREEBSD-6-2  -  FREEBSD-6-1  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-5  -  FREEBSD-5-4  -  FREEBSD-5-3  -  FREEBSD-5-2  -  FREEBSD-5-1  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  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 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: kern_prot.c,v 1.80 2003/08/07 16:31:47 agc Exp $       */
    2 
    3 /*
    4  * Copyright (c) 1982, 1986, 1989, 1990, 1991, 1993
    5  *      The Regents of the University of California.  All rights reserved.
    6  * (c) UNIX System Laboratories, Inc.
    7  * All or some portions of this file are derived from material licensed
    8  * to the University of California by American Telephone and Telegraph
    9  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
   10  * the permission of UNIX System Laboratories, Inc.
   11  *
   12  * Redistribution and use in source and binary forms, with or without
   13  * modification, are permitted provided that the following conditions
   14  * are met:
   15  * 1. Redistributions of source code must retain the above copyright
   16  *    notice, this list of conditions and the following disclaimer.
   17  * 2. Redistributions in binary form must reproduce the above copyright
   18  *    notice, this list of conditions and the following disclaimer in the
   19  *    documentation and/or other materials provided with the distribution.
   20  * 3. Neither the name of the University nor the names of its contributors
   21  *    may be used to endorse or promote products derived from this software
   22  *    without specific prior written permission.
   23  *
   24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   34  * SUCH DAMAGE.
   35  *
   36  *      @(#)kern_prot.c 8.9 (Berkeley) 2/14/95
   37  */
   38 
   39 /*
   40  * System calls related to processes and protection
   41  */
   42 
   43 #include <sys/cdefs.h>
   44 __KERNEL_RCSID(0, "$NetBSD: kern_prot.c,v 1.80 2003/08/07 16:31:47 agc Exp $");
   45 
   46 #include "opt_compat_43.h"
   47 
   48 #include <sys/param.h>
   49 #include <sys/acct.h>
   50 #include <sys/systm.h>
   51 #include <sys/ucred.h>
   52 #include <sys/proc.h>
   53 #include <sys/timeb.h>
   54 #include <sys/times.h>
   55 #include <sys/malloc.h>
   56 #include <sys/syslog.h>
   57 
   58 #include <sys/mount.h>
   59 #include <sys/sa.h>
   60 #include <sys/syscallargs.h>
   61 
   62 MALLOC_DEFINE(M_CRED, "cred", "credentials");
   63 
   64 int     sys_getpid(struct lwp *, void *, register_t *);
   65 int     sys_getpid_with_ppid(struct lwp *, void *, register_t *);
   66 int     sys_getuid(struct lwp *, void *, register_t *);
   67 int     sys_getuid_with_euid(struct lwp *, void *, register_t *);
   68 int     sys_getgid(struct lwp *, void *, register_t *);
   69 int     sys_getgid_with_egid(struct lwp *, void *, register_t *);
   70 
   71 /* ARGSUSED */
   72 int
   73 sys_getpid(struct lwp *l, void *v, register_t *retval)
   74 {
   75         struct proc *p = l->l_proc;
   76 
   77         *retval = p->p_pid;
   78         return (0);
   79 }
   80 
   81 /* ARGSUSED */
   82 int
   83 sys_getpid_with_ppid(struct lwp *l, void *v, register_t *retval)
   84 {
   85         struct proc *p = l->l_proc;
   86 
   87         retval[0] = p->p_pid;
   88         retval[1] = p->p_pptr->p_pid;
   89         return (0);
   90 }
   91 
   92 /* ARGSUSED */
   93 int
   94 sys_getppid(struct lwp *l, void *v, register_t *retval)
   95 {
   96         struct proc *p = l->l_proc;
   97 
   98         *retval = p->p_pptr->p_pid;
   99         return (0);
  100 }
  101 
  102 /* Get process group ID; note that POSIX getpgrp takes no parameter */
  103 int
  104 sys_getpgrp(struct lwp *l, void *v, register_t *retval)
  105 {
  106         struct proc *p = l->l_proc;
  107 
  108         *retval = p->p_pgrp->pg_id;
  109         return (0);
  110 }
  111 
  112 /*
  113  * Return the process group ID of the session leader (session ID)
  114  * for the specified process.
  115  */
  116 int
  117 sys_getsid(struct lwp *l, void *v, register_t *retval)
  118 {
  119         struct sys_getsid_args /* {
  120                 syscalldarg(pid_t) pid;
  121         } */ *uap = v;
  122         struct proc *p = l->l_proc;
  123 
  124         if (SCARG(uap, pid) == 0)
  125                 goto found;
  126         if ((p = pfind(SCARG(uap, pid))) == 0)
  127                 return (ESRCH);
  128 found:
  129         *retval = p->p_session->s_sid;
  130         return (0);
  131 }
  132 
  133 int
  134 sys_getpgid(struct lwp *l, void *v, register_t *retval)
  135 {
  136         struct sys_getpgid_args /* {
  137                 syscallarg(pid_t) pid;
  138         } */ *uap = v;
  139         struct proc *p = l->l_proc;
  140 
  141         if (SCARG(uap, pid) == 0)
  142                 goto found;
  143         if ((p = pfind(SCARG(uap, pid))) == 0)
  144                 return (ESRCH);
  145 found:
  146         *retval = p->p_pgid;
  147         return (0);
  148 }
  149 
  150 /* ARGSUSED */
  151 int
  152 sys_getuid(struct lwp *l, void *v, register_t *retval)
  153 {
  154         struct proc *p = l->l_proc;
  155 
  156         *retval = p->p_cred->p_ruid;
  157         return (0);
  158 }
  159 
  160 /* ARGSUSED */
  161 int
  162 sys_getuid_with_euid(struct lwp *l, void *v, register_t *retval)
  163 {
  164         struct proc *p = l->l_proc;
  165 
  166         retval[0] = p->p_cred->p_ruid;
  167         retval[1] = p->p_ucred->cr_uid;
  168         return (0);
  169 }
  170 
  171 /* ARGSUSED */
  172 int
  173 sys_geteuid(struct lwp *l, void *v, register_t *retval)
  174 {
  175         struct proc *p = l->l_proc;
  176 
  177         *retval = p->p_ucred->cr_uid;
  178         return (0);
  179 }
  180 
  181 /* ARGSUSED */
  182 int
  183 sys_getgid(struct lwp *l, void *v, register_t *retval)
  184 {
  185         struct proc *p = l->l_proc;
  186 
  187         *retval = p->p_cred->p_rgid;
  188         return (0);
  189 }
  190 
  191 /* ARGSUSED */
  192 int
  193 sys_getgid_with_egid(struct lwp *l, void *v, register_t *retval)
  194 {
  195         struct proc *p = l->l_proc;
  196 
  197         retval[0] = p->p_cred->p_rgid;
  198         retval[1] = p->p_ucred->cr_gid;
  199         return (0);
  200 }
  201 
  202 /*
  203  * Get effective group ID.  The "egid" is groups[0], and could be obtained
  204  * via getgroups.  This syscall exists because it is somewhat painful to do
  205  * correctly in a library function.
  206  */
  207 /* ARGSUSED */
  208 int
  209 sys_getegid(struct lwp *l, void *v, register_t *retval)
  210 {
  211         struct proc *p = l->l_proc;
  212 
  213         *retval = p->p_ucred->cr_gid;
  214         return (0);
  215 }
  216 
  217 int
  218 sys_getgroups(struct lwp *l, void *v, register_t *retval)
  219 {
  220         struct sys_getgroups_args /* {
  221                 syscallarg(int) gidsetsize;
  222                 syscallarg(gid_t *) gidset;
  223         } */ *uap = v;
  224         struct proc *p = l->l_proc;
  225         struct pcred *pc = p->p_cred;
  226         u_int ngrp;
  227         int error;
  228 
  229         if (SCARG(uap, gidsetsize) == 0) {
  230                 *retval = pc->pc_ucred->cr_ngroups;
  231                 return (0);
  232         } else if (SCARG(uap, gidsetsize) < 0)
  233                 return (EINVAL);
  234         ngrp = SCARG(uap, gidsetsize);
  235         if (ngrp < pc->pc_ucred->cr_ngroups)
  236                 return (EINVAL);
  237         ngrp = pc->pc_ucred->cr_ngroups;
  238         error = copyout((caddr_t)pc->pc_ucred->cr_groups,
  239             (caddr_t)SCARG(uap, gidset), ngrp * sizeof(gid_t));
  240         if (error)
  241                 return (error);
  242         *retval = ngrp;
  243         return (0);
  244 }
  245 
  246 /* ARGSUSED */
  247 int
  248 sys_setsid(struct lwp *l, void *v, register_t *retval)
  249 {
  250         struct proc *p = l->l_proc;
  251 
  252         if (p->p_pgid == p->p_pid || pgfind(p->p_pid)) {
  253                 return (EPERM);
  254         } else {
  255                 (void)enterpgrp(p, p->p_pid, 1);
  256                 *retval = p->p_pid;
  257                 return (0);
  258         }
  259 }
  260 
  261 /*
  262  * set process group (setpgid/old setpgrp)
  263  *
  264  * caller does setpgid(targpid, targpgid)
  265  *
  266  * pgid must be in valid range (EINVAL)
  267  * pid must be caller or child of caller (ESRCH)
  268  * if a child
  269  *      pid must be in same session (EPERM)
  270  *      pid can't have done an exec (EACCES)
  271  * if pgid != pid
  272  *      there must exist some pid in same session having pgid (EPERM)
  273  * pid must not be session leader (EPERM)
  274  *
  275  * Permission checks now in enterpgrp()
  276  */
  277 /* ARGSUSED */
  278 int
  279 sys_setpgid(struct lwp *l, void *v, register_t *retval)
  280 {
  281         struct sys_setpgid_args /* {
  282                 syscallarg(int) pid;
  283                 syscallarg(int) pgid;
  284         } */ *uap = v;
  285         struct proc *curp = l->l_proc;
  286         struct proc *targp;                     /* target process */
  287 
  288         if (SCARG(uap, pgid) < 0)
  289                 return EINVAL;
  290 
  291         /* XXX MP - there is a horrid race here with targp exiting! */
  292         if (SCARG(uap, pid) != 0 && SCARG(uap, pid) != curp->p_pid) {
  293                 targp = pfind(SCARG(uap, pid));
  294                 if (targp == NULL)
  295                         return ESRCH;
  296         } else
  297                 targp = curp;
  298 
  299         if (SCARG(uap, pgid) == 0)
  300                 SCARG(uap, pgid) = targp->p_pid;
  301         return enterpgrp(targp, SCARG(uap, pgid), 0);
  302 }
  303 
  304 /*
  305  * Set real, effective and saved uids to the requested values.
  306  * non-root callers can only ever change uids to values that match
  307  * one of the processes current uid values.
  308  * This is further restricted by the flags argument.
  309  */
  310 
  311 int
  312 do_setresuid(struct lwp *l, uid_t r, uid_t e, uid_t sv, u_int flags)
  313 {
  314         int error;
  315         struct proc *p = l->l_proc;
  316         struct pcred *pcred = p->p_cred;
  317         struct ucred *cred = pcred->pc_ucred;
  318 
  319         /* Superuser can do anything it wants to.... */
  320         error = suser(cred, &p->p_acflag);
  321         if (error) {
  322                 /* Otherwise check new value is one of the allowed
  323                    existing values. */
  324                 if (r != -1 && !((flags & ID_R_EQ_R) && r == pcred->p_ruid)
  325                             && !((flags & ID_R_EQ_E) && r == cred->cr_uid)
  326                             && !((flags & ID_R_EQ_S) && r == pcred->p_svuid))
  327                         return error;
  328                 if (e != -1 && !((flags & ID_E_EQ_R) && e == pcred->p_ruid)
  329                             && !((flags & ID_E_EQ_E) && e == cred->cr_uid)
  330                             && !((flags & ID_E_EQ_S) && e == pcred->p_svuid))
  331                         return error;
  332                 if (sv != -1 && !((flags & ID_S_EQ_R) && sv == pcred->p_ruid)
  333                             && !((flags & ID_S_EQ_E) && sv == cred->cr_uid)
  334                             && !((flags & ID_S_EQ_S) && sv == pcred->p_svuid))
  335                         return error;
  336         }
  337 
  338         /* If nothing has changed, short circuit the request */
  339         if ((r == -1 || r == pcred->p_ruid)
  340             && (e == -1 || e == cred->cr_uid)
  341             && (sv == -1 || sv == pcred->p_svuid))
  342                 /* nothing to do */
  343                 return 0;
  344 
  345         /* The pcred structure is not actually shared... */
  346         if (r != -1 && r != pcred->p_ruid) {
  347                 /* Update count of processes for this user */
  348                 (void)chgproccnt(pcred->p_ruid, -1);
  349                 (void)chgproccnt(r, 1);
  350                 pcred->p_ruid = r;
  351         }
  352         if (sv != -1)
  353                 pcred->p_svuid = sv;
  354         if (e != -1 && e != cred->cr_uid) {
  355                 /* Update a clone of the current credentials */
  356                 pcred->pc_ucred = cred = crcopy(cred);
  357                 cred->cr_uid = e;
  358         }
  359 
  360         /* Mark process as having changed credentials, stops tracing etc */
  361         p_sugid(p);
  362         return 0;
  363 }
  364 
  365 /*
  366  * Set real, effective and saved gids to the requested values.
  367  * non-root callers can only ever change gids to values that match
  368  * one of the processes current gid values.
  369  * This is further restricted by the flags argument.
  370  */
  371 
  372 int
  373 do_setresgid(struct lwp *l, gid_t r, gid_t e, gid_t sv, u_int flags)
  374 {
  375         int error;
  376         struct proc *p = l->l_proc;
  377         struct pcred *pcred = p->p_cred;
  378         struct ucred *cred = pcred->pc_ucred;
  379 
  380         /* Superuser can do anything it wants to.... */
  381         error = suser(cred, &p->p_acflag);
  382         if (error) {
  383                 /* Otherwise check new value is one of the allowed
  384                    existing values. */
  385                 if (r != -1 && !((flags & ID_R_EQ_R) && r == pcred->p_rgid)
  386                             && !((flags & ID_R_EQ_E) && r == cred->cr_gid)
  387                             && !((flags & ID_R_EQ_S) && r == pcred->p_svgid))
  388                         return error;
  389                 if (e != -1 && !((flags & ID_E_EQ_R) && e == pcred->p_rgid)
  390                             && !((flags & ID_E_EQ_E) && e == cred->cr_gid)
  391                             && !((flags & ID_E_EQ_S) && e == pcred->p_svgid))
  392                         return error;
  393                 if (sv != -1 && !((flags & ID_S_EQ_R) && sv == pcred->p_rgid)
  394                             && !((flags & ID_S_EQ_E) && sv == cred->cr_gid)
  395                             && !((flags & ID_S_EQ_S) && sv == pcred->p_svgid))
  396                         return error;
  397         }
  398 
  399         /* If nothing has changed, short circuit the request */
  400         if ((r == -1 || r == pcred->p_rgid)
  401             && (e == -1 || e == cred->cr_gid)
  402             && (sv == -1 || sv == pcred->p_svgid))
  403                 /* nothing to do */
  404                 return 0;
  405 
  406         /* The pcred structure is not actually shared... */
  407         if (r != -1)
  408                 pcred->p_rgid = r;
  409         if (sv != -1)
  410                 pcred->p_svgid = sv;
  411         if (e != -1 && e != cred->cr_gid) {
  412                 /* Update a clone of the current credentials */
  413                 pcred->pc_ucred = cred = crcopy(cred);
  414                 cred->cr_gid = e;
  415         }
  416 
  417         /* Mark process as having changed credentials, stops tracing etc */
  418         p_sugid(p);
  419         return 0;
  420 }
  421 
  422 /* ARGSUSED */
  423 int
  424 sys_setuid(struct lwp *l, void *v, register_t *retval)
  425 {
  426         struct sys_setuid_args /* {
  427                 syscallarg(uid_t) uid;
  428         } */ *uap = v;
  429         uid_t uid = SCARG(uap, uid);
  430 
  431         return do_setresuid(l, uid, uid, uid,
  432                             ID_R_EQ_R | ID_E_EQ_R | ID_S_EQ_R);
  433 }
  434 
  435 /* ARGSUSED */
  436 int
  437 sys_seteuid(struct lwp *l, void *v, register_t *retval)
  438 {
  439         struct sys_seteuid_args /* {
  440                 syscallarg(uid_t) euid;
  441         } */ *uap = v;
  442 
  443         return do_setresuid(l, -1, SCARG(uap, euid), -1, ID_E_EQ_R | ID_E_EQ_S);
  444 }
  445 
  446 int
  447 sys_setreuid(struct lwp *l, void *v, register_t *retval)
  448 {
  449         struct sys_setreuid_args /* {
  450                 syscallarg(uid_t) ruid;
  451                 syscallarg(uid_t) euid;
  452         } */ *uap = v;
  453         struct proc *p = l->l_proc;
  454         uid_t ruid, euid, svuid;
  455 
  456         ruid = SCARG(uap, ruid);
  457         euid = SCARG(uap, euid);
  458         if (ruid == -1)
  459                 ruid = p->p_cred->p_ruid;
  460         if (euid == -1)
  461                 euid = p->p_ucred->cr_uid;
  462         /* Saved uid is set to the new euid if the ruid changed */
  463         svuid = (ruid == p->p_cred->p_ruid) ? -1 : euid;
  464 
  465         return do_setresuid(l, ruid, euid, svuid,
  466                             ID_R_EQ_R | ID_R_EQ_E |
  467                             ID_E_EQ_R | ID_E_EQ_E | ID_E_EQ_S |
  468                             ID_S_EQ_R | ID_S_EQ_E | ID_S_EQ_S);
  469 }
  470 
  471 /* ARGSUSED */
  472 int
  473 sys_setgid(struct lwp *l, void *v, register_t *retval)
  474 {
  475         struct sys_setgid_args /* {
  476                 syscallarg(gid_t) gid;
  477         } */ *uap = v;
  478         gid_t gid = SCARG(uap, gid);
  479 
  480         return do_setresgid(l, gid, gid, gid,
  481                             ID_R_EQ_R | ID_E_EQ_R | ID_S_EQ_R);
  482 }
  483 
  484 /* ARGSUSED */
  485 int
  486 sys_setegid(struct lwp *l, void *v, register_t *retval)
  487 {
  488         struct sys_setegid_args /* {
  489                 syscallarg(gid_t) egid;
  490         } */ *uap = v;
  491 
  492         return do_setresgid(l, -1, SCARG(uap, egid), -1, ID_E_EQ_R | ID_E_EQ_S);
  493 }
  494 
  495 int
  496 sys_setregid(struct lwp *l, void *v, register_t *retval)
  497 {
  498         struct sys_setregid_args /* {
  499                 syscallarg(gid_t) rgid;
  500                 syscallarg(gid_t) egid;
  501         } */ *uap = v;
  502         struct proc *p = l->l_proc;
  503         gid_t rgid, egid, svgid;
  504 
  505         rgid = SCARG(uap, rgid);
  506         egid = SCARG(uap, egid);
  507         if (rgid == -1)
  508                 rgid = p->p_cred->p_rgid;
  509         if (egid == -1)
  510                 egid = p->p_ucred->cr_gid;
  511         /* Saved gid is set to the new egid if the rgid changed */
  512         svgid = rgid == p->p_cred->p_rgid ? -1 : egid;
  513 
  514         return do_setresgid(l, rgid, egid, svgid,
  515                         ID_R_EQ_R | ID_R_EQ_E |
  516                         ID_E_EQ_R | ID_E_EQ_E | ID_E_EQ_S |
  517                         ID_S_EQ_R | ID_S_EQ_E | ID_S_EQ_S);
  518 }
  519 
  520 int
  521 sys_issetugid(struct lwp *l, void *v, register_t *retval)
  522 {
  523         struct proc *p = l->l_proc;
  524 
  525         /*
  526          * Note: OpenBSD sets a P_SUGIDEXEC flag set at execve() time,
  527          * we use P_SUGID because we consider changing the owners as
  528          * "tainting" as well.
  529          * This is significant for procs that start as root and "become"
  530          * a user without an exec - programs cannot know *everything*
  531          * that libc *might* have put in their data segment.
  532          */
  533         *retval = (p->p_flag & P_SUGID) != 0;
  534         return (0);
  535 }
  536 
  537 /* ARGSUSED */
  538 int
  539 sys_setgroups(struct lwp *l, void *v, register_t *retval)
  540 {
  541         struct sys_setgroups_args /* {
  542                 syscallarg(int) gidsetsize;
  543                 syscallarg(const gid_t *) gidset;
  544         } */ *uap = v;
  545         struct proc *p = l->l_proc;
  546         struct pcred *pc = p->p_cred;
  547         int ngrp;
  548         int error;
  549         gid_t grp[NGROUPS];
  550         size_t grsize;
  551 
  552         if ((error = suser(pc->pc_ucred, &p->p_acflag)) != 0)
  553                 return (error);
  554 
  555         ngrp = SCARG(uap, gidsetsize);
  556         if ((u_int)ngrp > NGROUPS)
  557                 return (EINVAL);
  558 
  559         grsize = ngrp * sizeof(gid_t);
  560         error = copyin(SCARG(uap, gidset), grp, grsize);
  561         if (error)
  562                 return (error);
  563         /*
  564          * Check if this is a no-op.
  565          */
  566         if (pc->pc_ucred->cr_ngroups == (u_int) ngrp &&
  567             memcmp(grp, pc->pc_ucred->cr_groups, grsize) == 0)
  568                 return (0);
  569 
  570         pc->pc_ucred = crcopy(pc->pc_ucred);
  571         (void)memcpy(pc->pc_ucred->cr_groups, grp, grsize);
  572         pc->pc_ucred->cr_ngroups = ngrp;
  573         p_sugid(p);
  574         return (0);
  575 }
  576 
  577 /*
  578  * Check if gid is a member of the group set.
  579  */
  580 int
  581 groupmember(gid_t gid, const struct ucred *cred)
  582 {
  583         const gid_t *gp;
  584         const gid_t *egp;
  585 
  586         egp = &(cred->cr_groups[cred->cr_ngroups]);
  587         for (gp = cred->cr_groups; gp < egp; gp++)
  588                 if (*gp == gid)
  589                         return (1);
  590         return (0);
  591 }
  592 
  593 /*
  594  * Test whether the specified credentials imply "super-user"
  595  * privilege; if so, and we have accounting info, set the flag
  596  * indicating use of super-powers.
  597  * Returns 0 or error.
  598  */
  599 int
  600 suser(const struct ucred *cred, u_short *acflag)
  601 {
  602 
  603         if (cred->cr_uid == 0) {
  604                 if (acflag)
  605                         *acflag |= ASU;
  606                 return (0);
  607         }
  608         return (EPERM);
  609 }
  610 
  611 /*
  612  * Allocate a zeroed cred structure.
  613  */
  614 struct ucred *
  615 crget(void)
  616 {
  617         struct ucred *cr;
  618 
  619         MALLOC(cr, struct ucred *, sizeof(*cr), M_CRED, M_WAITOK);
  620         memset((caddr_t)cr, 0, sizeof(*cr));
  621         cr->cr_ref = 1;
  622         return (cr);
  623 }
  624 
  625 /*
  626  * Free a cred structure.
  627  * Throws away space when ref count gets to 0.
  628  */
  629 void
  630 crfree(struct ucred *cr)
  631 {
  632 
  633         if (--cr->cr_ref == 0)
  634                 FREE((caddr_t)cr, M_CRED);
  635 }
  636 
  637 /*
  638  * Compare cred structures and return 0 if they match
  639  */
  640 int
  641 crcmp(const struct ucred *cr1, const struct uucred *cr2)
  642 {
  643         return cr1->cr_uid != cr2->cr_uid ||
  644             cr1->cr_gid != cr2->cr_gid ||
  645             cr1->cr_ngroups != (uint32_t)cr2->cr_ngroups ||
  646             memcmp(cr1->cr_groups, cr2->cr_groups, cr1->cr_ngroups);
  647 }
  648 
  649 /*
  650  * Copy cred structure to a new one and free the old one.
  651  */
  652 struct ucred *
  653 crcopy(struct ucred *cr)
  654 {
  655         struct ucred *newcr;
  656 
  657         if (cr->cr_ref == 1)
  658                 return (cr);
  659         newcr = crget();
  660         *newcr = *cr;
  661         crfree(cr);
  662         newcr->cr_ref = 1;
  663         return (newcr);
  664 }
  665 
  666 /*
  667  * Dup cred struct to a new held one.
  668  */
  669 struct ucred *
  670 crdup(const struct ucred *cr)
  671 {
  672         struct ucred *newcr;
  673 
  674         newcr = crget();
  675         *newcr = *cr;
  676         newcr->cr_ref = 1;
  677         return (newcr);
  678 }
  679 
  680 /*
  681  * convert from userland credentials to kernel one
  682  */
  683 void
  684 crcvt(struct ucred *uc, const struct uucred *uuc)
  685 {
  686 
  687         uc->cr_ref = 0;
  688         uc->cr_uid = uuc->cr_uid;
  689         uc->cr_gid = uuc->cr_gid;
  690         uc->cr_ngroups = uuc->cr_ngroups;
  691         (void)memcpy(uc->cr_groups, uuc->cr_groups, sizeof(uuc->cr_groups));
  692 }
  693 
  694 /*
  695  * Get login name, if available.
  696  */
  697 /* ARGSUSED */
  698 int
  699 sys___getlogin(struct lwp *l, void *v, register_t *retval)
  700 {
  701         struct sys___getlogin_args /* {
  702                 syscallarg(char *) namebuf;
  703                 syscallarg(size_t) namelen;
  704         } */ *uap = v;
  705         struct proc *p = l->l_proc;
  706 
  707         if (SCARG(uap, namelen) > sizeof(p->p_pgrp->pg_session->s_login))
  708                 SCARG(uap, namelen) = sizeof(p->p_pgrp->pg_session->s_login);
  709         return (copyout((caddr_t) p->p_pgrp->pg_session->s_login,
  710             (caddr_t) SCARG(uap, namebuf), SCARG(uap, namelen)));
  711 }
  712 
  713 /*
  714  * Set login name.
  715  */
  716 /* ARGSUSED */
  717 int
  718 sys___setlogin(struct lwp *l, void *v, register_t *retval)
  719 {
  720         struct sys___setlogin_args /* {
  721                 syscallarg(const char *) namebuf;
  722         } */ *uap = v;
  723         struct proc *p = l->l_proc;
  724         struct session *s = p->p_pgrp->pg_session;
  725         char newname[sizeof s->s_login + 1];
  726         int error;
  727 
  728         if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
  729                 return (error);
  730         error = copyinstr(SCARG(uap, namebuf), &newname, sizeof newname, NULL);
  731         if (error != 0)
  732                 return (error == ENAMETOOLONG ? EINVAL : error);
  733 
  734         if (s->s_flags & S_LOGIN_SET && p->p_pid != s->s_sid &&
  735             strncmp(newname, s->s_login, sizeof s->s_login) != 0)
  736                 log(LOG_WARNING, "%s (pid %d) changing logname from "
  737                     "%.*s to %s\n", p->p_comm, p->p_pid,
  738                     (int)sizeof s->s_login, s->s_login, newname);
  739         s->s_flags |= S_LOGIN_SET;
  740         strncpy(s->s_login, newname, sizeof s->s_login);
  741         return (0);
  742 }

Cache object: 1aed2a31c8be1e0e8d5f2eb2f316938d


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