The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/kern/kern_prot.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: kern_prot.c,v 1.96 2006/11/01 10:17:58 yamt 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.96 2006/11/01 10:17:58 yamt 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/pool.h>
   56 #include <sys/syslog.h>
   57 #include <sys/resourcevar.h>
   58 #include <sys/kauth.h>
   59 
   60 #include <sys/mount.h>
   61 #include <sys/sa.h>
   62 #include <sys/syscallargs.h>
   63 
   64 #include <sys/malloc.h>
   65 
   66 int     sys_getpid(struct lwp *, void *, register_t *);
   67 int     sys_getpid_with_ppid(struct lwp *, void *, register_t *);
   68 int     sys_getuid(struct lwp *, void *, register_t *);
   69 int     sys_getuid_with_euid(struct lwp *, void *, register_t *);
   70 int     sys_getgid(struct lwp *, void *, register_t *);
   71 int     sys_getgid_with_egid(struct lwp *, void *, register_t *);
   72 
   73 static int grsortu(gid_t *, int);
   74 
   75 /* ARGSUSED */
   76 int
   77 sys_getpid(struct lwp *l, void *v, register_t *retval)
   78 {
   79         struct proc *p = l->l_proc;
   80 
   81         *retval = p->p_pid;
   82         return (0);
   83 }
   84 
   85 /* ARGSUSED */
   86 int
   87 sys_getpid_with_ppid(struct lwp *l, void *v, register_t *retval)
   88 {
   89         struct proc *p = l->l_proc;
   90 
   91         retval[0] = p->p_pid;
   92         retval[1] = p->p_pptr->p_pid;
   93         return (0);
   94 }
   95 
   96 /* ARGSUSED */
   97 int
   98 sys_getppid(struct lwp *l, void *v, register_t *retval)
   99 {
  100         struct proc *p = l->l_proc;
  101 
  102         *retval = p->p_pptr->p_pid;
  103         return (0);
  104 }
  105 
  106 /* Get process group ID; note that POSIX getpgrp takes no parameter */
  107 int
  108 sys_getpgrp(struct lwp *l, void *v, register_t *retval)
  109 {
  110         struct proc *p = l->l_proc;
  111 
  112         *retval = p->p_pgrp->pg_id;
  113         return (0);
  114 }
  115 
  116 /*
  117  * Return the process group ID of the session leader (session ID)
  118  * for the specified process.
  119  */
  120 int
  121 sys_getsid(struct lwp *l, void *v, register_t *retval)
  122 {
  123         struct sys_getsid_args /* {
  124                 syscalldarg(pid_t) pid;
  125         } */ *uap = v;
  126         struct proc *p = l->l_proc;
  127 
  128         if (SCARG(uap, pid) == 0)
  129                 goto found;
  130         if ((p = pfind(SCARG(uap, pid))) == 0)
  131                 return (ESRCH);
  132 found:
  133         *retval = p->p_session->s_sid;
  134         return (0);
  135 }
  136 
  137 int
  138 sys_getpgid(struct lwp *l, void *v, register_t *retval)
  139 {
  140         struct sys_getpgid_args /* {
  141                 syscallarg(pid_t) pid;
  142         } */ *uap = v;
  143         struct proc *p = l->l_proc;
  144 
  145         if (SCARG(uap, pid) == 0)
  146                 goto found;
  147         if ((p = pfind(SCARG(uap, pid))) == 0)
  148                 return (ESRCH);
  149 found:
  150         *retval = p->p_pgid;
  151         return (0);
  152 }
  153 
  154 /* ARGSUSED */
  155 int
  156 sys_getuid(struct lwp *l, void *v, register_t *retval)
  157 {
  158 
  159         *retval = kauth_cred_getuid(l->l_cred);
  160         return (0);
  161 }
  162 
  163 /* ARGSUSED */
  164 int
  165 sys_getuid_with_euid(struct lwp *l, void *v, register_t *retval)
  166 {
  167 
  168         retval[0] = kauth_cred_getuid(l->l_cred);
  169         retval[1] = kauth_cred_geteuid(l->l_cred);
  170         return (0);
  171 }
  172 
  173 /* ARGSUSED */
  174 int
  175 sys_geteuid(struct lwp *l, void *v, register_t *retval)
  176 {
  177 
  178         *retval = kauth_cred_geteuid(l->l_cred);
  179         return (0);
  180 }
  181 
  182 /* ARGSUSED */
  183 int
  184 sys_getgid(struct lwp *l, void *v, register_t *retval)
  185 {
  186 
  187         *retval = kauth_cred_getgid(l->l_cred);
  188         return (0);
  189 }
  190 
  191 /* ARGSUSED */
  192 int
  193 sys_getgid_with_egid(struct lwp *l, void *v, register_t *retval)
  194 {
  195 
  196         retval[0] = kauth_cred_getgid(l->l_cred);
  197         retval[1] = kauth_cred_getegid(l->l_cred);
  198         return (0);
  199 }
  200 
  201 /*
  202  * Get effective group ID.  The "egid" is groups[0], and could be obtained
  203  * via getgroups.  This syscall exists because it is somewhat painful to do
  204  * correctly in a library function.
  205  */
  206 /* ARGSUSED */
  207 int
  208 sys_getegid(struct lwp *l, void *v, register_t *retval)
  209 {
  210 
  211         *retval = kauth_cred_getegid(l->l_cred);
  212         return (0);
  213 }
  214 
  215 int
  216 sys_getgroups(struct lwp *l, void *v, register_t *retval)
  217 {
  218         struct sys_getgroups_args /* {
  219                 syscallarg(int) gidsetsize;
  220                 syscallarg(gid_t *) gidset;
  221         } */ *uap = v;
  222         kauth_cred_t cred = l->l_cred;
  223         u_int ngrp;
  224         int error;
  225         gid_t *grbuf;
  226 
  227         if (SCARG(uap, gidsetsize) == 0) {
  228                 *retval = kauth_cred_ngroups(cred);
  229                 return (0);
  230         } else if (SCARG(uap, gidsetsize) < 0)
  231                 return (EINVAL);
  232         ngrp = SCARG(uap, gidsetsize);
  233         if (ngrp < kauth_cred_ngroups(cred))
  234                 return (EINVAL);
  235         ngrp = kauth_cred_ngroups(cred);
  236 
  237         grbuf = malloc(ngrp * sizeof(*grbuf), M_TEMP, M_WAITOK);
  238         kauth_cred_getgroups(cred, grbuf, ngrp);
  239         error = copyout(grbuf, (caddr_t)SCARG(uap, gidset),
  240                         ngrp * sizeof(gid_t));
  241         free(grbuf, M_TEMP);
  242         if (error)
  243                 return (error);
  244         *retval = ngrp;
  245         return (0);
  246 }
  247 
  248 /* ARGSUSED */
  249 int
  250 sys_setsid(struct lwp *l, void *v, register_t *retval)
  251 {
  252         struct proc *p = l->l_proc;
  253 
  254         if (p->p_pgid == p->p_pid || pgfind(p->p_pid)) {
  255                 return (EPERM);
  256         } else {
  257                 (void)enterpgrp(p, p->p_pid, 1);
  258                 *retval = p->p_pid;
  259                 return (0);
  260         }
  261 }
  262 
  263 /*
  264  * set process group (setpgid/old setpgrp)
  265  *
  266  * caller does setpgid(targpid, targpgid)
  267  *
  268  * pgid must be in valid range (EINVAL)
  269  * pid must be caller or child of caller (ESRCH)
  270  * if a child
  271  *      pid must be in same session (EPERM)
  272  *      pid can't have done an exec (EACCES)
  273  * if pgid != pid
  274  *      there must exist some pid in same session having pgid (EPERM)
  275  * pid must not be session leader (EPERM)
  276  *
  277  * Permission checks now in enterpgrp()
  278  */
  279 /* ARGSUSED */
  280 int
  281 sys_setpgid(struct lwp *l, void *v, register_t *retval)
  282 {
  283         struct sys_setpgid_args /* {
  284                 syscallarg(int) pid;
  285                 syscallarg(int) pgid;
  286         } */ *uap = v;
  287         struct proc *curp = l->l_proc;
  288         struct proc *targp;                     /* target process */
  289 
  290         if (SCARG(uap, pgid) < 0)
  291                 return EINVAL;
  292 
  293         /* XXX MP - there is a horrid race here with targp exiting! */
  294         if (SCARG(uap, pid) != 0 && SCARG(uap, pid) != curp->p_pid) {
  295                 targp = pfind(SCARG(uap, pid));
  296                 if (targp == NULL)
  297                         return ESRCH;
  298         } else
  299                 targp = curp;
  300 
  301         if (SCARG(uap, pgid) == 0)
  302                 SCARG(uap, pgid) = targp->p_pid;
  303         return enterpgrp(targp, SCARG(uap, pgid), 0);
  304 }
  305 
  306 /*
  307  * Set real, effective and saved uids to the requested values.
  308  * non-root callers can only ever change uids to values that match
  309  * one of the processes current uid values.
  310  * This is further restricted by the flags argument.
  311  */
  312 
  313 int
  314 do_setresuid(struct lwp *l, uid_t r, uid_t e, uid_t sv, u_int flags)
  315 {
  316         struct proc *p = l->l_proc;
  317         kauth_cred_t cred;
  318 
  319         /* Get a write lock on the process credential. */
  320         proc_crmod_enter(p);
  321         cred = p->p_cred;
  322 
  323         /*
  324          * Check that the new value is one of the allowed existing values,
  325          * or that we have root privilege.
  326          */
  327         if ((r != -1
  328             && !((flags & ID_R_EQ_R) && r == kauth_cred_getuid(cred))
  329             && !((flags & ID_R_EQ_E) && r == kauth_cred_geteuid(cred))
  330             && !((flags & ID_R_EQ_S) && r == kauth_cred_getsvuid(cred))) ||
  331             (e != -1
  332             && !((flags & ID_E_EQ_R) && e == kauth_cred_getuid(cred))
  333             && !((flags & ID_E_EQ_E) && e == kauth_cred_geteuid(cred))
  334             && !((flags & ID_E_EQ_S) && e == kauth_cred_getsvuid(cred))) ||
  335             (sv != -1
  336             && !((flags & ID_S_EQ_R) && sv == kauth_cred_getuid(cred))
  337             && !((flags & ID_S_EQ_E) && sv == kauth_cred_geteuid(cred))
  338             && !((flags & ID_S_EQ_S) && sv == kauth_cred_getsvuid(cred)))) {
  339                 int error;
  340 
  341                 error = kauth_authorize_process(cred, KAUTH_PROCESS_SETID,
  342                     p, NULL, NULL, NULL);
  343                 if (error != 0) {
  344                         proc_crmod_leave(p, cred, NULL);
  345                         return error;
  346                 }
  347         }
  348 
  349         /* If nothing has changed, short circuit the request */
  350         if ((r == -1 || r == kauth_cred_getuid(cred))
  351             && (e == -1 || e == kauth_cred_geteuid(cred))
  352             && (sv == -1 || sv == kauth_cred_getsvuid(cred))) {
  353                 proc_crmod_leave(p, cred, NULL);
  354                 return 0;
  355         }
  356 
  357         cred = kauth_cred_dup(cred);
  358 
  359         if (r != -1 && r != kauth_cred_getuid(cred)) {
  360                 /* Update count of processes for this user */
  361                 (void)chgproccnt(kauth_cred_getuid(cred), -1);
  362                 (void)chgproccnt(r, 1);
  363                 kauth_cred_setuid(cred, r);
  364         }
  365         if (sv != -1)
  366                 kauth_cred_setsvuid(cred, sv);
  367         if (e != -1)
  368                 kauth_cred_seteuid(cred, e);
  369 
  370         /* Mark process as having changed credentials, stops tracing etc. */
  371         p_sugid(p);
  372 
  373         /* Broadcast our credentials to the process and other LWPs. */
  374         proc_crmod_leave(p, cred, p->p_cred);
  375 
  376         /* Update our copy of the credentials. */
  377         lwp_update_creds(l);
  378 
  379         return 0;
  380 }
  381 
  382 /*
  383  * Set real, effective and saved gids to the requested values.
  384  * non-root callers can only ever change gids to values that match
  385  * one of the processes current gid values.
  386  * This is further restricted by the flags argument.
  387  */
  388 
  389 int
  390 do_setresgid(struct lwp *l, gid_t r, gid_t e, gid_t sv, u_int flags)
  391 {
  392         struct proc *p = l->l_proc;
  393         kauth_cred_t cred;
  394 
  395         /* Get a write lock on the process credential. */
  396         proc_crmod_enter(p);
  397         cred = p->p_cred;
  398 
  399         /*
  400          * check new value is one of the allowed existing values.
  401          * otherwise, check if we have root privilege.
  402          */
  403         if ((r != -1
  404             && !((flags & ID_R_EQ_R) && r == kauth_cred_getgid(cred))
  405             && !((flags & ID_R_EQ_E) && r == kauth_cred_getegid(cred))
  406             && !((flags & ID_R_EQ_S) && r == kauth_cred_getsvgid(cred))) ||
  407             (e != -1
  408             && !((flags & ID_E_EQ_R) && e == kauth_cred_getgid(cred))
  409             && !((flags & ID_E_EQ_E) && e == kauth_cred_getegid(cred))
  410             && !((flags & ID_E_EQ_S) && e == kauth_cred_getsvgid(cred))) ||
  411             (sv != -1
  412             && !((flags & ID_S_EQ_R) && sv == kauth_cred_getgid(cred))
  413             && !((flags & ID_S_EQ_E) && sv == kauth_cred_getegid(cred))
  414             && !((flags & ID_S_EQ_S) && sv == kauth_cred_getsvgid(cred)))) {
  415                 int error;
  416 
  417                 error = kauth_authorize_process(cred, KAUTH_PROCESS_SETID,
  418                     p, NULL, NULL, NULL);
  419                 if (error != 0) {
  420                         proc_crmod_leave(p, cred, NULL);
  421                         return error;
  422                 }
  423         }
  424 
  425         /* If nothing has changed, short circuit the request */
  426         if ((r == -1 || r == kauth_cred_getgid(cred))
  427             && (e == -1 || e == kauth_cred_getegid(cred))
  428             && (sv == -1 || sv == kauth_cred_getsvgid(cred))) {
  429                 proc_crmod_leave(p, cred, NULL);
  430                 return 0;
  431         }
  432 
  433         cred = kauth_cred_dup(cred);
  434 
  435         if (r != -1)
  436                 kauth_cred_setgid(cred, r);
  437         if (sv != -1)
  438                 kauth_cred_setsvgid(cred, sv);
  439         if (e != -1)
  440                 kauth_cred_setegid(cred, e);
  441 
  442         /* Mark process as having changed credentials, stops tracing etc. */
  443         p_sugid(p);
  444 
  445         /* Broadcast our credentials to the process and other LWPs. */
  446         proc_crmod_leave(p, cred, p->p_cred);
  447 
  448         /* Update our copy of the credentials. */
  449         lwp_update_creds(l);
  450 
  451         return 0;
  452 }
  453 
  454 /* ARGSUSED */
  455 int
  456 sys_setuid(struct lwp *l, void *v, register_t *retval)
  457 {
  458         struct sys_setuid_args /* {
  459                 syscallarg(uid_t) uid;
  460         } */ *uap = v;
  461         uid_t uid = SCARG(uap, uid);
  462 
  463         return do_setresuid(l, uid, uid, uid,
  464                             ID_R_EQ_R | ID_E_EQ_R | ID_S_EQ_R);
  465 }
  466 
  467 /* ARGSUSED */
  468 int
  469 sys_seteuid(struct lwp *l, void *v, register_t *retval)
  470 {
  471         struct sys_seteuid_args /* {
  472                 syscallarg(uid_t) euid;
  473         } */ *uap = v;
  474 
  475         return do_setresuid(l, -1, SCARG(uap, euid), -1, ID_E_EQ_R | ID_E_EQ_S);
  476 }
  477 
  478 int
  479 sys_setreuid(struct lwp *l, void *v, register_t *retval)
  480 {
  481         struct sys_setreuid_args /* {
  482                 syscallarg(uid_t) ruid;
  483                 syscallarg(uid_t) euid;
  484         } */ *uap = v;
  485         kauth_cred_t cred = l->l_cred;
  486         uid_t ruid, euid, svuid;
  487 
  488         ruid = SCARG(uap, ruid);
  489         euid = SCARG(uap, euid);
  490 
  491         if (ruid == -1)
  492                 ruid = kauth_cred_getuid(cred);
  493         if (euid == -1)
  494                 euid = kauth_cred_geteuid(cred);
  495 
  496         /* Saved uid is set to the new euid if the ruid changed */
  497         svuid = (ruid == kauth_cred_getuid(cred)) ? -1 : euid;
  498 
  499         return do_setresuid(l, ruid, euid, svuid,
  500                             ID_R_EQ_R | ID_R_EQ_E |
  501                             ID_E_EQ_R | ID_E_EQ_E | ID_E_EQ_S |
  502                             ID_S_EQ_R | ID_S_EQ_E | ID_S_EQ_S);
  503 }
  504 
  505 /* ARGSUSED */
  506 int
  507 sys_setgid(struct lwp *l, void *v, register_t *retval)
  508 {
  509         struct sys_setgid_args /* {
  510                 syscallarg(gid_t) gid;
  511         } */ *uap = v;
  512         gid_t gid = SCARG(uap, gid);
  513 
  514         return do_setresgid(l, gid, gid, gid,
  515                             ID_R_EQ_R | ID_E_EQ_R | ID_S_EQ_R);
  516 }
  517 
  518 /* ARGSUSED */
  519 int
  520 sys_setegid(struct lwp *l, void *v, register_t *retval)
  521 {
  522         struct sys_setegid_args /* {
  523                 syscallarg(gid_t) egid;
  524         } */ *uap = v;
  525 
  526         return do_setresgid(l, -1, SCARG(uap, egid), -1, ID_E_EQ_R | ID_E_EQ_S);
  527 }
  528 
  529 int
  530 sys_setregid(struct lwp *l, void *v, register_t *retval)
  531 {
  532         struct sys_setregid_args /* {
  533                 syscallarg(gid_t) rgid;
  534                 syscallarg(gid_t) egid;
  535         } */ *uap = v;
  536         kauth_cred_t cred = l->l_cred;
  537         gid_t rgid, egid, svgid;
  538 
  539         rgid = SCARG(uap, rgid);
  540         egid = SCARG(uap, egid);
  541 
  542         if (rgid == -1)
  543                 rgid = kauth_cred_getgid(cred);
  544         if (egid == -1)
  545                 egid = kauth_cred_getegid(cred);
  546 
  547         /* Saved gid is set to the new egid if the rgid changed */
  548         svgid = rgid == kauth_cred_getgid(cred) ? -1 : egid;
  549 
  550         return do_setresgid(l, rgid, egid, svgid,
  551                         ID_R_EQ_R | ID_R_EQ_E |
  552                         ID_E_EQ_R | ID_E_EQ_E | ID_E_EQ_S |
  553                         ID_S_EQ_R | ID_S_EQ_E | ID_S_EQ_S);
  554 }
  555 
  556 int
  557 sys_issetugid(struct lwp *l, void *v, register_t *retval)
  558 {
  559         struct proc *p = l->l_proc;
  560 
  561         /*
  562          * Note: OpenBSD sets a P_SUGIDEXEC flag set at execve() time,
  563          * we use P_SUGID because we consider changing the owners as
  564          * "tainting" as well.
  565          * This is significant for procs that start as root and "become"
  566          * a user without an exec - programs cannot know *everything*
  567          * that libc *might* have put in their data segment.
  568          */
  569         *retval = (p->p_flag & P_SUGID) != 0;
  570         return (0);
  571 }
  572 
  573 /*
  574  * sort -u for groups.
  575  */
  576 static int
  577 grsortu(gid_t *grp, int ngrp)
  578 {
  579         const gid_t *src, *end;
  580         gid_t *dst;
  581         gid_t group;
  582         int i, j;
  583 
  584         /* bubble sort */
  585         for (i = 0; i < ngrp; i++)
  586                 for (j = i + 1; j < ngrp; j++)
  587                         if (grp[i] > grp[j]) {
  588                                 gid_t tmp = grp[i];
  589                                 grp[i] = grp[j];
  590                                 grp[j] = tmp;
  591                         }
  592 
  593         /* uniq */
  594         end = grp + ngrp;
  595         src = grp;
  596         dst = grp;
  597         while (src < end) {
  598                 group = *src++;
  599                 while (src < end && *src == group)
  600                         src++;
  601                 *dst++ = group;
  602         }
  603 
  604 #ifdef DIAGNOSTIC
  605         /* zero out the rest of the array */
  606         (void)memset(dst, 0, sizeof(*grp) * (end - dst));
  607 #endif
  608 
  609         return dst - grp;
  610 }
  611 
  612 /* ARGSUSED */
  613 int
  614 sys_setgroups(struct lwp *l, void *v, register_t *retval)
  615 {
  616         struct sys_setgroups_args /* {
  617                 syscallarg(int) gidsetsize;
  618                 syscallarg(const gid_t *) gidset;
  619         } */ *uap = v;
  620         kauth_cred_t cred;
  621         struct proc *p = l->l_proc;
  622         int ngrp;
  623         int error;
  624         gid_t grp[NGROUPS];
  625         size_t grsize;
  626 
  627         proc_crmod_enter(p);
  628         cred = p->p_cred;
  629 
  630         if ((error = kauth_authorize_process(cred, KAUTH_PROCESS_SETID,
  631             p, NULL, NULL, NULL)) != 0)
  632                 goto bad;
  633 
  634         ngrp = SCARG(uap, gidsetsize);
  635         if ((u_int)ngrp > NGROUPS) {
  636                 error = EINVAL;
  637                 goto bad;
  638         }
  639 
  640         grsize = ngrp * sizeof(gid_t);
  641         error = copyin(SCARG(uap, gidset), grp, grsize);
  642         if (error)
  643                 goto bad;
  644 
  645         ngrp = grsortu(grp, ngrp);
  646         cred = kauth_cred_dup(cred);
  647         kauth_cred_setgroups(cred, grp, ngrp, -1);
  648 
  649         /* Mark process as having changed credentials, stops tracing etc. */
  650         p_sugid(p);
  651 
  652         /* Broadcast our credentials to the process and other LWPs. */
  653         proc_crmod_leave(p, cred, p->p_cred);
  654 
  655         /* Update our copy of the credentials. */
  656         lwp_update_creds(l);
  657 
  658         return (0);
  659   bad:
  660         proc_crmod_leave(p, cred, NULL); 
  661         return (error);
  662 }
  663 
  664 /*
  665  * Get login name, if available.
  666  */
  667 /* ARGSUSED */
  668 int
  669 sys___getlogin(struct lwp *l, void *v, register_t *retval)
  670 {
  671         struct sys___getlogin_args /* {
  672                 syscallarg(char *) namebuf;
  673                 syscallarg(size_t) namelen;
  674         } */ *uap = v;
  675         struct proc *p = l->l_proc;
  676 
  677         if (SCARG(uap, namelen) > sizeof(p->p_pgrp->pg_session->s_login))
  678                 SCARG(uap, namelen) = sizeof(p->p_pgrp->pg_session->s_login);
  679         return (copyout((caddr_t) p->p_pgrp->pg_session->s_login,
  680             (caddr_t) SCARG(uap, namebuf), SCARG(uap, namelen)));
  681 }
  682 
  683 /*
  684  * Set login name.
  685  */
  686 /* ARGSUSED */
  687 int
  688 sys___setlogin(struct lwp *l, void *v, register_t *retval)
  689 {
  690         struct sys___setlogin_args /* {
  691                 syscallarg(const char *) namebuf;
  692         } */ *uap = v;
  693         struct proc *p = l->l_proc;
  694         struct session *s = p->p_pgrp->pg_session;
  695         char newname[sizeof s->s_login + 1];
  696         int error;
  697 
  698         if ((error = kauth_authorize_process(l->l_cred, KAUTH_PROCESS_SETID,
  699             p, NULL, NULL, NULL)) != 0)
  700                 return (error);
  701         error = copyinstr(SCARG(uap, namebuf), &newname, sizeof newname, NULL);
  702         if (error != 0)
  703                 return (error == ENAMETOOLONG ? EINVAL : error);
  704 
  705         if (s->s_flags & S_LOGIN_SET && p->p_pid != s->s_sid &&
  706             strncmp(newname, s->s_login, sizeof s->s_login) != 0)
  707                 log(LOG_WARNING, "%s (pid %d) changing logname from "
  708                     "%.*s to %s\n", p->p_comm, p->p_pid,
  709                     (int)sizeof s->s_login, s->s_login, newname);
  710         s->s_flags |= S_LOGIN_SET;
  711         strncpy(s->s_login, newname, sizeof s->s_login);
  712         return (0);
  713 }

Cache object: be9a3defdd0eb44b42f5be83ddd5091c


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