kern_prot.c revision 58717
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 58717 2000-03-28 07:16:37Z dillon $ 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 17228401Speter#ifndef _SYS_SYSPROTO_H_ 17311332Sswallacestruct getuid_args { 17411332Sswallace int dummy; 17511332Sswallace}; 17612221Sbde#endif 17711332Sswallace 17858717Sdillon/* 17958717Sdillon * MP SAFE 18058717Sdillon */ 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 19512221Sbde#ifndef _SYS_SYSPROTO_H_ 19611332Sswallacestruct geteuid_args { 19711332Sswallace int dummy; 19811332Sswallace}; 19912221Sbde#endif 20011332Sswallace 2011541Srgrimes/* ARGSUSED */ 2021549Srgrimesint 20330994Sphkgeteuid(p, uap) 2041541Srgrimes struct proc *p; 20511332Sswallace struct geteuid_args *uap; 2061541Srgrimes{ 2071541Srgrimes 20830994Sphk p->p_retval[0] = p->p_ucred->cr_uid; 2091541Srgrimes return (0); 2101541Srgrimes} 2111541Srgrimes 21212221Sbde#ifndef _SYS_SYSPROTO_H_ 21311332Sswallacestruct getgid_args { 21411332Sswallace int dummy; 21511332Sswallace}; 21612221Sbde#endif 21711332Sswallace 21858717Sdillon/* 21958717Sdillon * MP SAFE 22058717Sdillon */ 2211541Srgrimes/* ARGSUSED */ 2221549Srgrimesint 22330994Sphkgetgid(p, uap) 2241541Srgrimes struct proc *p; 22511332Sswallace struct getgid_args *uap; 2261541Srgrimes{ 2271541Srgrimes 22830994Sphk p->p_retval[0] = p->p_cred->p_rgid; 2291541Srgrimes#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 23030994Sphk p->p_retval[1] = p->p_ucred->cr_groups[0]; 2311541Srgrimes#endif 2321541Srgrimes return (0); 2331541Srgrimes} 2341541Srgrimes 2351541Srgrimes/* 2361541Srgrimes * Get effective group ID. The "egid" is groups[0], and could be obtained 2371541Srgrimes * via getgroups. This syscall exists because it is somewhat painful to do 2381541Srgrimes * correctly in a library function. 2391541Srgrimes */ 24012221Sbde#ifndef _SYS_SYSPROTO_H_ 24111332Sswallacestruct getegid_args { 24211332Sswallace int dummy; 24311332Sswallace}; 24412221Sbde#endif 24511332Sswallace 2461541Srgrimes/* ARGSUSED */ 2471549Srgrimesint 24830994Sphkgetegid(p, uap) 2491541Srgrimes struct proc *p; 25011332Sswallace struct getegid_args *uap; 2511541Srgrimes{ 2521541Srgrimes 25330994Sphk p->p_retval[0] = p->p_ucred->cr_groups[0]; 2541541Srgrimes return (0); 2551541Srgrimes} 2561541Srgrimes 25712221Sbde#ifndef _SYS_SYSPROTO_H_ 2581541Srgrimesstruct getgroups_args { 2591541Srgrimes u_int gidsetsize; 2601541Srgrimes gid_t *gidset; 2611541Srgrimes}; 26212221Sbde#endif 2631549Srgrimesint 26430994Sphkgetgroups(p, uap) 2651541Srgrimes struct proc *p; 2661541Srgrimes register struct getgroups_args *uap; 2671541Srgrimes{ 2681541Srgrimes register struct pcred *pc = p->p_cred; 2691541Srgrimes register u_int ngrp; 2701541Srgrimes int error; 2711541Srgrimes 2721541Srgrimes if ((ngrp = uap->gidsetsize) == 0) { 27330994Sphk p->p_retval[0] = pc->pc_ucred->cr_ngroups; 2741541Srgrimes return (0); 2751541Srgrimes } 2761541Srgrimes if (ngrp < pc->pc_ucred->cr_ngroups) 2771541Srgrimes return (EINVAL); 2781541Srgrimes ngrp = pc->pc_ucred->cr_ngroups; 2793098Sphk if ((error = copyout((caddr_t)pc->pc_ucred->cr_groups, 2803098Sphk (caddr_t)uap->gidset, ngrp * sizeof(gid_t)))) 2811541Srgrimes return (error); 28230994Sphk p->p_retval[0] = ngrp; 2831541Srgrimes return (0); 2841541Srgrimes} 2851541Srgrimes 28612221Sbde#ifndef _SYS_SYSPROTO_H_ 28712207Sbdestruct setsid_args { 28811332Sswallace int dummy; 28911332Sswallace}; 29012221Sbde#endif 29111332Sswallace 2921541Srgrimes/* ARGSUSED */ 2931549Srgrimesint 29430994Sphksetsid(p, uap) 2951541Srgrimes register struct proc *p; 29612207Sbde struct setsid_args *uap; 2971541Srgrimes{ 2981541Srgrimes 2991541Srgrimes if (p->p_pgid == p->p_pid || pgfind(p->p_pid)) { 3001541Srgrimes return (EPERM); 3011541Srgrimes } else { 3021541Srgrimes (void)enterpgrp(p, p->p_pid, 1); 30330994Sphk p->p_retval[0] = p->p_pid; 3041541Srgrimes return (0); 3051541Srgrimes } 3061541Srgrimes} 3071541Srgrimes 3081541Srgrimes/* 3091541Srgrimes * set process group (setpgid/old setpgrp) 3101541Srgrimes * 3111541Srgrimes * caller does setpgid(targpid, targpgid) 3121541Srgrimes * 3131541Srgrimes * pid must be caller or child of caller (ESRCH) 3141541Srgrimes * if a child 3151541Srgrimes * pid must be in same session (EPERM) 3161541Srgrimes * pid can't have done an exec (EACCES) 3171541Srgrimes * if pgid != pid 3181541Srgrimes * there must exist some pid in same session having pgid (EPERM) 3191541Srgrimes * pid must not be session leader (EPERM) 3201541Srgrimes */ 32112221Sbde#ifndef _SYS_SYSPROTO_H_ 3221541Srgrimesstruct setpgid_args { 3231541Srgrimes int pid; /* target process id */ 3241541Srgrimes int pgid; /* target pgrp id */ 3251541Srgrimes}; 32612221Sbde#endif 3271541Srgrimes/* ARGSUSED */ 3281549Srgrimesint 32930994Sphksetpgid(curp, uap) 3301541Srgrimes struct proc *curp; 3311541Srgrimes register struct setpgid_args *uap; 3321541Srgrimes{ 3331541Srgrimes register struct proc *targp; /* target process */ 3341541Srgrimes register struct pgrp *pgrp; /* target pgrp */ 3351541Srgrimes 33620677Sbde if (uap->pgid < 0) 33720677Sbde return (EINVAL); 3381541Srgrimes if (uap->pid != 0 && uap->pid != curp->p_pid) { 3391541Srgrimes if ((targp = pfind(uap->pid)) == 0 || !inferior(targp)) 3401541Srgrimes return (ESRCH); 34115985Sdg if (targp->p_pgrp == NULL || targp->p_session != curp->p_session) 3421541Srgrimes return (EPERM); 3431541Srgrimes if (targp->p_flag & P_EXEC) 3441541Srgrimes return (EACCES); 3451541Srgrimes } else 3461541Srgrimes targp = curp; 3471541Srgrimes if (SESS_LEADER(targp)) 3481541Srgrimes return (EPERM); 3491541Srgrimes if (uap->pgid == 0) 3501541Srgrimes uap->pgid = targp->p_pid; 3511541Srgrimes else if (uap->pgid != targp->p_pid) 3521541Srgrimes if ((pgrp = pgfind(uap->pgid)) == 0 || 3531541Srgrimes pgrp->pg_session != curp->p_session) 3541541Srgrimes return (EPERM); 3551541Srgrimes return (enterpgrp(targp, uap->pgid, 0)); 3561541Srgrimes} 3571541Srgrimes 35824448Speter/* 35924448Speter * Use the clause in B.4.2.2 that allows setuid/setgid to be 4.2/4.3BSD 36024448Speter * compatable. It says that setting the uid/gid to euid/egid is a special 36124448Speter * case of "appropriate privilege". Once the rules are expanded out, this 36224448Speter * basically means that setuid(nnn) sets all three id's, in all permitted 36324448Speter * cases unless _POSIX_SAVED_IDS is enabled. In that case, setuid(getuid()) 36424448Speter * does not set the saved id - this is dangerous for traditional BSD 36524448Speter * programs. For this reason, we *really* do not want to set 36624448Speter * _POSIX_SAVED_IDS and do not want to clear POSIX_APPENDIX_B_4_2_2. 36724448Speter */ 36824448Speter#define POSIX_APPENDIX_B_4_2_2 36924448Speter 37012221Sbde#ifndef _SYS_SYSPROTO_H_ 3711541Srgrimesstruct setuid_args { 3721541Srgrimes uid_t uid; 3731541Srgrimes}; 37412221Sbde#endif 3751541Srgrimes/* ARGSUSED */ 3761549Srgrimesint 37730994Sphksetuid(p, uap) 3781541Srgrimes struct proc *p; 3791541Srgrimes struct setuid_args *uap; 3801541Srgrimes{ 3811541Srgrimes register struct pcred *pc = p->p_cred; 3821541Srgrimes register uid_t uid; 3831541Srgrimes int error; 3841541Srgrimes 38524448Speter /* 38624448Speter * See if we have "permission" by POSIX 1003.1 rules. 38724448Speter * 38824448Speter * Note that setuid(geteuid()) is a special case of 38924448Speter * "appropriate privileges" in appendix B.4.2.2. We need 39024448Speter * to use this clause to be compatable with traditional BSD 39124448Speter * semantics. Basically, it means that "setuid(xx)" sets all 39224448Speter * three id's (assuming you have privs). 39324448Speter * 39424448Speter * Notes on the logic. We do things in three steps. 39524448Speter * 1: We determine if the euid is going to change, and do EPERM 39624448Speter * right away. We unconditionally change the euid later if this 39724448Speter * test is satisfied, simplifying that part of the logic. 39824448Speter * 2: We determine if the real and/or saved uid's are going to 39924448Speter * change. Determined by compile options. 40024448Speter * 3: Change euid last. (after tests in #2 for "appropriate privs") 40124448Speter */ 4021541Srgrimes uid = uap->uid; 40324448Speter if (uid != pc->p_ruid && /* allow setuid(getuid()) */ 40417994Sache#ifdef _POSIX_SAVED_IDS 40524448Speter uid != pc->p_svuid && /* allow setuid(saved gid) */ 40617994Sache#endif 40724448Speter#ifdef POSIX_APPENDIX_B_4_2_2 /* Use BSD-compat clause from B.4.2.2 */ 40824448Speter uid != pc->pc_ucred->cr_uid && /* allow setuid(geteuid()) */ 40924448Speter#endif 41046155Sphk (error = suser_xxx(0, p, PRISON_ROOT))) 4111541Srgrimes return (error); 41224448Speter 41324448Speter#ifdef _POSIX_SAVED_IDS 4141541Srgrimes /* 41524448Speter * Do we have "appropriate privileges" (are we root or uid == euid) 41624448Speter * If so, we are changing the real uid and/or saved uid. 4171541Srgrimes */ 41817994Sache if ( 41924448Speter#ifdef POSIX_APPENDIX_B_4_2_2 /* Use the clause from B.4.2.2 */ 42024448Speter uid == pc->pc_ucred->cr_uid || 42117994Sache#endif 42246155Sphk suser_xxx(0, p, PRISON_ROOT) == 0) /* we are using privs */ 42317994Sache#endif 42424448Speter { 42524448Speter /* 42624448Speter * Transfer proc count to new user. 42724448Speter */ 42824448Speter if (uid != pc->p_ruid) { 42924448Speter (void)chgproccnt(pc->p_ruid, -1); 43024448Speter (void)chgproccnt(uid, 1); 43124448Speter } 43224448Speter /* 43324448Speter * Set real uid 43424448Speter */ 43524448Speter if (uid != pc->p_ruid) { 43624448Speter pc->p_ruid = uid; 43731891Ssef setsugid(p); 43824448Speter } 43924448Speter /* 44024448Speter * Set saved uid 44124448Speter * 44224448Speter * XXX always set saved uid even if not _POSIX_SAVED_IDS, as 44324448Speter * the security of seteuid() depends on it. B.4.2.2 says it 44424448Speter * is important that we should do this. 44524448Speter */ 44624448Speter if (pc->p_svuid != uid) { 44724448Speter pc->p_svuid = uid; 44831891Ssef setsugid(p); 44924448Speter } 4508141Sache } 45124448Speter 45224448Speter /* 45324448Speter * In all permitted cases, we are changing the euid. 45424448Speter * Copy credentials so other references do not see our changes. 45524448Speter */ 45624448Speter if (pc->pc_ucred->cr_uid != uid) { 45724448Speter pc->pc_ucred = crcopy(pc->pc_ucred); 45824448Speter pc->pc_ucred->cr_uid = uid; 45931891Ssef setsugid(p); 46024448Speter } 4611541Srgrimes return (0); 4621541Srgrimes} 4631541Srgrimes 46412221Sbde#ifndef _SYS_SYSPROTO_H_ 4651541Srgrimesstruct seteuid_args { 4661541Srgrimes uid_t euid; 4671541Srgrimes}; 46812221Sbde#endif 4691541Srgrimes/* ARGSUSED */ 4701549Srgrimesint 47130994Sphkseteuid(p, uap) 4721541Srgrimes struct proc *p; 4731541Srgrimes struct seteuid_args *uap; 4741541Srgrimes{ 4751541Srgrimes register struct pcred *pc = p->p_cred; 4761541Srgrimes register uid_t euid; 4771541Srgrimes int error; 4781541Srgrimes 4791541Srgrimes euid = uap->euid; 48024449Speter if (euid != pc->p_ruid && /* allow seteuid(getuid()) */ 48124449Speter euid != pc->p_svuid && /* allow seteuid(saved uid) */ 48246155Sphk (error = suser_xxx(0, p, PRISON_ROOT))) 4831541Srgrimes return (error); 4841541Srgrimes /* 4851541Srgrimes * Everything's okay, do it. Copy credentials so other references do 4861541Srgrimes * not see our changes. 4871541Srgrimes */ 48824449Speter if (pc->pc_ucred->cr_uid != euid) { 48924449Speter pc->pc_ucred = crcopy(pc->pc_ucred); 49024449Speter pc->pc_ucred->cr_uid = euid; 49131891Ssef setsugid(p); 49224449Speter } 4931541Srgrimes return (0); 4941541Srgrimes} 4951541Srgrimes 49612221Sbde#ifndef _SYS_SYSPROTO_H_ 4971541Srgrimesstruct setgid_args { 4981541Srgrimes gid_t gid; 4991541Srgrimes}; 50012221Sbde#endif 5011541Srgrimes/* ARGSUSED */ 5021549Srgrimesint 50330994Sphksetgid(p, uap) 5041541Srgrimes struct proc *p; 5051541Srgrimes struct setgid_args *uap; 5061541Srgrimes{ 5071541Srgrimes register struct pcred *pc = p->p_cred; 5081541Srgrimes register gid_t gid; 5091541Srgrimes int error; 5101541Srgrimes 51124448Speter /* 51224448Speter * See if we have "permission" by POSIX 1003.1 rules. 51324448Speter * 51424448Speter * Note that setgid(getegid()) is a special case of 51524448Speter * "appropriate privileges" in appendix B.4.2.2. We need 51624448Speter * to use this clause to be compatable with traditional BSD 51724448Speter * semantics. Basically, it means that "setgid(xx)" sets all 51824448Speter * three id's (assuming you have privs). 51924448Speter * 52024448Speter * For notes on the logic here, see setuid() above. 52124448Speter */ 5221541Srgrimes gid = uap->gid; 52324448Speter if (gid != pc->p_rgid && /* allow setgid(getgid()) */ 52417994Sache#ifdef _POSIX_SAVED_IDS 52524448Speter gid != pc->p_svgid && /* allow setgid(saved gid) */ 52617994Sache#endif 52724448Speter#ifdef POSIX_APPENDIX_B_4_2_2 /* Use BSD-compat clause from B.4.2.2 */ 52824448Speter gid != pc->pc_ucred->cr_groups[0] && /* allow setgid(getegid()) */ 52924448Speter#endif 53046155Sphk (error = suser_xxx(0, p, PRISON_ROOT))) 5311541Srgrimes return (error); 53224448Speter 53317994Sache#ifdef _POSIX_SAVED_IDS 53424448Speter /* 53524448Speter * Do we have "appropriate privileges" (are we root or gid == egid) 53624448Speter * If so, we are changing the real uid and saved gid. 53724448Speter */ 53824448Speter if ( 53924448Speter#ifdef POSIX_APPENDIX_B_4_2_2 /* use the clause from B.4.2.2 */ 54024448Speter gid == pc->pc_ucred->cr_groups[0] || 54117994Sache#endif 54246155Sphk suser_xxx(0, p, PRISON_ROOT) == 0) /* we are using privs */ 54324448Speter#endif 54424448Speter { 54524448Speter /* 54624448Speter * Set real gid 54724448Speter */ 54824448Speter if (pc->p_rgid != gid) { 54924448Speter pc->p_rgid = gid; 55031891Ssef setsugid(p); 55124448Speter } 55224448Speter /* 55324448Speter * Set saved gid 55424448Speter * 55524448Speter * XXX always set saved gid even if not _POSIX_SAVED_IDS, as 55624448Speter * the security of setegid() depends on it. B.4.2.2 says it 55724448Speter * is important that we should do this. 55824448Speter */ 55924448Speter if (pc->p_svgid != gid) { 56024448Speter pc->p_svgid = gid; 56131891Ssef setsugid(p); 56224448Speter } 5638141Sache } 56424448Speter /* 56524448Speter * In all cases permitted cases, we are changing the egid. 56624448Speter * Copy credentials so other references do not see our changes. 56724448Speter */ 56824448Speter if (pc->pc_ucred->cr_groups[0] != gid) { 56924448Speter pc->pc_ucred = crcopy(pc->pc_ucred); 57024448Speter pc->pc_ucred->cr_groups[0] = gid; 57131891Ssef setsugid(p); 57224448Speter } 5731541Srgrimes return (0); 5741541Srgrimes} 5751541Srgrimes 57612221Sbde#ifndef _SYS_SYSPROTO_H_ 5771541Srgrimesstruct setegid_args { 5781541Srgrimes gid_t egid; 5791541Srgrimes}; 58012221Sbde#endif 5811541Srgrimes/* ARGSUSED */ 5821549Srgrimesint 58330994Sphksetegid(p, uap) 5841541Srgrimes struct proc *p; 5851541Srgrimes struct setegid_args *uap; 5861541Srgrimes{ 5871541Srgrimes register struct pcred *pc = p->p_cred; 5881541Srgrimes register gid_t egid; 5891541Srgrimes int error; 5901541Srgrimes 5911541Srgrimes egid = uap->egid; 59224449Speter if (egid != pc->p_rgid && /* allow setegid(getgid()) */ 59324449Speter egid != pc->p_svgid && /* allow setegid(saved gid) */ 59446155Sphk (error = suser_xxx(0, p, PRISON_ROOT))) 5951541Srgrimes return (error); 59624449Speter if (pc->pc_ucred->cr_groups[0] != egid) { 59724449Speter pc->pc_ucred = crcopy(pc->pc_ucred); 59824449Speter pc->pc_ucred->cr_groups[0] = egid; 59931891Ssef setsugid(p); 60024449Speter } 6011541Srgrimes return (0); 6021541Srgrimes} 6031541Srgrimes 60412221Sbde#ifndef _SYS_SYSPROTO_H_ 6051541Srgrimesstruct setgroups_args { 6061541Srgrimes u_int gidsetsize; 6071541Srgrimes gid_t *gidset; 6081541Srgrimes}; 60912221Sbde#endif 6101541Srgrimes/* ARGSUSED */ 6111549Srgrimesint 61230994Sphksetgroups(p, uap) 6131541Srgrimes struct proc *p; 6141541Srgrimes struct setgroups_args *uap; 6151541Srgrimes{ 6161541Srgrimes register struct pcred *pc = p->p_cred; 6171541Srgrimes register u_int ngrp; 6181541Srgrimes int error; 6191541Srgrimes 62046155Sphk if ((error = suser_xxx(0, p, PRISON_ROOT))) 6211541Srgrimes return (error); 62212063Sdg ngrp = uap->gidsetsize; 62324447Speter if (ngrp > NGROUPS) 6241541Srgrimes return (EINVAL); 62524447Speter /* 62624447Speter * XXX A little bit lazy here. We could test if anything has 62724447Speter * changed before crcopy() and setting P_SUGID. 62824447Speter */ 6291541Srgrimes pc->pc_ucred = crcopy(pc->pc_ucred); 63024447Speter if (ngrp < 1) { 63124447Speter /* 63224447Speter * setgroups(0, NULL) is a legitimate way of clearing the 63324447Speter * groups vector on non-BSD systems (which generally do not 63424447Speter * have the egid in the groups[0]). We risk security holes 63524447Speter * when running non-BSD software if we do not do the same. 63624447Speter */ 63724447Speter pc->pc_ucred->cr_ngroups = 1; 63824447Speter } else { 63924447Speter if ((error = copyin((caddr_t)uap->gidset, 64024447Speter (caddr_t)pc->pc_ucred->cr_groups, ngrp * sizeof(gid_t)))) 64124447Speter return (error); 64224447Speter pc->pc_ucred->cr_ngroups = ngrp; 64324447Speter } 64431891Ssef setsugid(p); 6451541Srgrimes return (0); 6461541Srgrimes} 6471541Srgrimes 64812221Sbde#ifndef _SYS_SYSPROTO_H_ 6491541Srgrimesstruct setreuid_args { 6509238Sache uid_t ruid; 6519238Sache uid_t euid; 6521541Srgrimes}; 65312221Sbde#endif 6541541Srgrimes/* ARGSUSED */ 6551549Srgrimesint 65630994Sphksetreuid(p, uap) 6571541Srgrimes register struct proc *p; 6581541Srgrimes struct setreuid_args *uap; 6591541Srgrimes{ 6601541Srgrimes register struct pcred *pc = p->p_cred; 6619238Sache register uid_t ruid, euid; 6628135Sache int error; 6631541Srgrimes 6649238Sache ruid = uap->ruid; 6659238Sache euid = uap->euid; 66643311Sdillon if (((ruid != (uid_t)-1 && ruid != pc->p_ruid && ruid != pc->p_svuid) || 66743311Sdillon (euid != (uid_t)-1 && euid != pc->pc_ucred->cr_uid && 66843311Sdillon euid != pc->p_ruid && euid != pc->p_svuid)) && 66946155Sphk (error = suser_xxx(0, p, PRISON_ROOT)) != 0) 6708135Sache return (error); 6719238Sache 67224450Speter if (euid != (uid_t)-1 && pc->pc_ucred->cr_uid != euid) { 67324450Speter pc->pc_ucred = crcopy(pc->pc_ucred); 6749238Sache pc->pc_ucred->cr_uid = euid; 67531891Ssef setsugid(p); 67624450Speter } 67724450Speter if (ruid != (uid_t)-1 && pc->p_ruid != ruid) { 6789238Sache (void)chgproccnt(pc->p_ruid, -1); 6799238Sache (void)chgproccnt(ruid, 1); 6809238Sache pc->p_ruid = ruid; 68131891Ssef setsugid(p); 6828135Sache } 68324559Speter if ((ruid != (uid_t)-1 || pc->pc_ucred->cr_uid != pc->p_ruid) && 68424559Speter pc->p_svuid != pc->pc_ucred->cr_uid) { 6858111Sache pc->p_svuid = pc->pc_ucred->cr_uid; 68631891Ssef setsugid(p); 68724450Speter } 6888135Sache return (0); 6891541Srgrimes} 6901541Srgrimes 69112221Sbde#ifndef _SYS_SYSPROTO_H_ 6921541Srgrimesstruct setregid_args { 6939238Sache gid_t rgid; 6949238Sache gid_t egid; 6951541Srgrimes}; 69612221Sbde#endif 6971541Srgrimes/* ARGSUSED */ 6981549Srgrimesint 69930994Sphksetregid(p, uap) 7001541Srgrimes register struct proc *p; 7011541Srgrimes struct setregid_args *uap; 7021541Srgrimes{ 7031541Srgrimes register struct pcred *pc = p->p_cred; 7049238Sache register gid_t rgid, egid; 7058135Sache int error; 7061541Srgrimes 7079238Sache rgid = uap->rgid; 7089238Sache egid = uap->egid; 70943311Sdillon if (((rgid != (gid_t)-1 && rgid != pc->p_rgid && rgid != pc->p_svgid) || 71043311Sdillon (egid != (gid_t)-1 && egid != pc->pc_ucred->cr_groups[0] && 71143311Sdillon egid != pc->p_rgid && egid != pc->p_svgid)) && 71246155Sphk (error = suser_xxx(0, p, PRISON_ROOT)) != 0) 7138135Sache return (error); 7149238Sache 71524450Speter if (egid != (gid_t)-1 && pc->pc_ucred->cr_groups[0] != egid) { 71624450Speter pc->pc_ucred = crcopy(pc->pc_ucred); 7179238Sache pc->pc_ucred->cr_groups[0] = egid; 71831891Ssef setsugid(p); 71924450Speter } 72024450Speter if (rgid != (gid_t)-1 && pc->p_rgid != rgid) { 7219238Sache pc->p_rgid = rgid; 72231891Ssef setsugid(p); 72324450Speter } 72424559Speter if ((rgid != (gid_t)-1 || pc->pc_ucred->cr_groups[0] != pc->p_rgid) && 72524559Speter pc->p_svgid != pc->pc_ucred->cr_groups[0]) { 7268111Sache pc->p_svgid = pc->pc_ucred->cr_groups[0]; 72731891Ssef setsugid(p); 72824450Speter } 7298135Sache return (0); 7301541Srgrimes} 7311541Srgrimes 73256115Speter/* 73356115Speter * setresuid(ruid, euid, suid) is like setreuid except control over the 73456115Speter * saved uid is explicit. 73556115Speter */ 73656115Speter 73724453Speter#ifndef _SYS_SYSPROTO_H_ 73856115Speterstruct setresuid_args { 73956115Speter uid_t ruid; 74056115Speter uid_t euid; 74156115Speter uid_t suid; 74256115Speter}; 74356115Speter#endif 74456115Speter/* ARGSUSED */ 74556115Speterint 74656115Spetersetresuid(p, uap) 74756115Speter register struct proc *p; 74856115Speter struct setresuid_args *uap; 74956115Speter{ 75056115Speter register struct pcred *pc = p->p_cred; 75156115Speter register uid_t ruid, euid, suid; 75256115Speter int error; 75356115Speter 75456115Speter ruid = uap->ruid; 75556115Speter euid = uap->euid; 75656115Speter suid = uap->suid; 75756115Speter if (((ruid != (uid_t)-1 && ruid != pc->p_ruid && ruid != pc->p_svuid && 75856115Speter ruid != pc->pc_ucred->cr_uid) || 75956115Speter (euid != (uid_t)-1 && euid != pc->p_ruid && euid != pc->p_svuid && 76056115Speter euid != pc->pc_ucred->cr_uid) || 76156115Speter (suid != (uid_t)-1 && suid != pc->p_ruid && suid != pc->p_svuid && 76256115Speter suid != pc->pc_ucred->cr_uid)) && 76356115Speter (error = suser_xxx(0, p, PRISON_ROOT)) != 0) 76456115Speter return (error); 76556115Speter if (euid != (uid_t)-1 && pc->pc_ucred->cr_uid != euid) { 76656115Speter pc->pc_ucred = crcopy(pc->pc_ucred); 76756115Speter pc->pc_ucred->cr_uid = euid; 76856115Speter setsugid(p); 76956115Speter } 77056115Speter if (ruid != (uid_t)-1 && pc->p_ruid != ruid) { 77156115Speter (void)chgproccnt(pc->p_ruid, -1); 77256115Speter (void)chgproccnt(ruid, 1); 77356115Speter pc->p_ruid = ruid; 77456115Speter setsugid(p); 77556115Speter } 77656115Speter if (suid != (uid_t)-1 && pc->p_svuid != suid) { 77756115Speter pc->p_svuid = suid; 77856115Speter setsugid(p); 77956115Speter } 78056115Speter return (0); 78156115Speter} 78256115Speter 78356115Speter/* 78456115Speter * setresgid(rgid, egid, sgid) is like setregid except control over the 78556115Speter * saved gid is explicit. 78656115Speter */ 78756115Speter 78856115Speter#ifndef _SYS_SYSPROTO_H_ 78956115Speterstruct setresgid_args { 79056115Speter gid_t rgid; 79156115Speter gid_t egid; 79256115Speter gid_t sgid; 79356115Speter}; 79456115Speter#endif 79556115Speter/* ARGSUSED */ 79656115Speterint 79756115Spetersetresgid(p, uap) 79856115Speter register struct proc *p; 79956115Speter struct setresgid_args *uap; 80056115Speter{ 80156115Speter register struct pcred *pc = p->p_cred; 80256115Speter register gid_t rgid, egid, sgid; 80356115Speter int error; 80456115Speter 80556115Speter rgid = uap->rgid; 80656115Speter egid = uap->egid; 80756115Speter sgid = uap->sgid; 80856115Speter if (((rgid != (gid_t)-1 && rgid != pc->p_rgid && rgid != pc->p_svgid && 80956115Speter rgid != pc->pc_ucred->cr_groups[0]) || 81056115Speter (egid != (gid_t)-1 && egid != pc->p_rgid && egid != pc->p_svgid && 81156115Speter egid != pc->pc_ucred->cr_groups[0]) || 81256115Speter (sgid != (gid_t)-1 && sgid != pc->p_rgid && sgid != pc->p_svgid && 81356115Speter sgid != pc->pc_ucred->cr_groups[0])) && 81456115Speter (error = suser_xxx(0, p, PRISON_ROOT)) != 0) 81556115Speter return (error); 81656115Speter 81756115Speter if (egid != (gid_t)-1 && pc->pc_ucred->cr_groups[0] != egid) { 81856115Speter pc->pc_ucred = crcopy(pc->pc_ucred); 81956115Speter pc->pc_ucred->cr_groups[0] = egid; 82056115Speter setsugid(p); 82156115Speter } 82256115Speter if (rgid != (gid_t)-1 && pc->p_rgid != rgid) { 82356115Speter pc->p_rgid = rgid; 82456115Speter setsugid(p); 82556115Speter } 82656115Speter if (sgid != (gid_t)-1 && pc->p_svgid != sgid) { 82756115Speter pc->p_svgid = sgid; 82856115Speter setsugid(p); 82956115Speter } 83056115Speter return (0); 83156115Speter} 83256115Speter 83356115Speter#ifndef _SYS_SYSPROTO_H_ 83456115Speterstruct getresuid_args { 83556115Speter uid_t *ruid; 83656115Speter uid_t *euid; 83756115Speter uid_t *suid; 83856115Speter}; 83956115Speter#endif 84056115Speter/* ARGSUSED */ 84156115Speterint 84256115Spetergetresuid(p, uap) 84356115Speter register struct proc *p; 84456115Speter struct getresuid_args *uap; 84556115Speter{ 84656115Speter struct pcred *pc = p->p_cred; 84756115Speter int error1 = 0, error2 = 0, error3 = 0; 84856115Speter 84956115Speter if (uap->ruid) 85056115Speter error1 = copyout((caddr_t)&pc->p_ruid, 85156115Speter (caddr_t)uap->ruid, sizeof(pc->p_ruid)); 85256115Speter if (uap->euid) 85356115Speter error2 = copyout((caddr_t)&pc->pc_ucred->cr_uid, 85456115Speter (caddr_t)uap->euid, sizeof(pc->pc_ucred->cr_uid)); 85556115Speter if (uap->suid) 85656115Speter error3 = copyout((caddr_t)&pc->p_svuid, 85756115Speter (caddr_t)uap->suid, sizeof(pc->p_svuid)); 85856115Speter return error1 ? error1 : (error2 ? error2 : error3); 85956115Speter} 86056115Speter 86156115Speter#ifndef _SYS_SYSPROTO_H_ 86256115Speterstruct getresgid_args { 86356115Speter gid_t *rgid; 86456115Speter gid_t *egid; 86556115Speter gid_t *sgid; 86656115Speter}; 86756115Speter#endif 86856115Speter/* ARGSUSED */ 86956115Speterint 87056115Spetergetresgid(p, uap) 87156115Speter register struct proc *p; 87256115Speter struct getresgid_args *uap; 87356115Speter{ 87456115Speter struct pcred *pc = p->p_cred; 87556115Speter int error1 = 0, error2 = 0, error3 = 0; 87656115Speter 87756115Speter if (uap->rgid) 87856115Speter error1 = copyout((caddr_t)&pc->p_rgid, 87956115Speter (caddr_t)uap->rgid, sizeof(pc->p_rgid)); 88056115Speter if (uap->egid) 88156115Speter error2 = copyout((caddr_t)&pc->pc_ucred->cr_groups[0], 88256115Speter (caddr_t)uap->egid, sizeof(pc->pc_ucred->cr_groups[0])); 88356115Speter if (uap->sgid) 88456115Speter error3 = copyout((caddr_t)&pc->p_svgid, 88556115Speter (caddr_t)uap->sgid, sizeof(pc->p_svgid)); 88656115Speter return error1 ? error1 : (error2 ? error2 : error3); 88756115Speter} 88856115Speter 88956115Speter 89056115Speter#ifndef _SYS_SYSPROTO_H_ 89124453Speterstruct issetugid_args { 89224453Speter int dummy; 89324453Speter}; 89424453Speter#endif 89524453Speter/* ARGSUSED */ 89624453Speterint 89730994Sphkissetugid(p, uap) 89824453Speter register struct proc *p; 89924453Speter struct issetugid_args *uap; 90024453Speter{ 90124453Speter /* 90224453Speter * Note: OpenBSD sets a P_SUGIDEXEC flag set at execve() time, 90324453Speter * we use P_SUGID because we consider changing the owners as 90424453Speter * "tainting" as well. 90524453Speter * This is significant for procs that start as root and "become" 90624453Speter * a user without an exec - programs cannot know *everything* 90724453Speter * that libc *might* have put in their data segment. 90824453Speter */ 90924453Speter if (p->p_flag & P_SUGID) 91024453Speter return (1); 91124453Speter return (0); 91224453Speter} 91324453Speter 9141541Srgrimes/* 9151541Srgrimes * Check if gid is a member of the group set. 9161541Srgrimes */ 9171549Srgrimesint 9181541Srgrimesgroupmember(gid, cred) 9191541Srgrimes gid_t gid; 9201541Srgrimes register struct ucred *cred; 9211541Srgrimes{ 9221541Srgrimes register gid_t *gp; 9231541Srgrimes gid_t *egp; 9241541Srgrimes 9251541Srgrimes egp = &(cred->cr_groups[cred->cr_ngroups]); 9261541Srgrimes for (gp = cred->cr_groups; gp < egp; gp++) 9271541Srgrimes if (*gp == gid) 9281541Srgrimes return (1); 9291541Srgrimes return (0); 9301541Srgrimes} 9311541Srgrimes 9321541Srgrimes/* 9331541Srgrimes * Test whether the specified credentials imply "super-user" 9341541Srgrimes * privilege; if so, and we have accounting info, set the flag 9351541Srgrimes * indicating use of super-powers. 9361541Srgrimes * Returns 0 or error. 9371541Srgrimes */ 9381549Srgrimesint 93946112Sphksuser(p) 94046112Sphk struct proc *p; 94146112Sphk{ 94246155Sphk return suser_xxx(0, p, 0); 94346112Sphk} 94446112Sphk 94546112Sphkint 94646155Sphksuser_xxx(cred, proc, flag) 9471541Srgrimes struct ucred *cred; 94846155Sphk struct proc *proc; 94946155Sphk int flag; 9501541Srgrimes{ 95146155Sphk if (!cred && !proc) { 95246155Sphk printf("suser_xxx(): THINK!\n"); 95346155Sphk return (EPERM); 9541541Srgrimes } 95546155Sphk if (!cred) 95646155Sphk cred = proc->p_ucred; 95746155Sphk if (cred->cr_uid != 0) 95846155Sphk return (EPERM); 95946155Sphk if (proc && proc->p_prison && !(flag & PRISON_ROOT)) 96046155Sphk return (EPERM); 96146155Sphk if (proc) 96246155Sphk proc->p_acflag |= ASU; 96346155Sphk return (0); 9641541Srgrimes} 9651541Srgrimes 9661541Srgrimes/* 96753518Sphk * Return zero if p1 can fondle p2, return errno (EPERM/ESRCH) otherwise. 96853518Sphk */ 96953518Sphk 97053518Sphkint 97153518Sphkp_trespass(struct proc *p1, struct proc *p2) 97253518Sphk{ 97353518Sphk 97453518Sphk if (p1 == p2) 97553518Sphk return (0); 97653518Sphk if (!PRISON_CHECK(p1, p2)) 97753518Sphk return (ESRCH); 97853518Sphk if (p1->p_cred->p_ruid == p2->p_cred->p_ruid) 97953518Sphk return (0); 98053518Sphk if (p1->p_ucred->cr_uid == p2->p_cred->p_ruid) 98153518Sphk return (0); 98253518Sphk if (p1->p_cred->p_ruid == p2->p_ucred->cr_uid) 98353518Sphk return (0); 98453518Sphk if (p1->p_ucred->cr_uid == p2->p_ucred->cr_uid) 98553518Sphk return (0); 98653518Sphk if (!suser_xxx(0, p1, PRISON_ROOT)) 98753518Sphk return (0); 98853518Sphk return (EPERM); 98953518Sphk} 99053518Sphk 99153518Sphk/* 9921541Srgrimes * Allocate a zeroed cred structure. 9931541Srgrimes */ 9941541Srgrimesstruct ucred * 9951541Srgrimescrget() 9961541Srgrimes{ 9971541Srgrimes register struct ucred *cr; 9981541Srgrimes 9991541Srgrimes MALLOC(cr, struct ucred *, sizeof(*cr), M_CRED, M_WAITOK); 10001541Srgrimes bzero((caddr_t)cr, sizeof(*cr)); 10011541Srgrimes cr->cr_ref = 1; 10021541Srgrimes return (cr); 10031541Srgrimes} 10041541Srgrimes 10051541Srgrimes/* 10061541Srgrimes * Free a cred structure. 10071541Srgrimes * Throws away space when ref count gets to 0. 10081541Srgrimes */ 10091549Srgrimesvoid 10101541Srgrimescrfree(cr) 10111541Srgrimes struct ucred *cr; 10121541Srgrimes{ 10131541Srgrimes if (--cr->cr_ref == 0) 10141541Srgrimes FREE((caddr_t)cr, M_CRED); 10151541Srgrimes} 10161541Srgrimes 10171541Srgrimes/* 10181541Srgrimes * Copy cred structure to a new one and free the old one. 10191541Srgrimes */ 10201541Srgrimesstruct ucred * 10211541Srgrimescrcopy(cr) 10221541Srgrimes struct ucred *cr; 10231541Srgrimes{ 10241541Srgrimes struct ucred *newcr; 10251541Srgrimes 10261541Srgrimes if (cr->cr_ref == 1) 10271541Srgrimes return (cr); 10281541Srgrimes newcr = crget(); 10291541Srgrimes *newcr = *cr; 10301541Srgrimes crfree(cr); 10311541Srgrimes newcr->cr_ref = 1; 10321541Srgrimes return (newcr); 10331541Srgrimes} 10341541Srgrimes 10351541Srgrimes/* 10361541Srgrimes * Dup cred struct to a new held one. 10371541Srgrimes */ 10381541Srgrimesstruct ucred * 10391541Srgrimescrdup(cr) 10401541Srgrimes struct ucred *cr; 10411541Srgrimes{ 10421541Srgrimes struct ucred *newcr; 10431541Srgrimes 10441541Srgrimes newcr = crget(); 10451541Srgrimes *newcr = *cr; 10461541Srgrimes newcr->cr_ref = 1; 10471541Srgrimes return (newcr); 10481541Srgrimes} 10491541Srgrimes 10501541Srgrimes/* 10511541Srgrimes * Get login name, if available. 10521541Srgrimes */ 105312221Sbde#ifndef _SYS_SYSPROTO_H_ 10541541Srgrimesstruct getlogin_args { 10551541Srgrimes char *namebuf; 10561541Srgrimes u_int namelen; 10571541Srgrimes}; 105812221Sbde#endif 10591541Srgrimes/* ARGSUSED */ 10601549Srgrimesint 106130994Sphkgetlogin(p, uap) 10621541Srgrimes struct proc *p; 10631541Srgrimes struct getlogin_args *uap; 10641541Srgrimes{ 10651541Srgrimes 106623358Sache if (uap->namelen > MAXLOGNAME) 106723359Sache uap->namelen = MAXLOGNAME; 10681541Srgrimes return (copyout((caddr_t) p->p_pgrp->pg_session->s_login, 10691541Srgrimes (caddr_t) uap->namebuf, uap->namelen)); 10701541Srgrimes} 10711541Srgrimes 10721541Srgrimes/* 10731541Srgrimes * Set login name. 10741541Srgrimes */ 107512221Sbde#ifndef _SYS_SYSPROTO_H_ 10761541Srgrimesstruct setlogin_args { 10771541Srgrimes char *namebuf; 10781541Srgrimes}; 107912221Sbde#endif 10801541Srgrimes/* ARGSUSED */ 10811549Srgrimesint 108230994Sphksetlogin(p, uap) 10831541Srgrimes struct proc *p; 10841541Srgrimes struct setlogin_args *uap; 10851541Srgrimes{ 10861541Srgrimes int error; 108723330Sache char logintmp[MAXLOGNAME]; 10881541Srgrimes 108946155Sphk if ((error = suser_xxx(0, p, PRISON_ROOT))) 10901541Srgrimes return (error); 109122522Sdavidn error = copyinstr((caddr_t) uap->namebuf, (caddr_t) logintmp, 109236845Sdfr sizeof(logintmp), (size_t *)0); 10931541Srgrimes if (error == ENAMETOOLONG) 10941541Srgrimes error = EINVAL; 109522522Sdavidn else if (!error) 109622522Sdavidn (void) memcpy(p->p_pgrp->pg_session->s_login, logintmp, 109723330Sache sizeof(logintmp)); 10981541Srgrimes return (error); 10991541Srgrimes} 110031891Ssef 110131891Ssefvoid 110231891Ssefsetsugid(p) 110355338Sphk struct proc *p; 110431891Ssef{ 110531891Ssef p->p_flag |= P_SUGID; 110655707Ssef if (!(p->p_pfsflags & PF_ISUGID)) 110731891Ssef p->p_stops = 0; 110831891Ssef} 1109