kern_prot.c revision 60216
11541Srgrimes/* 21541Srgrimes * Copyright (c) 1982, 1986, 1989, 1990, 1991, 1993 31541Srgrimes * The Regents of the University of California. All rights reserved. 41541Srgrimes * (c) UNIX System Laboratories, Inc. 51541Srgrimes * All or some portions of this file are derived from material licensed 61541Srgrimes * to the University of California by American Telephone and Telegraph 71541Srgrimes * Co. or Unix System Laboratories, Inc. and are reproduced herein with 81541Srgrimes * the permission of UNIX System Laboratories, Inc. 91541Srgrimes * 101541Srgrimes * Redistribution and use in source and binary forms, with or without 111541Srgrimes * modification, are permitted provided that the following conditions 121541Srgrimes * are met: 131541Srgrimes * 1. Redistributions of source code must retain the above copyright 141541Srgrimes * notice, this list of conditions and the following disclaimer. 151541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 161541Srgrimes * notice, this list of conditions and the following disclaimer in the 171541Srgrimes * documentation and/or other materials provided with the distribution. 181541Srgrimes * 3. All advertising materials mentioning features or use of this software 191541Srgrimes * must display the following acknowledgement: 201541Srgrimes * This product includes software developed by the University of 211541Srgrimes * California, Berkeley and its contributors. 221541Srgrimes * 4. Neither the name of the University nor the names of its contributors 231541Srgrimes * may be used to endorse or promote products derived from this software 241541Srgrimes * without specific prior written permission. 251541Srgrimes * 261541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 271541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 281541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 291541Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 301541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 311541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 321541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 331541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 341541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 351541Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 361541Srgrimes * SUCH DAMAGE. 371541Srgrimes * 381541Srgrimes * @(#)kern_prot.c 8.6 (Berkeley) 1/21/94 3950477Speter * $FreeBSD: head/sys/kern/kern_prot.c 60216 2000-05-09 00:58:34Z peter $ 401541Srgrimes */ 411541Srgrimes 421541Srgrimes/* 431541Srgrimes * System calls related to processes and protection 441541Srgrimes */ 451541Srgrimes 4631778Seivind#include "opt_compat.h" 4731778Seivind 481541Srgrimes#include <sys/param.h> 491541Srgrimes#include <sys/acct.h> 501541Srgrimes#include <sys/systm.h> 5112221Sbde#include <sys/sysproto.h> 5241059Speter#include <sys/kernel.h> 531541Srgrimes#include <sys/proc.h> 541541Srgrimes#include <sys/malloc.h> 5531891Ssef#include <sys/pioctl.h> 561541Srgrimes 5730354Sphkstatic MALLOC_DEFINE(M_CRED, "cred", "credentials"); 5830354Sphk 5912221Sbde#ifndef _SYS_SYSPROTO_H_ 6011332Sswallacestruct getpid_args { 611541Srgrimes int dummy; 621541Srgrimes}; 6312221Sbde#endif 641541Srgrimes 6558717Sdillon/* 6658717Sdillon * NOT MP SAFE due to p_pptr access 6758717Sdillon */ 681541Srgrimes/* ARGSUSED */ 691549Srgrimesint 7030994Sphkgetpid(p, uap) 711541Srgrimes struct proc *p; 7211332Sswallace struct getpid_args *uap; 731541Srgrimes{ 741541Srgrimes 7530994Sphk p->p_retval[0] = p->p_pid; 761541Srgrimes#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 7730994Sphk p->p_retval[1] = p->p_pptr->p_pid; 781541Srgrimes#endif 791541Srgrimes return (0); 801541Srgrimes} 811541Srgrimes 8212221Sbde#ifndef _SYS_SYSPROTO_H_ 8311332Sswallacestruct getppid_args { 8411332Sswallace int dummy; 8511332Sswallace}; 8612221Sbde#endif 871541Srgrimes/* ARGSUSED */ 881549Srgrimesint 8930994Sphkgetppid(p, uap) 901541Srgrimes struct proc *p; 9111332Sswallace struct getppid_args *uap; 921541Srgrimes{ 931541Srgrimes 9430994Sphk p->p_retval[0] = p->p_pptr->p_pid; 951541Srgrimes return (0); 961541Srgrimes} 971541Srgrimes 9858717Sdillon/* 9958717Sdillon * Get process group ID; note that POSIX getpgrp takes no parameter 10058717Sdillon * 10158717Sdillon * MP SAFE 10258717Sdillon */ 10312221Sbde#ifndef _SYS_SYSPROTO_H_ 10411332Sswallacestruct getpgrp_args { 10511332Sswallace int dummy; 10611332Sswallace}; 10712221Sbde#endif 10811332Sswallace 1091549Srgrimesint 11030994Sphkgetpgrp(p, uap) 1111541Srgrimes struct proc *p; 11211332Sswallace struct getpgrp_args *uap; 1131541Srgrimes{ 1141541Srgrimes 11530994Sphk p->p_retval[0] = p->p_pgrp->pg_id; 1161541Srgrimes return (0); 1171541Srgrimes} 1181541Srgrimes 11928401Speter/* Get an arbitary pid's process group id */ 12012221Sbde#ifndef _SYS_SYSPROTO_H_ 12128401Speterstruct getpgid_args { 12228401Speter pid_t pid; 12328401Speter}; 12428401Speter#endif 12528401Speter 12628401Speterint 12730994Sphkgetpgid(p, uap) 12828401Speter struct proc *p; 12928401Speter struct getpgid_args *uap; 13028401Speter{ 13141726Struckman struct proc *pt; 13241726Struckman 13341726Struckman pt = p; 13428401Speter if (uap->pid == 0) 13528401Speter goto found; 13628401Speter 13741726Struckman if ((pt = pfind(uap->pid)) == 0) 13828401Speter return ESRCH; 13928401Speterfound: 14041726Struckman p->p_retval[0] = pt->p_pgrp->pg_id; 14128401Speter return 0; 14228401Speter} 14328401Speter 14428401Speter/* 14528401Speter * Get an arbitary pid's session id. 14628401Speter */ 14728401Speter#ifndef _SYS_SYSPROTO_H_ 14828401Speterstruct getsid_args { 14928401Speter pid_t pid; 15028401Speter}; 15128401Speter#endif 15228401Speter 15328401Speterint 15430994Sphkgetsid(p, uap) 15528401Speter struct proc *p; 15628401Speter struct getsid_args *uap; 15728401Speter{ 15841726Struckman struct proc *pt; 15941726Struckman 16041726Struckman pt = p; 16128401Speter if (uap->pid == 0) 16228401Speter goto found; 16328401Speter 16441726Struckman if ((pt == pfind(uap->pid)) == 0) 16528401Speter return ESRCH; 16628401Speterfound: 16741726Struckman p->p_retval[0] = pt->p_session->s_sid; 16828401Speter return 0; 16928401Speter} 17028401Speter 17128401Speter 17258941Sdillon/* 17358941Sdillon * getuid() - MP SAFE 17458941Sdillon */ 17528401Speter#ifndef _SYS_SYSPROTO_H_ 17611332Sswallacestruct getuid_args { 17711332Sswallace int dummy; 17811332Sswallace}; 17912221Sbde#endif 18011332Sswallace 1811541Srgrimes/* ARGSUSED */ 1821549Srgrimesint 18330994Sphkgetuid(p, uap) 1841541Srgrimes struct proc *p; 18511332Sswallace struct getuid_args *uap; 1861541Srgrimes{ 1871541Srgrimes 18830994Sphk p->p_retval[0] = p->p_cred->p_ruid; 1891541Srgrimes#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 19030994Sphk p->p_retval[1] = p->p_ucred->cr_uid; 1911541Srgrimes#endif 1921541Srgrimes return (0); 1931541Srgrimes} 1941541Srgrimes 19558941Sdillon/* 19658941Sdillon * geteuid() - MP SAFE 19758941Sdillon */ 19812221Sbde#ifndef _SYS_SYSPROTO_H_ 19911332Sswallacestruct geteuid_args { 20011332Sswallace int dummy; 20111332Sswallace}; 20212221Sbde#endif 20311332Sswallace 2041541Srgrimes/* ARGSUSED */ 2051549Srgrimesint 20630994Sphkgeteuid(p, uap) 2071541Srgrimes struct proc *p; 20811332Sswallace struct geteuid_args *uap; 2091541Srgrimes{ 2101541Srgrimes 21130994Sphk p->p_retval[0] = p->p_ucred->cr_uid; 2121541Srgrimes return (0); 2131541Srgrimes} 2141541Srgrimes 21558941Sdillon/* 21658941Sdillon * getgid() - MP SAFE 21758941Sdillon */ 21812221Sbde#ifndef _SYS_SYSPROTO_H_ 21911332Sswallacestruct getgid_args { 22011332Sswallace int dummy; 22111332Sswallace}; 22212221Sbde#endif 22311332Sswallace 2241541Srgrimes/* ARGSUSED */ 2251549Srgrimesint 22630994Sphkgetgid(p, uap) 2271541Srgrimes struct proc *p; 22811332Sswallace struct getgid_args *uap; 2291541Srgrimes{ 2301541Srgrimes 23130994Sphk p->p_retval[0] = p->p_cred->p_rgid; 2321541Srgrimes#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 23330994Sphk p->p_retval[1] = p->p_ucred->cr_groups[0]; 2341541Srgrimes#endif 2351541Srgrimes return (0); 2361541Srgrimes} 2371541Srgrimes 2381541Srgrimes/* 2391541Srgrimes * Get effective group ID. The "egid" is groups[0], and could be obtained 2401541Srgrimes * via getgroups. This syscall exists because it is somewhat painful to do 2411541Srgrimes * correctly in a library function. 2421541Srgrimes */ 24312221Sbde#ifndef _SYS_SYSPROTO_H_ 24411332Sswallacestruct getegid_args { 24511332Sswallace int dummy; 24611332Sswallace}; 24712221Sbde#endif 24811332Sswallace 2491541Srgrimes/* ARGSUSED */ 2501549Srgrimesint 25130994Sphkgetegid(p, uap) 2521541Srgrimes struct proc *p; 25311332Sswallace struct getegid_args *uap; 2541541Srgrimes{ 2551541Srgrimes 25630994Sphk p->p_retval[0] = p->p_ucred->cr_groups[0]; 2571541Srgrimes return (0); 2581541Srgrimes} 2591541Srgrimes 26012221Sbde#ifndef _SYS_SYSPROTO_H_ 2611541Srgrimesstruct getgroups_args { 2621541Srgrimes u_int gidsetsize; 2631541Srgrimes gid_t *gidset; 2641541Srgrimes}; 26512221Sbde#endif 2661549Srgrimesint 26730994Sphkgetgroups(p, uap) 2681541Srgrimes struct proc *p; 2691541Srgrimes register struct getgroups_args *uap; 2701541Srgrimes{ 2711541Srgrimes register struct pcred *pc = p->p_cred; 2721541Srgrimes register u_int ngrp; 2731541Srgrimes int error; 2741541Srgrimes 2751541Srgrimes if ((ngrp = uap->gidsetsize) == 0) { 27630994Sphk p->p_retval[0] = pc->pc_ucred->cr_ngroups; 2771541Srgrimes return (0); 2781541Srgrimes } 2791541Srgrimes if (ngrp < pc->pc_ucred->cr_ngroups) 2801541Srgrimes return (EINVAL); 2811541Srgrimes ngrp = pc->pc_ucred->cr_ngroups; 2823098Sphk if ((error = copyout((caddr_t)pc->pc_ucred->cr_groups, 2833098Sphk (caddr_t)uap->gidset, ngrp * sizeof(gid_t)))) 2841541Srgrimes return (error); 28530994Sphk p->p_retval[0] = ngrp; 2861541Srgrimes return (0); 2871541Srgrimes} 2881541Srgrimes 28912221Sbde#ifndef _SYS_SYSPROTO_H_ 29012207Sbdestruct setsid_args { 29111332Sswallace int dummy; 29211332Sswallace}; 29312221Sbde#endif 29411332Sswallace 2951541Srgrimes/* ARGSUSED */ 2961549Srgrimesint 29730994Sphksetsid(p, uap) 2981541Srgrimes register struct proc *p; 29912207Sbde struct setsid_args *uap; 3001541Srgrimes{ 3011541Srgrimes 3021541Srgrimes if (p->p_pgid == p->p_pid || pgfind(p->p_pid)) { 3031541Srgrimes return (EPERM); 3041541Srgrimes } else { 3051541Srgrimes (void)enterpgrp(p, p->p_pid, 1); 30630994Sphk p->p_retval[0] = p->p_pid; 3071541Srgrimes return (0); 3081541Srgrimes } 3091541Srgrimes} 3101541Srgrimes 3111541Srgrimes/* 3121541Srgrimes * set process group (setpgid/old setpgrp) 3131541Srgrimes * 3141541Srgrimes * caller does setpgid(targpid, targpgid) 3151541Srgrimes * 3161541Srgrimes * pid must be caller or child of caller (ESRCH) 3171541Srgrimes * if a child 3181541Srgrimes * pid must be in same session (EPERM) 3191541Srgrimes * pid can't have done an exec (EACCES) 3201541Srgrimes * if pgid != pid 3211541Srgrimes * there must exist some pid in same session having pgid (EPERM) 3221541Srgrimes * pid must not be session leader (EPERM) 3231541Srgrimes */ 32412221Sbde#ifndef _SYS_SYSPROTO_H_ 3251541Srgrimesstruct setpgid_args { 3261541Srgrimes int pid; /* target process id */ 3271541Srgrimes int pgid; /* target pgrp id */ 3281541Srgrimes}; 32912221Sbde#endif 3301541Srgrimes/* ARGSUSED */ 3311549Srgrimesint 33230994Sphksetpgid(curp, uap) 3331541Srgrimes struct proc *curp; 3341541Srgrimes register struct setpgid_args *uap; 3351541Srgrimes{ 3361541Srgrimes register struct proc *targp; /* target process */ 3371541Srgrimes register struct pgrp *pgrp; /* target pgrp */ 3381541Srgrimes 33920677Sbde if (uap->pgid < 0) 34020677Sbde return (EINVAL); 3411541Srgrimes if (uap->pid != 0 && uap->pid != curp->p_pid) { 3421541Srgrimes if ((targp = pfind(uap->pid)) == 0 || !inferior(targp)) 3431541Srgrimes return (ESRCH); 34415985Sdg if (targp->p_pgrp == NULL || targp->p_session != curp->p_session) 3451541Srgrimes return (EPERM); 3461541Srgrimes if (targp->p_flag & P_EXEC) 3471541Srgrimes return (EACCES); 3481541Srgrimes } else 3491541Srgrimes targp = curp; 3501541Srgrimes if (SESS_LEADER(targp)) 3511541Srgrimes return (EPERM); 3521541Srgrimes if (uap->pgid == 0) 3531541Srgrimes uap->pgid = targp->p_pid; 3541541Srgrimes else if (uap->pgid != targp->p_pid) 3551541Srgrimes if ((pgrp = pgfind(uap->pgid)) == 0 || 3561541Srgrimes pgrp->pg_session != curp->p_session) 3571541Srgrimes return (EPERM); 3581541Srgrimes return (enterpgrp(targp, uap->pgid, 0)); 3591541Srgrimes} 3601541Srgrimes 36124448Speter/* 36224448Speter * Use the clause in B.4.2.2 that allows setuid/setgid to be 4.2/4.3BSD 36324448Speter * compatable. It says that setting the uid/gid to euid/egid is a special 36424448Speter * case of "appropriate privilege". Once the rules are expanded out, this 36524448Speter * basically means that setuid(nnn) sets all three id's, in all permitted 36624448Speter * cases unless _POSIX_SAVED_IDS is enabled. In that case, setuid(getuid()) 36724448Speter * does not set the saved id - this is dangerous for traditional BSD 36824448Speter * programs. For this reason, we *really* do not want to set 36924448Speter * _POSIX_SAVED_IDS and do not want to clear POSIX_APPENDIX_B_4_2_2. 37024448Speter */ 37124448Speter#define POSIX_APPENDIX_B_4_2_2 37224448Speter 37312221Sbde#ifndef _SYS_SYSPROTO_H_ 3741541Srgrimesstruct setuid_args { 3751541Srgrimes uid_t uid; 3761541Srgrimes}; 37712221Sbde#endif 3781541Srgrimes/* ARGSUSED */ 3791549Srgrimesint 38030994Sphksetuid(p, uap) 3811541Srgrimes struct proc *p; 3821541Srgrimes struct setuid_args *uap; 3831541Srgrimes{ 3841541Srgrimes register struct pcred *pc = p->p_cred; 3851541Srgrimes register uid_t uid; 3861541Srgrimes int error; 3871541Srgrimes 38824448Speter /* 38924448Speter * See if we have "permission" by POSIX 1003.1 rules. 39024448Speter * 39124448Speter * Note that setuid(geteuid()) is a special case of 39224448Speter * "appropriate privileges" in appendix B.4.2.2. We need 39324448Speter * to use this clause to be compatable with traditional BSD 39424448Speter * semantics. Basically, it means that "setuid(xx)" sets all 39524448Speter * three id's (assuming you have privs). 39624448Speter * 39724448Speter * Notes on the logic. We do things in three steps. 39824448Speter * 1: We determine if the euid is going to change, and do EPERM 39924448Speter * right away. We unconditionally change the euid later if this 40024448Speter * test is satisfied, simplifying that part of the logic. 40124448Speter * 2: We determine if the real and/or saved uid's are going to 40224448Speter * change. Determined by compile options. 40324448Speter * 3: Change euid last. (after tests in #2 for "appropriate privs") 40424448Speter */ 4051541Srgrimes uid = uap->uid; 40624448Speter if (uid != pc->p_ruid && /* allow setuid(getuid()) */ 40717994Sache#ifdef _POSIX_SAVED_IDS 40824448Speter uid != pc->p_svuid && /* allow setuid(saved gid) */ 40917994Sache#endif 41024448Speter#ifdef POSIX_APPENDIX_B_4_2_2 /* Use BSD-compat clause from B.4.2.2 */ 41124448Speter uid != pc->pc_ucred->cr_uid && /* allow setuid(geteuid()) */ 41224448Speter#endif 41346155Sphk (error = suser_xxx(0, p, PRISON_ROOT))) 4141541Srgrimes return (error); 41524448Speter 41624448Speter#ifdef _POSIX_SAVED_IDS 4171541Srgrimes /* 41824448Speter * Do we have "appropriate privileges" (are we root or uid == euid) 41924448Speter * If so, we are changing the real uid and/or saved uid. 4201541Srgrimes */ 42117994Sache if ( 42224448Speter#ifdef POSIX_APPENDIX_B_4_2_2 /* Use the clause from B.4.2.2 */ 42324448Speter uid == pc->pc_ucred->cr_uid || 42417994Sache#endif 42546155Sphk suser_xxx(0, p, PRISON_ROOT) == 0) /* we are using privs */ 42617994Sache#endif 42724448Speter { 42824448Speter /* 42924448Speter * Transfer proc count to new user. 43024448Speter */ 43124448Speter if (uid != pc->p_ruid) { 43224448Speter (void)chgproccnt(pc->p_ruid, -1); 43324448Speter (void)chgproccnt(uid, 1); 43424448Speter } 43524448Speter /* 43624448Speter * Set real uid 43724448Speter */ 43824448Speter if (uid != pc->p_ruid) { 43924448Speter pc->p_ruid = uid; 44031891Ssef setsugid(p); 44124448Speter } 44224448Speter /* 44324448Speter * Set saved uid 44424448Speter * 44524448Speter * XXX always set saved uid even if not _POSIX_SAVED_IDS, as 44624448Speter * the security of seteuid() depends on it. B.4.2.2 says it 44724448Speter * is important that we should do this. 44824448Speter */ 44924448Speter if (pc->p_svuid != uid) { 45024448Speter pc->p_svuid = uid; 45131891Ssef setsugid(p); 45224448Speter } 4538141Sache } 45424448Speter 45524448Speter /* 45624448Speter * In all permitted cases, we are changing the euid. 45724448Speter * Copy credentials so other references do not see our changes. 45824448Speter */ 45924448Speter if (pc->pc_ucred->cr_uid != uid) { 46024448Speter pc->pc_ucred = crcopy(pc->pc_ucred); 46124448Speter pc->pc_ucred->cr_uid = uid; 46231891Ssef setsugid(p); 46324448Speter } 4641541Srgrimes return (0); 4651541Srgrimes} 4661541Srgrimes 46712221Sbde#ifndef _SYS_SYSPROTO_H_ 4681541Srgrimesstruct seteuid_args { 4691541Srgrimes uid_t euid; 4701541Srgrimes}; 47112221Sbde#endif 4721541Srgrimes/* ARGSUSED */ 4731549Srgrimesint 47430994Sphkseteuid(p, uap) 4751541Srgrimes struct proc *p; 4761541Srgrimes struct seteuid_args *uap; 4771541Srgrimes{ 4781541Srgrimes register struct pcred *pc = p->p_cred; 4791541Srgrimes register uid_t euid; 4801541Srgrimes int error; 4811541Srgrimes 4821541Srgrimes euid = uap->euid; 48324449Speter if (euid != pc->p_ruid && /* allow seteuid(getuid()) */ 48424449Speter euid != pc->p_svuid && /* allow seteuid(saved uid) */ 48546155Sphk (error = suser_xxx(0, p, PRISON_ROOT))) 4861541Srgrimes return (error); 4871541Srgrimes /* 4881541Srgrimes * Everything's okay, do it. Copy credentials so other references do 4891541Srgrimes * not see our changes. 4901541Srgrimes */ 49124449Speter if (pc->pc_ucred->cr_uid != euid) { 49224449Speter pc->pc_ucred = crcopy(pc->pc_ucred); 49324449Speter pc->pc_ucred->cr_uid = euid; 49431891Ssef setsugid(p); 49524449Speter } 4961541Srgrimes return (0); 4971541Srgrimes} 4981541Srgrimes 49912221Sbde#ifndef _SYS_SYSPROTO_H_ 5001541Srgrimesstruct setgid_args { 5011541Srgrimes gid_t gid; 5021541Srgrimes}; 50312221Sbde#endif 5041541Srgrimes/* ARGSUSED */ 5051549Srgrimesint 50630994Sphksetgid(p, uap) 5071541Srgrimes struct proc *p; 5081541Srgrimes struct setgid_args *uap; 5091541Srgrimes{ 5101541Srgrimes register struct pcred *pc = p->p_cred; 5111541Srgrimes register gid_t gid; 5121541Srgrimes int error; 5131541Srgrimes 51424448Speter /* 51524448Speter * See if we have "permission" by POSIX 1003.1 rules. 51624448Speter * 51724448Speter * Note that setgid(getegid()) is a special case of 51824448Speter * "appropriate privileges" in appendix B.4.2.2. We need 51924448Speter * to use this clause to be compatable with traditional BSD 52024448Speter * semantics. Basically, it means that "setgid(xx)" sets all 52124448Speter * three id's (assuming you have privs). 52224448Speter * 52324448Speter * For notes on the logic here, see setuid() above. 52424448Speter */ 5251541Srgrimes gid = uap->gid; 52624448Speter if (gid != pc->p_rgid && /* allow setgid(getgid()) */ 52717994Sache#ifdef _POSIX_SAVED_IDS 52824448Speter gid != pc->p_svgid && /* allow setgid(saved gid) */ 52917994Sache#endif 53024448Speter#ifdef POSIX_APPENDIX_B_4_2_2 /* Use BSD-compat clause from B.4.2.2 */ 53124448Speter gid != pc->pc_ucred->cr_groups[0] && /* allow setgid(getegid()) */ 53224448Speter#endif 53346155Sphk (error = suser_xxx(0, p, PRISON_ROOT))) 5341541Srgrimes return (error); 53524448Speter 53617994Sache#ifdef _POSIX_SAVED_IDS 53724448Speter /* 53824448Speter * Do we have "appropriate privileges" (are we root or gid == egid) 53924448Speter * If so, we are changing the real uid and saved gid. 54024448Speter */ 54124448Speter if ( 54224448Speter#ifdef POSIX_APPENDIX_B_4_2_2 /* use the clause from B.4.2.2 */ 54324448Speter gid == pc->pc_ucred->cr_groups[0] || 54417994Sache#endif 54546155Sphk suser_xxx(0, p, PRISON_ROOT) == 0) /* we are using privs */ 54624448Speter#endif 54724448Speter { 54824448Speter /* 54924448Speter * Set real gid 55024448Speter */ 55124448Speter if (pc->p_rgid != gid) { 55224448Speter pc->p_rgid = gid; 55331891Ssef setsugid(p); 55424448Speter } 55524448Speter /* 55624448Speter * Set saved gid 55724448Speter * 55824448Speter * XXX always set saved gid even if not _POSIX_SAVED_IDS, as 55924448Speter * the security of setegid() depends on it. B.4.2.2 says it 56024448Speter * is important that we should do this. 56124448Speter */ 56224448Speter if (pc->p_svgid != gid) { 56324448Speter pc->p_svgid = gid; 56431891Ssef setsugid(p); 56524448Speter } 5668141Sache } 56724448Speter /* 56824448Speter * In all cases permitted cases, we are changing the egid. 56924448Speter * Copy credentials so other references do not see our changes. 57024448Speter */ 57124448Speter if (pc->pc_ucred->cr_groups[0] != gid) { 57224448Speter pc->pc_ucred = crcopy(pc->pc_ucred); 57324448Speter pc->pc_ucred->cr_groups[0] = gid; 57431891Ssef setsugid(p); 57524448Speter } 5761541Srgrimes return (0); 5771541Srgrimes} 5781541Srgrimes 57912221Sbde#ifndef _SYS_SYSPROTO_H_ 5801541Srgrimesstruct setegid_args { 5811541Srgrimes gid_t egid; 5821541Srgrimes}; 58312221Sbde#endif 5841541Srgrimes/* ARGSUSED */ 5851549Srgrimesint 58630994Sphksetegid(p, uap) 5871541Srgrimes struct proc *p; 5881541Srgrimes struct setegid_args *uap; 5891541Srgrimes{ 5901541Srgrimes register struct pcred *pc = p->p_cred; 5911541Srgrimes register gid_t egid; 5921541Srgrimes int error; 5931541Srgrimes 5941541Srgrimes egid = uap->egid; 59524449Speter if (egid != pc->p_rgid && /* allow setegid(getgid()) */ 59624449Speter egid != pc->p_svgid && /* allow setegid(saved gid) */ 59746155Sphk (error = suser_xxx(0, p, PRISON_ROOT))) 5981541Srgrimes return (error); 59924449Speter if (pc->pc_ucred->cr_groups[0] != egid) { 60024449Speter pc->pc_ucred = crcopy(pc->pc_ucred); 60124449Speter pc->pc_ucred->cr_groups[0] = egid; 60231891Ssef setsugid(p); 60324449Speter } 6041541Srgrimes return (0); 6051541Srgrimes} 6061541Srgrimes 60712221Sbde#ifndef _SYS_SYSPROTO_H_ 6081541Srgrimesstruct setgroups_args { 6091541Srgrimes u_int gidsetsize; 6101541Srgrimes gid_t *gidset; 6111541Srgrimes}; 61212221Sbde#endif 6131541Srgrimes/* ARGSUSED */ 6141549Srgrimesint 61530994Sphksetgroups(p, uap) 6161541Srgrimes struct proc *p; 6171541Srgrimes struct setgroups_args *uap; 6181541Srgrimes{ 6191541Srgrimes register struct pcred *pc = p->p_cred; 6201541Srgrimes register u_int ngrp; 6211541Srgrimes int error; 6221541Srgrimes 62346155Sphk if ((error = suser_xxx(0, p, PRISON_ROOT))) 6241541Srgrimes return (error); 62512063Sdg ngrp = uap->gidsetsize; 62624447Speter if (ngrp > NGROUPS) 6271541Srgrimes return (EINVAL); 62824447Speter /* 62924447Speter * XXX A little bit lazy here. We could test if anything has 63024447Speter * changed before crcopy() and setting P_SUGID. 63124447Speter */ 6321541Srgrimes pc->pc_ucred = crcopy(pc->pc_ucred); 63324447Speter if (ngrp < 1) { 63424447Speter /* 63524447Speter * setgroups(0, NULL) is a legitimate way of clearing the 63624447Speter * groups vector on non-BSD systems (which generally do not 63724447Speter * have the egid in the groups[0]). We risk security holes 63824447Speter * when running non-BSD software if we do not do the same. 63924447Speter */ 64024447Speter pc->pc_ucred->cr_ngroups = 1; 64124447Speter } else { 64224447Speter if ((error = copyin((caddr_t)uap->gidset, 64324447Speter (caddr_t)pc->pc_ucred->cr_groups, ngrp * sizeof(gid_t)))) 64424447Speter return (error); 64524447Speter pc->pc_ucred->cr_ngroups = ngrp; 64624447Speter } 64731891Ssef setsugid(p); 6481541Srgrimes return (0); 6491541Srgrimes} 6501541Srgrimes 65112221Sbde#ifndef _SYS_SYSPROTO_H_ 6521541Srgrimesstruct setreuid_args { 6539238Sache uid_t ruid; 6549238Sache uid_t euid; 6551541Srgrimes}; 65612221Sbde#endif 6571541Srgrimes/* ARGSUSED */ 6581549Srgrimesint 65930994Sphksetreuid(p, uap) 6601541Srgrimes register struct proc *p; 6611541Srgrimes struct setreuid_args *uap; 6621541Srgrimes{ 6631541Srgrimes register struct pcred *pc = p->p_cred; 6649238Sache register uid_t ruid, euid; 6658135Sache int error; 6661541Srgrimes 6679238Sache ruid = uap->ruid; 6689238Sache euid = uap->euid; 66943311Sdillon if (((ruid != (uid_t)-1 && ruid != pc->p_ruid && ruid != pc->p_svuid) || 67043311Sdillon (euid != (uid_t)-1 && euid != pc->pc_ucred->cr_uid && 67143311Sdillon euid != pc->p_ruid && euid != pc->p_svuid)) && 67246155Sphk (error = suser_xxx(0, p, PRISON_ROOT)) != 0) 6738135Sache return (error); 6749238Sache 67524450Speter if (euid != (uid_t)-1 && pc->pc_ucred->cr_uid != euid) { 67624450Speter pc->pc_ucred = crcopy(pc->pc_ucred); 6779238Sache pc->pc_ucred->cr_uid = euid; 67831891Ssef setsugid(p); 67924450Speter } 68024450Speter if (ruid != (uid_t)-1 && pc->p_ruid != ruid) { 6819238Sache (void)chgproccnt(pc->p_ruid, -1); 6829238Sache (void)chgproccnt(ruid, 1); 6839238Sache pc->p_ruid = ruid; 68431891Ssef setsugid(p); 6858135Sache } 68624559Speter if ((ruid != (uid_t)-1 || pc->pc_ucred->cr_uid != pc->p_ruid) && 68724559Speter pc->p_svuid != pc->pc_ucred->cr_uid) { 6888111Sache pc->p_svuid = pc->pc_ucred->cr_uid; 68931891Ssef setsugid(p); 69024450Speter } 6918135Sache return (0); 6921541Srgrimes} 6931541Srgrimes 69412221Sbde#ifndef _SYS_SYSPROTO_H_ 6951541Srgrimesstruct setregid_args { 6969238Sache gid_t rgid; 6979238Sache gid_t egid; 6981541Srgrimes}; 69912221Sbde#endif 7001541Srgrimes/* ARGSUSED */ 7011549Srgrimesint 70230994Sphksetregid(p, uap) 7031541Srgrimes register struct proc *p; 7041541Srgrimes struct setregid_args *uap; 7051541Srgrimes{ 7061541Srgrimes register struct pcred *pc = p->p_cred; 7079238Sache register gid_t rgid, egid; 7088135Sache int error; 7091541Srgrimes 7109238Sache rgid = uap->rgid; 7119238Sache egid = uap->egid; 71243311Sdillon if (((rgid != (gid_t)-1 && rgid != pc->p_rgid && rgid != pc->p_svgid) || 71343311Sdillon (egid != (gid_t)-1 && egid != pc->pc_ucred->cr_groups[0] && 71443311Sdillon egid != pc->p_rgid && egid != pc->p_svgid)) && 71546155Sphk (error = suser_xxx(0, p, PRISON_ROOT)) != 0) 7168135Sache return (error); 7179238Sache 71824450Speter if (egid != (gid_t)-1 && pc->pc_ucred->cr_groups[0] != egid) { 71924450Speter pc->pc_ucred = crcopy(pc->pc_ucred); 7209238Sache pc->pc_ucred->cr_groups[0] = egid; 72131891Ssef setsugid(p); 72224450Speter } 72324450Speter if (rgid != (gid_t)-1 && pc->p_rgid != rgid) { 7249238Sache pc->p_rgid = rgid; 72531891Ssef setsugid(p); 72624450Speter } 72724559Speter if ((rgid != (gid_t)-1 || pc->pc_ucred->cr_groups[0] != pc->p_rgid) && 72824559Speter pc->p_svgid != pc->pc_ucred->cr_groups[0]) { 7298111Sache pc->p_svgid = pc->pc_ucred->cr_groups[0]; 73031891Ssef setsugid(p); 73124450Speter } 7328135Sache return (0); 7331541Srgrimes} 7341541Srgrimes 73556115Speter/* 73656115Speter * setresuid(ruid, euid, suid) is like setreuid except control over the 73756115Speter * saved uid is explicit. 73856115Speter */ 73956115Speter 74024453Speter#ifndef _SYS_SYSPROTO_H_ 74156115Speterstruct setresuid_args { 74256115Speter uid_t ruid; 74356115Speter uid_t euid; 74456115Speter uid_t suid; 74556115Speter}; 74656115Speter#endif 74756115Speter/* ARGSUSED */ 74856115Speterint 74956115Spetersetresuid(p, uap) 75056115Speter register struct proc *p; 75156115Speter struct setresuid_args *uap; 75256115Speter{ 75356115Speter register struct pcred *pc = p->p_cred; 75456115Speter register uid_t ruid, euid, suid; 75556115Speter int error; 75656115Speter 75756115Speter ruid = uap->ruid; 75856115Speter euid = uap->euid; 75956115Speter suid = uap->suid; 76056115Speter if (((ruid != (uid_t)-1 && ruid != pc->p_ruid && ruid != pc->p_svuid && 76156115Speter ruid != pc->pc_ucred->cr_uid) || 76256115Speter (euid != (uid_t)-1 && euid != pc->p_ruid && euid != pc->p_svuid && 76356115Speter euid != pc->pc_ucred->cr_uid) || 76456115Speter (suid != (uid_t)-1 && suid != pc->p_ruid && suid != pc->p_svuid && 76556115Speter suid != pc->pc_ucred->cr_uid)) && 76656115Speter (error = suser_xxx(0, p, PRISON_ROOT)) != 0) 76756115Speter return (error); 76856115Speter if (euid != (uid_t)-1 && pc->pc_ucred->cr_uid != euid) { 76956115Speter pc->pc_ucred = crcopy(pc->pc_ucred); 77056115Speter pc->pc_ucred->cr_uid = euid; 77156115Speter setsugid(p); 77256115Speter } 77356115Speter if (ruid != (uid_t)-1 && pc->p_ruid != ruid) { 77456115Speter (void)chgproccnt(pc->p_ruid, -1); 77556115Speter (void)chgproccnt(ruid, 1); 77656115Speter pc->p_ruid = ruid; 77756115Speter setsugid(p); 77856115Speter } 77956115Speter if (suid != (uid_t)-1 && pc->p_svuid != suid) { 78056115Speter pc->p_svuid = suid; 78156115Speter setsugid(p); 78256115Speter } 78356115Speter return (0); 78456115Speter} 78556115Speter 78656115Speter/* 78756115Speter * setresgid(rgid, egid, sgid) is like setregid except control over the 78856115Speter * saved gid is explicit. 78956115Speter */ 79056115Speter 79156115Speter#ifndef _SYS_SYSPROTO_H_ 79256115Speterstruct setresgid_args { 79356115Speter gid_t rgid; 79456115Speter gid_t egid; 79556115Speter gid_t sgid; 79656115Speter}; 79756115Speter#endif 79856115Speter/* ARGSUSED */ 79956115Speterint 80056115Spetersetresgid(p, uap) 80156115Speter register struct proc *p; 80256115Speter struct setresgid_args *uap; 80356115Speter{ 80456115Speter register struct pcred *pc = p->p_cred; 80556115Speter register gid_t rgid, egid, sgid; 80656115Speter int error; 80756115Speter 80856115Speter rgid = uap->rgid; 80956115Speter egid = uap->egid; 81056115Speter sgid = uap->sgid; 81156115Speter if (((rgid != (gid_t)-1 && rgid != pc->p_rgid && rgid != pc->p_svgid && 81256115Speter rgid != pc->pc_ucred->cr_groups[0]) || 81356115Speter (egid != (gid_t)-1 && egid != pc->p_rgid && egid != pc->p_svgid && 81456115Speter egid != pc->pc_ucred->cr_groups[0]) || 81556115Speter (sgid != (gid_t)-1 && sgid != pc->p_rgid && sgid != pc->p_svgid && 81656115Speter sgid != pc->pc_ucred->cr_groups[0])) && 81756115Speter (error = suser_xxx(0, p, PRISON_ROOT)) != 0) 81856115Speter return (error); 81956115Speter 82056115Speter if (egid != (gid_t)-1 && pc->pc_ucred->cr_groups[0] != egid) { 82156115Speter pc->pc_ucred = crcopy(pc->pc_ucred); 82256115Speter pc->pc_ucred->cr_groups[0] = egid; 82356115Speter setsugid(p); 82456115Speter } 82556115Speter if (rgid != (gid_t)-1 && pc->p_rgid != rgid) { 82656115Speter pc->p_rgid = rgid; 82756115Speter setsugid(p); 82856115Speter } 82956115Speter if (sgid != (gid_t)-1 && pc->p_svgid != sgid) { 83056115Speter pc->p_svgid = sgid; 83156115Speter setsugid(p); 83256115Speter } 83356115Speter return (0); 83456115Speter} 83556115Speter 83656115Speter#ifndef _SYS_SYSPROTO_H_ 83756115Speterstruct getresuid_args { 83856115Speter uid_t *ruid; 83956115Speter uid_t *euid; 84056115Speter uid_t *suid; 84156115Speter}; 84256115Speter#endif 84356115Speter/* ARGSUSED */ 84456115Speterint 84556115Spetergetresuid(p, uap) 84656115Speter register struct proc *p; 84756115Speter struct getresuid_args *uap; 84856115Speter{ 84956115Speter struct pcred *pc = p->p_cred; 85056115Speter int error1 = 0, error2 = 0, error3 = 0; 85156115Speter 85256115Speter if (uap->ruid) 85356115Speter error1 = copyout((caddr_t)&pc->p_ruid, 85456115Speter (caddr_t)uap->ruid, sizeof(pc->p_ruid)); 85556115Speter if (uap->euid) 85656115Speter error2 = copyout((caddr_t)&pc->pc_ucred->cr_uid, 85756115Speter (caddr_t)uap->euid, sizeof(pc->pc_ucred->cr_uid)); 85856115Speter if (uap->suid) 85956115Speter error3 = copyout((caddr_t)&pc->p_svuid, 86056115Speter (caddr_t)uap->suid, sizeof(pc->p_svuid)); 86156115Speter return error1 ? error1 : (error2 ? error2 : error3); 86256115Speter} 86356115Speter 86456115Speter#ifndef _SYS_SYSPROTO_H_ 86556115Speterstruct getresgid_args { 86656115Speter gid_t *rgid; 86756115Speter gid_t *egid; 86856115Speter gid_t *sgid; 86956115Speter}; 87056115Speter#endif 87156115Speter/* ARGSUSED */ 87256115Speterint 87356115Spetergetresgid(p, uap) 87456115Speter register struct proc *p; 87556115Speter struct getresgid_args *uap; 87656115Speter{ 87756115Speter struct pcred *pc = p->p_cred; 87856115Speter int error1 = 0, error2 = 0, error3 = 0; 87956115Speter 88056115Speter if (uap->rgid) 88156115Speter error1 = copyout((caddr_t)&pc->p_rgid, 88256115Speter (caddr_t)uap->rgid, sizeof(pc->p_rgid)); 88356115Speter if (uap->egid) 88456115Speter error2 = copyout((caddr_t)&pc->pc_ucred->cr_groups[0], 88556115Speter (caddr_t)uap->egid, sizeof(pc->pc_ucred->cr_groups[0])); 88656115Speter if (uap->sgid) 88756115Speter error3 = copyout((caddr_t)&pc->p_svgid, 88856115Speter (caddr_t)uap->sgid, sizeof(pc->p_svgid)); 88956115Speter return error1 ? error1 : (error2 ? error2 : error3); 89056115Speter} 89156115Speter 89256115Speter 89356115Speter#ifndef _SYS_SYSPROTO_H_ 89424453Speterstruct issetugid_args { 89524453Speter int dummy; 89624453Speter}; 89724453Speter#endif 89824453Speter/* ARGSUSED */ 89924453Speterint 90030994Sphkissetugid(p, uap) 90124453Speter register struct proc *p; 90224453Speter struct issetugid_args *uap; 90324453Speter{ 90424453Speter /* 90524453Speter * Note: OpenBSD sets a P_SUGIDEXEC flag set at execve() time, 90624453Speter * we use P_SUGID because we consider changing the owners as 90724453Speter * "tainting" as well. 90824453Speter * This is significant for procs that start as root and "become" 90924453Speter * a user without an exec - programs cannot know *everything* 91024453Speter * that libc *might* have put in their data segment. 91124453Speter */ 91260216Speter p->p_retval[0] = (p->p_flag & P_SUGID) ? 1 : 0; 91324453Speter return (0); 91424453Speter} 91524453Speter 9161541Srgrimes/* 9171541Srgrimes * Check if gid is a member of the group set. 9181541Srgrimes */ 9191549Srgrimesint 9201541Srgrimesgroupmember(gid, cred) 9211541Srgrimes gid_t gid; 9221541Srgrimes register struct ucred *cred; 9231541Srgrimes{ 9241541Srgrimes register gid_t *gp; 9251541Srgrimes gid_t *egp; 9261541Srgrimes 9271541Srgrimes egp = &(cred->cr_groups[cred->cr_ngroups]); 9281541Srgrimes for (gp = cred->cr_groups; gp < egp; gp++) 9291541Srgrimes if (*gp == gid) 9301541Srgrimes return (1); 9311541Srgrimes return (0); 9321541Srgrimes} 9331541Srgrimes 9341541Srgrimes/* 9351541Srgrimes * Test whether the specified credentials imply "super-user" 9361541Srgrimes * privilege; if so, and we have accounting info, set the flag 9371541Srgrimes * indicating use of super-powers. 9381541Srgrimes * Returns 0 or error. 9391541Srgrimes */ 9401549Srgrimesint 94146112Sphksuser(p) 94246112Sphk struct proc *p; 94346112Sphk{ 94446155Sphk return suser_xxx(0, p, 0); 94546112Sphk} 94646112Sphk 94746112Sphkint 94846155Sphksuser_xxx(cred, proc, flag) 9491541Srgrimes struct ucred *cred; 95046155Sphk struct proc *proc; 95146155Sphk int flag; 9521541Srgrimes{ 95346155Sphk if (!cred && !proc) { 95446155Sphk printf("suser_xxx(): THINK!\n"); 95546155Sphk return (EPERM); 9561541Srgrimes } 95746155Sphk if (!cred) 95846155Sphk cred = proc->p_ucred; 95946155Sphk if (cred->cr_uid != 0) 96046155Sphk return (EPERM); 96146155Sphk if (proc && proc->p_prison && !(flag & PRISON_ROOT)) 96246155Sphk return (EPERM); 96346155Sphk if (proc) 96446155Sphk proc->p_acflag |= ASU; 96546155Sphk return (0); 9661541Srgrimes} 9671541Srgrimes 9681541Srgrimes/* 96953518Sphk * Return zero if p1 can fondle p2, return errno (EPERM/ESRCH) otherwise. 97053518Sphk */ 97153518Sphk 97253518Sphkint 97353518Sphkp_trespass(struct proc *p1, struct proc *p2) 97453518Sphk{ 97553518Sphk 97653518Sphk if (p1 == p2) 97753518Sphk return (0); 97853518Sphk if (!PRISON_CHECK(p1, p2)) 97953518Sphk return (ESRCH); 98053518Sphk if (p1->p_cred->p_ruid == p2->p_cred->p_ruid) 98153518Sphk return (0); 98253518Sphk if (p1->p_ucred->cr_uid == p2->p_cred->p_ruid) 98353518Sphk return (0); 98453518Sphk if (p1->p_cred->p_ruid == p2->p_ucred->cr_uid) 98553518Sphk return (0); 98653518Sphk if (p1->p_ucred->cr_uid == p2->p_ucred->cr_uid) 98753518Sphk return (0); 98853518Sphk if (!suser_xxx(0, p1, PRISON_ROOT)) 98953518Sphk return (0); 99053518Sphk return (EPERM); 99153518Sphk} 99253518Sphk 99353518Sphk/* 9941541Srgrimes * Allocate a zeroed cred structure. 9951541Srgrimes */ 9961541Srgrimesstruct ucred * 9971541Srgrimescrget() 9981541Srgrimes{ 9991541Srgrimes register struct ucred *cr; 10001541Srgrimes 10011541Srgrimes MALLOC(cr, struct ucred *, sizeof(*cr), M_CRED, M_WAITOK); 10021541Srgrimes bzero((caddr_t)cr, sizeof(*cr)); 10031541Srgrimes cr->cr_ref = 1; 10041541Srgrimes return (cr); 10051541Srgrimes} 10061541Srgrimes 10071541Srgrimes/* 10081541Srgrimes * Free a cred structure. 10091541Srgrimes * Throws away space when ref count gets to 0. 10101541Srgrimes */ 10111549Srgrimesvoid 10121541Srgrimescrfree(cr) 10131541Srgrimes struct ucred *cr; 10141541Srgrimes{ 10151541Srgrimes if (--cr->cr_ref == 0) 10161541Srgrimes FREE((caddr_t)cr, M_CRED); 10171541Srgrimes} 10181541Srgrimes 10191541Srgrimes/* 10201541Srgrimes * Copy cred structure to a new one and free the old one. 10211541Srgrimes */ 10221541Srgrimesstruct ucred * 10231541Srgrimescrcopy(cr) 10241541Srgrimes struct ucred *cr; 10251541Srgrimes{ 10261541Srgrimes struct ucred *newcr; 10271541Srgrimes 10281541Srgrimes if (cr->cr_ref == 1) 10291541Srgrimes return (cr); 10301541Srgrimes newcr = crget(); 10311541Srgrimes *newcr = *cr; 10321541Srgrimes crfree(cr); 10331541Srgrimes newcr->cr_ref = 1; 10341541Srgrimes return (newcr); 10351541Srgrimes} 10361541Srgrimes 10371541Srgrimes/* 10381541Srgrimes * Dup cred struct to a new held one. 10391541Srgrimes */ 10401541Srgrimesstruct ucred * 10411541Srgrimescrdup(cr) 10421541Srgrimes struct ucred *cr; 10431541Srgrimes{ 10441541Srgrimes struct ucred *newcr; 10451541Srgrimes 10461541Srgrimes newcr = crget(); 10471541Srgrimes *newcr = *cr; 10481541Srgrimes newcr->cr_ref = 1; 10491541Srgrimes return (newcr); 10501541Srgrimes} 10511541Srgrimes 10521541Srgrimes/* 10531541Srgrimes * Get login name, if available. 10541541Srgrimes */ 105512221Sbde#ifndef _SYS_SYSPROTO_H_ 10561541Srgrimesstruct getlogin_args { 10571541Srgrimes char *namebuf; 10581541Srgrimes u_int namelen; 10591541Srgrimes}; 106012221Sbde#endif 10611541Srgrimes/* ARGSUSED */ 10621549Srgrimesint 106330994Sphkgetlogin(p, uap) 10641541Srgrimes struct proc *p; 10651541Srgrimes struct getlogin_args *uap; 10661541Srgrimes{ 10671541Srgrimes 106823358Sache if (uap->namelen > MAXLOGNAME) 106923359Sache uap->namelen = MAXLOGNAME; 10701541Srgrimes return (copyout((caddr_t) p->p_pgrp->pg_session->s_login, 10711541Srgrimes (caddr_t) uap->namebuf, uap->namelen)); 10721541Srgrimes} 10731541Srgrimes 10741541Srgrimes/* 10751541Srgrimes * Set login name. 10761541Srgrimes */ 107712221Sbde#ifndef _SYS_SYSPROTO_H_ 10781541Srgrimesstruct setlogin_args { 10791541Srgrimes char *namebuf; 10801541Srgrimes}; 108112221Sbde#endif 10821541Srgrimes/* ARGSUSED */ 10831549Srgrimesint 108430994Sphksetlogin(p, uap) 10851541Srgrimes struct proc *p; 10861541Srgrimes struct setlogin_args *uap; 10871541Srgrimes{ 10881541Srgrimes int error; 108923330Sache char logintmp[MAXLOGNAME]; 10901541Srgrimes 109146155Sphk if ((error = suser_xxx(0, p, PRISON_ROOT))) 10921541Srgrimes return (error); 109322522Sdavidn error = copyinstr((caddr_t) uap->namebuf, (caddr_t) logintmp, 109436845Sdfr sizeof(logintmp), (size_t *)0); 10951541Srgrimes if (error == ENAMETOOLONG) 10961541Srgrimes error = EINVAL; 109722522Sdavidn else if (!error) 109822522Sdavidn (void) memcpy(p->p_pgrp->pg_session->s_login, logintmp, 109923330Sache sizeof(logintmp)); 11001541Srgrimes return (error); 11011541Srgrimes} 110231891Ssef 110331891Ssefvoid 110431891Ssefsetsugid(p) 110555338Sphk struct proc *p; 110631891Ssef{ 110731891Ssef p->p_flag |= P_SUGID; 110855707Ssef if (!(p->p_pfsflags & PF_ISUGID)) 110931891Ssef p->p_stops = 0; 111031891Ssef} 1111