kern_prot.c revision 61287
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 61287 2000-06-05 18:30:55Z rwatson $ 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> 5661287Srwatson#include <sys/sysctl.h> 571541Srgrimes 5830354Sphkstatic MALLOC_DEFINE(M_CRED, "cred", "credentials"); 5930354Sphk 6012221Sbde#ifndef _SYS_SYSPROTO_H_ 6111332Sswallacestruct getpid_args { 621541Srgrimes int dummy; 631541Srgrimes}; 6412221Sbde#endif 651541Srgrimes 6658717Sdillon/* 6758717Sdillon * NOT MP SAFE due to p_pptr access 6858717Sdillon */ 691541Srgrimes/* ARGSUSED */ 701549Srgrimesint 7130994Sphkgetpid(p, uap) 721541Srgrimes struct proc *p; 7311332Sswallace struct getpid_args *uap; 741541Srgrimes{ 751541Srgrimes 7630994Sphk p->p_retval[0] = p->p_pid; 771541Srgrimes#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 7830994Sphk p->p_retval[1] = p->p_pptr->p_pid; 791541Srgrimes#endif 801541Srgrimes return (0); 811541Srgrimes} 821541Srgrimes 8312221Sbde#ifndef _SYS_SYSPROTO_H_ 8411332Sswallacestruct getppid_args { 8511332Sswallace int dummy; 8611332Sswallace}; 8712221Sbde#endif 881541Srgrimes/* ARGSUSED */ 891549Srgrimesint 9030994Sphkgetppid(p, uap) 911541Srgrimes struct proc *p; 9211332Sswallace struct getppid_args *uap; 931541Srgrimes{ 941541Srgrimes 9530994Sphk p->p_retval[0] = p->p_pptr->p_pid; 961541Srgrimes return (0); 971541Srgrimes} 981541Srgrimes 9958717Sdillon/* 10058717Sdillon * Get process group ID; note that POSIX getpgrp takes no parameter 10158717Sdillon * 10258717Sdillon * MP SAFE 10358717Sdillon */ 10412221Sbde#ifndef _SYS_SYSPROTO_H_ 10511332Sswallacestruct getpgrp_args { 10611332Sswallace int dummy; 10711332Sswallace}; 10812221Sbde#endif 10911332Sswallace 1101549Srgrimesint 11130994Sphkgetpgrp(p, uap) 1121541Srgrimes struct proc *p; 11311332Sswallace struct getpgrp_args *uap; 1141541Srgrimes{ 1151541Srgrimes 11630994Sphk p->p_retval[0] = p->p_pgrp->pg_id; 1171541Srgrimes return (0); 1181541Srgrimes} 1191541Srgrimes 12028401Speter/* Get an arbitary pid's process group id */ 12112221Sbde#ifndef _SYS_SYSPROTO_H_ 12228401Speterstruct getpgid_args { 12328401Speter pid_t pid; 12428401Speter}; 12528401Speter#endif 12628401Speter 12728401Speterint 12830994Sphkgetpgid(p, uap) 12928401Speter struct proc *p; 13028401Speter struct getpgid_args *uap; 13128401Speter{ 13241726Struckman struct proc *pt; 13341726Struckman 13441726Struckman pt = p; 13528401Speter if (uap->pid == 0) 13628401Speter goto found; 13728401Speter 13841726Struckman if ((pt = pfind(uap->pid)) == 0) 13928401Speter return ESRCH; 14028401Speterfound: 14141726Struckman p->p_retval[0] = pt->p_pgrp->pg_id; 14228401Speter return 0; 14328401Speter} 14428401Speter 14528401Speter/* 14628401Speter * Get an arbitary pid's session id. 14728401Speter */ 14828401Speter#ifndef _SYS_SYSPROTO_H_ 14928401Speterstruct getsid_args { 15028401Speter pid_t pid; 15128401Speter}; 15228401Speter#endif 15328401Speter 15428401Speterint 15530994Sphkgetsid(p, uap) 15628401Speter struct proc *p; 15728401Speter struct getsid_args *uap; 15828401Speter{ 15941726Struckman struct proc *pt; 16041726Struckman 16141726Struckman pt = p; 16228401Speter if (uap->pid == 0) 16328401Speter goto found; 16428401Speter 16541726Struckman if ((pt == pfind(uap->pid)) == 0) 16628401Speter return ESRCH; 16728401Speterfound: 16841726Struckman p->p_retval[0] = pt->p_session->s_sid; 16928401Speter return 0; 17028401Speter} 17128401Speter 17228401Speter 17358941Sdillon/* 17458941Sdillon * getuid() - MP SAFE 17558941Sdillon */ 17628401Speter#ifndef _SYS_SYSPROTO_H_ 17711332Sswallacestruct getuid_args { 17811332Sswallace int dummy; 17911332Sswallace}; 18012221Sbde#endif 18111332Sswallace 1821541Srgrimes/* ARGSUSED */ 1831549Srgrimesint 18430994Sphkgetuid(p, uap) 1851541Srgrimes struct proc *p; 18611332Sswallace struct getuid_args *uap; 1871541Srgrimes{ 1881541Srgrimes 18930994Sphk p->p_retval[0] = p->p_cred->p_ruid; 1901541Srgrimes#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 19130994Sphk p->p_retval[1] = p->p_ucred->cr_uid; 1921541Srgrimes#endif 1931541Srgrimes return (0); 1941541Srgrimes} 1951541Srgrimes 19658941Sdillon/* 19758941Sdillon * geteuid() - MP SAFE 19858941Sdillon */ 19912221Sbde#ifndef _SYS_SYSPROTO_H_ 20011332Sswallacestruct geteuid_args { 20111332Sswallace int dummy; 20211332Sswallace}; 20312221Sbde#endif 20411332Sswallace 2051541Srgrimes/* ARGSUSED */ 2061549Srgrimesint 20730994Sphkgeteuid(p, uap) 2081541Srgrimes struct proc *p; 20911332Sswallace struct geteuid_args *uap; 2101541Srgrimes{ 2111541Srgrimes 21230994Sphk p->p_retval[0] = p->p_ucred->cr_uid; 2131541Srgrimes return (0); 2141541Srgrimes} 2151541Srgrimes 21658941Sdillon/* 21758941Sdillon * getgid() - MP SAFE 21858941Sdillon */ 21912221Sbde#ifndef _SYS_SYSPROTO_H_ 22011332Sswallacestruct getgid_args { 22111332Sswallace int dummy; 22211332Sswallace}; 22312221Sbde#endif 22411332Sswallace 2251541Srgrimes/* ARGSUSED */ 2261549Srgrimesint 22730994Sphkgetgid(p, uap) 2281541Srgrimes struct proc *p; 22911332Sswallace struct getgid_args *uap; 2301541Srgrimes{ 2311541Srgrimes 23230994Sphk p->p_retval[0] = p->p_cred->p_rgid; 2331541Srgrimes#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 23430994Sphk p->p_retval[1] = p->p_ucred->cr_groups[0]; 2351541Srgrimes#endif 2361541Srgrimes return (0); 2371541Srgrimes} 2381541Srgrimes 2391541Srgrimes/* 2401541Srgrimes * Get effective group ID. The "egid" is groups[0], and could be obtained 2411541Srgrimes * via getgroups. This syscall exists because it is somewhat painful to do 2421541Srgrimes * correctly in a library function. 2431541Srgrimes */ 24412221Sbde#ifndef _SYS_SYSPROTO_H_ 24511332Sswallacestruct getegid_args { 24611332Sswallace int dummy; 24711332Sswallace}; 24812221Sbde#endif 24911332Sswallace 2501541Srgrimes/* ARGSUSED */ 2511549Srgrimesint 25230994Sphkgetegid(p, uap) 2531541Srgrimes struct proc *p; 25411332Sswallace struct getegid_args *uap; 2551541Srgrimes{ 2561541Srgrimes 25730994Sphk p->p_retval[0] = p->p_ucred->cr_groups[0]; 2581541Srgrimes return (0); 2591541Srgrimes} 2601541Srgrimes 26112221Sbde#ifndef _SYS_SYSPROTO_H_ 2621541Srgrimesstruct getgroups_args { 2631541Srgrimes u_int gidsetsize; 2641541Srgrimes gid_t *gidset; 2651541Srgrimes}; 26612221Sbde#endif 2671549Srgrimesint 26830994Sphkgetgroups(p, uap) 2691541Srgrimes struct proc *p; 2701541Srgrimes register struct getgroups_args *uap; 2711541Srgrimes{ 2721541Srgrimes register struct pcred *pc = p->p_cred; 2731541Srgrimes register u_int ngrp; 2741541Srgrimes int error; 2751541Srgrimes 2761541Srgrimes if ((ngrp = uap->gidsetsize) == 0) { 27730994Sphk p->p_retval[0] = pc->pc_ucred->cr_ngroups; 2781541Srgrimes return (0); 2791541Srgrimes } 2801541Srgrimes if (ngrp < pc->pc_ucred->cr_ngroups) 2811541Srgrimes return (EINVAL); 2821541Srgrimes ngrp = pc->pc_ucred->cr_ngroups; 2833098Sphk if ((error = copyout((caddr_t)pc->pc_ucred->cr_groups, 2843098Sphk (caddr_t)uap->gidset, ngrp * sizeof(gid_t)))) 2851541Srgrimes return (error); 28630994Sphk p->p_retval[0] = ngrp; 2871541Srgrimes return (0); 2881541Srgrimes} 2891541Srgrimes 29012221Sbde#ifndef _SYS_SYSPROTO_H_ 29112207Sbdestruct setsid_args { 29211332Sswallace int dummy; 29311332Sswallace}; 29412221Sbde#endif 29511332Sswallace 2961541Srgrimes/* ARGSUSED */ 2971549Srgrimesint 29830994Sphksetsid(p, uap) 2991541Srgrimes register struct proc *p; 30012207Sbde struct setsid_args *uap; 3011541Srgrimes{ 3021541Srgrimes 3031541Srgrimes if (p->p_pgid == p->p_pid || pgfind(p->p_pid)) { 3041541Srgrimes return (EPERM); 3051541Srgrimes } else { 3061541Srgrimes (void)enterpgrp(p, p->p_pid, 1); 30730994Sphk p->p_retval[0] = p->p_pid; 3081541Srgrimes return (0); 3091541Srgrimes } 3101541Srgrimes} 3111541Srgrimes 3121541Srgrimes/* 3131541Srgrimes * set process group (setpgid/old setpgrp) 3141541Srgrimes * 3151541Srgrimes * caller does setpgid(targpid, targpgid) 3161541Srgrimes * 3171541Srgrimes * pid must be caller or child of caller (ESRCH) 3181541Srgrimes * if a child 3191541Srgrimes * pid must be in same session (EPERM) 3201541Srgrimes * pid can't have done an exec (EACCES) 3211541Srgrimes * if pgid != pid 3221541Srgrimes * there must exist some pid in same session having pgid (EPERM) 3231541Srgrimes * pid must not be session leader (EPERM) 3241541Srgrimes */ 32512221Sbde#ifndef _SYS_SYSPROTO_H_ 3261541Srgrimesstruct setpgid_args { 3271541Srgrimes int pid; /* target process id */ 3281541Srgrimes int pgid; /* target pgrp id */ 3291541Srgrimes}; 33012221Sbde#endif 3311541Srgrimes/* ARGSUSED */ 3321549Srgrimesint 33330994Sphksetpgid(curp, uap) 3341541Srgrimes struct proc *curp; 3351541Srgrimes register struct setpgid_args *uap; 3361541Srgrimes{ 3371541Srgrimes register struct proc *targp; /* target process */ 3381541Srgrimes register struct pgrp *pgrp; /* target pgrp */ 3391541Srgrimes 34020677Sbde if (uap->pgid < 0) 34120677Sbde return (EINVAL); 3421541Srgrimes if (uap->pid != 0 && uap->pid != curp->p_pid) { 3431541Srgrimes if ((targp = pfind(uap->pid)) == 0 || !inferior(targp)) 3441541Srgrimes return (ESRCH); 34515985Sdg if (targp->p_pgrp == NULL || targp->p_session != curp->p_session) 3461541Srgrimes return (EPERM); 3471541Srgrimes if (targp->p_flag & P_EXEC) 3481541Srgrimes return (EACCES); 3491541Srgrimes } else 3501541Srgrimes targp = curp; 3511541Srgrimes if (SESS_LEADER(targp)) 3521541Srgrimes return (EPERM); 3531541Srgrimes if (uap->pgid == 0) 3541541Srgrimes uap->pgid = targp->p_pid; 3551541Srgrimes else if (uap->pgid != targp->p_pid) 3561541Srgrimes if ((pgrp = pgfind(uap->pgid)) == 0 || 3571541Srgrimes pgrp->pg_session != curp->p_session) 3581541Srgrimes return (EPERM); 3591541Srgrimes return (enterpgrp(targp, uap->pgid, 0)); 3601541Srgrimes} 3611541Srgrimes 36224448Speter/* 36324448Speter * Use the clause in B.4.2.2 that allows setuid/setgid to be 4.2/4.3BSD 36424448Speter * compatable. It says that setting the uid/gid to euid/egid is a special 36524448Speter * case of "appropriate privilege". Once the rules are expanded out, this 36624448Speter * basically means that setuid(nnn) sets all three id's, in all permitted 36724448Speter * cases unless _POSIX_SAVED_IDS is enabled. In that case, setuid(getuid()) 36824448Speter * does not set the saved id - this is dangerous for traditional BSD 36924448Speter * programs. For this reason, we *really* do not want to set 37024448Speter * _POSIX_SAVED_IDS and do not want to clear POSIX_APPENDIX_B_4_2_2. 37124448Speter */ 37224448Speter#define POSIX_APPENDIX_B_4_2_2 37324448Speter 37412221Sbde#ifndef _SYS_SYSPROTO_H_ 3751541Srgrimesstruct setuid_args { 3761541Srgrimes uid_t uid; 3771541Srgrimes}; 37812221Sbde#endif 3791541Srgrimes/* ARGSUSED */ 3801549Srgrimesint 38130994Sphksetuid(p, uap) 3821541Srgrimes struct proc *p; 3831541Srgrimes struct setuid_args *uap; 3841541Srgrimes{ 3851541Srgrimes register struct pcred *pc = p->p_cred; 3861541Srgrimes register uid_t uid; 3871541Srgrimes int error; 3881541Srgrimes 38924448Speter /* 39024448Speter * See if we have "permission" by POSIX 1003.1 rules. 39124448Speter * 39224448Speter * Note that setuid(geteuid()) is a special case of 39324448Speter * "appropriate privileges" in appendix B.4.2.2. We need 39424448Speter * to use this clause to be compatable with traditional BSD 39524448Speter * semantics. Basically, it means that "setuid(xx)" sets all 39624448Speter * three id's (assuming you have privs). 39724448Speter * 39824448Speter * Notes on the logic. We do things in three steps. 39924448Speter * 1: We determine if the euid is going to change, and do EPERM 40024448Speter * right away. We unconditionally change the euid later if this 40124448Speter * test is satisfied, simplifying that part of the logic. 40224448Speter * 2: We determine if the real and/or saved uid's are going to 40324448Speter * change. Determined by compile options. 40424448Speter * 3: Change euid last. (after tests in #2 for "appropriate privs") 40524448Speter */ 4061541Srgrimes uid = uap->uid; 40724448Speter if (uid != pc->p_ruid && /* allow setuid(getuid()) */ 40817994Sache#ifdef _POSIX_SAVED_IDS 40924448Speter uid != pc->p_svuid && /* allow setuid(saved gid) */ 41017994Sache#endif 41124448Speter#ifdef POSIX_APPENDIX_B_4_2_2 /* Use BSD-compat clause from B.4.2.2 */ 41224448Speter uid != pc->pc_ucred->cr_uid && /* allow setuid(geteuid()) */ 41324448Speter#endif 41446155Sphk (error = suser_xxx(0, p, PRISON_ROOT))) 4151541Srgrimes return (error); 41624448Speter 41724448Speter#ifdef _POSIX_SAVED_IDS 4181541Srgrimes /* 41924448Speter * Do we have "appropriate privileges" (are we root or uid == euid) 42024448Speter * If so, we are changing the real uid and/or saved uid. 4211541Srgrimes */ 42217994Sache if ( 42324448Speter#ifdef POSIX_APPENDIX_B_4_2_2 /* Use the clause from B.4.2.2 */ 42424448Speter uid == pc->pc_ucred->cr_uid || 42517994Sache#endif 42646155Sphk suser_xxx(0, p, PRISON_ROOT) == 0) /* we are using privs */ 42717994Sache#endif 42824448Speter { 42924448Speter /* 43024448Speter * Transfer proc count to new user. 43124448Speter */ 43224448Speter if (uid != pc->p_ruid) { 43324448Speter (void)chgproccnt(pc->p_ruid, -1); 43424448Speter (void)chgproccnt(uid, 1); 43524448Speter } 43624448Speter /* 43724448Speter * Set real uid 43824448Speter */ 43924448Speter if (uid != pc->p_ruid) { 44024448Speter pc->p_ruid = uid; 44131891Ssef setsugid(p); 44224448Speter } 44324448Speter /* 44424448Speter * Set saved uid 44524448Speter * 44624448Speter * XXX always set saved uid even if not _POSIX_SAVED_IDS, as 44724448Speter * the security of seteuid() depends on it. B.4.2.2 says it 44824448Speter * is important that we should do this. 44924448Speter */ 45024448Speter if (pc->p_svuid != uid) { 45124448Speter pc->p_svuid = uid; 45231891Ssef setsugid(p); 45324448Speter } 4548141Sache } 45524448Speter 45624448Speter /* 45724448Speter * In all permitted cases, we are changing the euid. 45824448Speter * Copy credentials so other references do not see our changes. 45924448Speter */ 46024448Speter if (pc->pc_ucred->cr_uid != uid) { 46124448Speter pc->pc_ucred = crcopy(pc->pc_ucred); 46224448Speter pc->pc_ucred->cr_uid = uid; 46331891Ssef setsugid(p); 46424448Speter } 4651541Srgrimes return (0); 4661541Srgrimes} 4671541Srgrimes 46812221Sbde#ifndef _SYS_SYSPROTO_H_ 4691541Srgrimesstruct seteuid_args { 4701541Srgrimes uid_t euid; 4711541Srgrimes}; 47212221Sbde#endif 4731541Srgrimes/* ARGSUSED */ 4741549Srgrimesint 47530994Sphkseteuid(p, uap) 4761541Srgrimes struct proc *p; 4771541Srgrimes struct seteuid_args *uap; 4781541Srgrimes{ 4791541Srgrimes register struct pcred *pc = p->p_cred; 4801541Srgrimes register uid_t euid; 4811541Srgrimes int error; 4821541Srgrimes 4831541Srgrimes euid = uap->euid; 48424449Speter if (euid != pc->p_ruid && /* allow seteuid(getuid()) */ 48524449Speter euid != pc->p_svuid && /* allow seteuid(saved uid) */ 48646155Sphk (error = suser_xxx(0, p, PRISON_ROOT))) 4871541Srgrimes return (error); 4881541Srgrimes /* 4891541Srgrimes * Everything's okay, do it. Copy credentials so other references do 4901541Srgrimes * not see our changes. 4911541Srgrimes */ 49224449Speter if (pc->pc_ucred->cr_uid != euid) { 49324449Speter pc->pc_ucred = crcopy(pc->pc_ucred); 49424449Speter pc->pc_ucred->cr_uid = euid; 49531891Ssef setsugid(p); 49624449Speter } 4971541Srgrimes return (0); 4981541Srgrimes} 4991541Srgrimes 50012221Sbde#ifndef _SYS_SYSPROTO_H_ 5011541Srgrimesstruct setgid_args { 5021541Srgrimes gid_t gid; 5031541Srgrimes}; 50412221Sbde#endif 5051541Srgrimes/* ARGSUSED */ 5061549Srgrimesint 50730994Sphksetgid(p, uap) 5081541Srgrimes struct proc *p; 5091541Srgrimes struct setgid_args *uap; 5101541Srgrimes{ 5111541Srgrimes register struct pcred *pc = p->p_cred; 5121541Srgrimes register gid_t gid; 5131541Srgrimes int error; 5141541Srgrimes 51524448Speter /* 51624448Speter * See if we have "permission" by POSIX 1003.1 rules. 51724448Speter * 51824448Speter * Note that setgid(getegid()) is a special case of 51924448Speter * "appropriate privileges" in appendix B.4.2.2. We need 52024448Speter * to use this clause to be compatable with traditional BSD 52124448Speter * semantics. Basically, it means that "setgid(xx)" sets all 52224448Speter * three id's (assuming you have privs). 52324448Speter * 52424448Speter * For notes on the logic here, see setuid() above. 52524448Speter */ 5261541Srgrimes gid = uap->gid; 52724448Speter if (gid != pc->p_rgid && /* allow setgid(getgid()) */ 52817994Sache#ifdef _POSIX_SAVED_IDS 52924448Speter gid != pc->p_svgid && /* allow setgid(saved gid) */ 53017994Sache#endif 53124448Speter#ifdef POSIX_APPENDIX_B_4_2_2 /* Use BSD-compat clause from B.4.2.2 */ 53224448Speter gid != pc->pc_ucred->cr_groups[0] && /* allow setgid(getegid()) */ 53324448Speter#endif 53446155Sphk (error = suser_xxx(0, p, PRISON_ROOT))) 5351541Srgrimes return (error); 53624448Speter 53717994Sache#ifdef _POSIX_SAVED_IDS 53824448Speter /* 53924448Speter * Do we have "appropriate privileges" (are we root or gid == egid) 54024448Speter * If so, we are changing the real uid and saved gid. 54124448Speter */ 54224448Speter if ( 54324448Speter#ifdef POSIX_APPENDIX_B_4_2_2 /* use the clause from B.4.2.2 */ 54424448Speter gid == pc->pc_ucred->cr_groups[0] || 54517994Sache#endif 54646155Sphk suser_xxx(0, p, PRISON_ROOT) == 0) /* we are using privs */ 54724448Speter#endif 54824448Speter { 54924448Speter /* 55024448Speter * Set real gid 55124448Speter */ 55224448Speter if (pc->p_rgid != gid) { 55324448Speter pc->p_rgid = gid; 55431891Ssef setsugid(p); 55524448Speter } 55624448Speter /* 55724448Speter * Set saved gid 55824448Speter * 55924448Speter * XXX always set saved gid even if not _POSIX_SAVED_IDS, as 56024448Speter * the security of setegid() depends on it. B.4.2.2 says it 56124448Speter * is important that we should do this. 56224448Speter */ 56324448Speter if (pc->p_svgid != gid) { 56424448Speter pc->p_svgid = gid; 56531891Ssef setsugid(p); 56624448Speter } 5678141Sache } 56824448Speter /* 56924448Speter * In all cases permitted cases, we are changing the egid. 57024448Speter * Copy credentials so other references do not see our changes. 57124448Speter */ 57224448Speter if (pc->pc_ucred->cr_groups[0] != gid) { 57324448Speter pc->pc_ucred = crcopy(pc->pc_ucred); 57424448Speter pc->pc_ucred->cr_groups[0] = gid; 57531891Ssef setsugid(p); 57624448Speter } 5771541Srgrimes return (0); 5781541Srgrimes} 5791541Srgrimes 58012221Sbde#ifndef _SYS_SYSPROTO_H_ 5811541Srgrimesstruct setegid_args { 5821541Srgrimes gid_t egid; 5831541Srgrimes}; 58412221Sbde#endif 5851541Srgrimes/* ARGSUSED */ 5861549Srgrimesint 58730994Sphksetegid(p, uap) 5881541Srgrimes struct proc *p; 5891541Srgrimes struct setegid_args *uap; 5901541Srgrimes{ 5911541Srgrimes register struct pcred *pc = p->p_cred; 5921541Srgrimes register gid_t egid; 5931541Srgrimes int error; 5941541Srgrimes 5951541Srgrimes egid = uap->egid; 59624449Speter if (egid != pc->p_rgid && /* allow setegid(getgid()) */ 59724449Speter egid != pc->p_svgid && /* allow setegid(saved gid) */ 59846155Sphk (error = suser_xxx(0, p, PRISON_ROOT))) 5991541Srgrimes return (error); 60024449Speter if (pc->pc_ucred->cr_groups[0] != egid) { 60124449Speter pc->pc_ucred = crcopy(pc->pc_ucred); 60224449Speter pc->pc_ucred->cr_groups[0] = egid; 60331891Ssef setsugid(p); 60424449Speter } 6051541Srgrimes return (0); 6061541Srgrimes} 6071541Srgrimes 60812221Sbde#ifndef _SYS_SYSPROTO_H_ 6091541Srgrimesstruct setgroups_args { 6101541Srgrimes u_int gidsetsize; 6111541Srgrimes gid_t *gidset; 6121541Srgrimes}; 61312221Sbde#endif 6141541Srgrimes/* ARGSUSED */ 6151549Srgrimesint 61630994Sphksetgroups(p, uap) 6171541Srgrimes struct proc *p; 6181541Srgrimes struct setgroups_args *uap; 6191541Srgrimes{ 6201541Srgrimes register struct pcred *pc = p->p_cred; 6211541Srgrimes register u_int ngrp; 6221541Srgrimes int error; 6231541Srgrimes 62446155Sphk if ((error = suser_xxx(0, p, PRISON_ROOT))) 6251541Srgrimes return (error); 62612063Sdg ngrp = uap->gidsetsize; 62724447Speter if (ngrp > NGROUPS) 6281541Srgrimes return (EINVAL); 62924447Speter /* 63024447Speter * XXX A little bit lazy here. We could test if anything has 63124447Speter * changed before crcopy() and setting P_SUGID. 63224447Speter */ 6331541Srgrimes pc->pc_ucred = crcopy(pc->pc_ucred); 63424447Speter if (ngrp < 1) { 63524447Speter /* 63624447Speter * setgroups(0, NULL) is a legitimate way of clearing the 63724447Speter * groups vector on non-BSD systems (which generally do not 63824447Speter * have the egid in the groups[0]). We risk security holes 63924447Speter * when running non-BSD software if we do not do the same. 64024447Speter */ 64124447Speter pc->pc_ucred->cr_ngroups = 1; 64224447Speter } else { 64324447Speter if ((error = copyin((caddr_t)uap->gidset, 64424447Speter (caddr_t)pc->pc_ucred->cr_groups, ngrp * sizeof(gid_t)))) 64524447Speter return (error); 64624447Speter pc->pc_ucred->cr_ngroups = ngrp; 64724447Speter } 64831891Ssef setsugid(p); 6491541Srgrimes return (0); 6501541Srgrimes} 6511541Srgrimes 65212221Sbde#ifndef _SYS_SYSPROTO_H_ 6531541Srgrimesstruct setreuid_args { 6549238Sache uid_t ruid; 6559238Sache uid_t euid; 6561541Srgrimes}; 65712221Sbde#endif 6581541Srgrimes/* ARGSUSED */ 6591549Srgrimesint 66030994Sphksetreuid(p, uap) 6611541Srgrimes register struct proc *p; 6621541Srgrimes struct setreuid_args *uap; 6631541Srgrimes{ 6641541Srgrimes register struct pcred *pc = p->p_cred; 6659238Sache register uid_t ruid, euid; 6668135Sache int error; 6671541Srgrimes 6689238Sache ruid = uap->ruid; 6699238Sache euid = uap->euid; 67043311Sdillon if (((ruid != (uid_t)-1 && ruid != pc->p_ruid && ruid != pc->p_svuid) || 67143311Sdillon (euid != (uid_t)-1 && euid != pc->pc_ucred->cr_uid && 67243311Sdillon euid != pc->p_ruid && euid != pc->p_svuid)) && 67346155Sphk (error = suser_xxx(0, p, PRISON_ROOT)) != 0) 6748135Sache return (error); 6759238Sache 67624450Speter if (euid != (uid_t)-1 && pc->pc_ucred->cr_uid != euid) { 67724450Speter pc->pc_ucred = crcopy(pc->pc_ucred); 6789238Sache pc->pc_ucred->cr_uid = euid; 67931891Ssef setsugid(p); 68024450Speter } 68124450Speter if (ruid != (uid_t)-1 && pc->p_ruid != ruid) { 6829238Sache (void)chgproccnt(pc->p_ruid, -1); 6839238Sache (void)chgproccnt(ruid, 1); 6849238Sache pc->p_ruid = ruid; 68531891Ssef setsugid(p); 6868135Sache } 68724559Speter if ((ruid != (uid_t)-1 || pc->pc_ucred->cr_uid != pc->p_ruid) && 68824559Speter pc->p_svuid != pc->pc_ucred->cr_uid) { 6898111Sache pc->p_svuid = pc->pc_ucred->cr_uid; 69031891Ssef setsugid(p); 69124450Speter } 6928135Sache return (0); 6931541Srgrimes} 6941541Srgrimes 69512221Sbde#ifndef _SYS_SYSPROTO_H_ 6961541Srgrimesstruct setregid_args { 6979238Sache gid_t rgid; 6989238Sache gid_t egid; 6991541Srgrimes}; 70012221Sbde#endif 7011541Srgrimes/* ARGSUSED */ 7021549Srgrimesint 70330994Sphksetregid(p, uap) 7041541Srgrimes register struct proc *p; 7051541Srgrimes struct setregid_args *uap; 7061541Srgrimes{ 7071541Srgrimes register struct pcred *pc = p->p_cred; 7089238Sache register gid_t rgid, egid; 7098135Sache int error; 7101541Srgrimes 7119238Sache rgid = uap->rgid; 7129238Sache egid = uap->egid; 71343311Sdillon if (((rgid != (gid_t)-1 && rgid != pc->p_rgid && rgid != pc->p_svgid) || 71443311Sdillon (egid != (gid_t)-1 && egid != pc->pc_ucred->cr_groups[0] && 71543311Sdillon egid != pc->p_rgid && egid != pc->p_svgid)) && 71646155Sphk (error = suser_xxx(0, p, PRISON_ROOT)) != 0) 7178135Sache return (error); 7189238Sache 71924450Speter if (egid != (gid_t)-1 && pc->pc_ucred->cr_groups[0] != egid) { 72024450Speter pc->pc_ucred = crcopy(pc->pc_ucred); 7219238Sache pc->pc_ucred->cr_groups[0] = egid; 72231891Ssef setsugid(p); 72324450Speter } 72424450Speter if (rgid != (gid_t)-1 && pc->p_rgid != rgid) { 7259238Sache pc->p_rgid = rgid; 72631891Ssef setsugid(p); 72724450Speter } 72824559Speter if ((rgid != (gid_t)-1 || pc->pc_ucred->cr_groups[0] != pc->p_rgid) && 72924559Speter pc->p_svgid != pc->pc_ucred->cr_groups[0]) { 7308111Sache pc->p_svgid = pc->pc_ucred->cr_groups[0]; 73131891Ssef setsugid(p); 73224450Speter } 7338135Sache return (0); 7341541Srgrimes} 7351541Srgrimes 73656115Speter/* 73756115Speter * setresuid(ruid, euid, suid) is like setreuid except control over the 73856115Speter * saved uid is explicit. 73956115Speter */ 74056115Speter 74124453Speter#ifndef _SYS_SYSPROTO_H_ 74256115Speterstruct setresuid_args { 74356115Speter uid_t ruid; 74456115Speter uid_t euid; 74556115Speter uid_t suid; 74656115Speter}; 74756115Speter#endif 74856115Speter/* ARGSUSED */ 74956115Speterint 75056115Spetersetresuid(p, uap) 75156115Speter register struct proc *p; 75256115Speter struct setresuid_args *uap; 75356115Speter{ 75456115Speter register struct pcred *pc = p->p_cred; 75556115Speter register uid_t ruid, euid, suid; 75656115Speter int error; 75756115Speter 75856115Speter ruid = uap->ruid; 75956115Speter euid = uap->euid; 76056115Speter suid = uap->suid; 76156115Speter if (((ruid != (uid_t)-1 && ruid != pc->p_ruid && ruid != pc->p_svuid && 76256115Speter ruid != pc->pc_ucred->cr_uid) || 76356115Speter (euid != (uid_t)-1 && euid != pc->p_ruid && euid != pc->p_svuid && 76456115Speter euid != pc->pc_ucred->cr_uid) || 76556115Speter (suid != (uid_t)-1 && suid != pc->p_ruid && suid != pc->p_svuid && 76656115Speter suid != pc->pc_ucred->cr_uid)) && 76756115Speter (error = suser_xxx(0, p, PRISON_ROOT)) != 0) 76856115Speter return (error); 76956115Speter if (euid != (uid_t)-1 && pc->pc_ucred->cr_uid != euid) { 77056115Speter pc->pc_ucred = crcopy(pc->pc_ucred); 77156115Speter pc->pc_ucred->cr_uid = euid; 77256115Speter setsugid(p); 77356115Speter } 77456115Speter if (ruid != (uid_t)-1 && pc->p_ruid != ruid) { 77556115Speter (void)chgproccnt(pc->p_ruid, -1); 77656115Speter (void)chgproccnt(ruid, 1); 77756115Speter pc->p_ruid = ruid; 77856115Speter setsugid(p); 77956115Speter } 78056115Speter if (suid != (uid_t)-1 && pc->p_svuid != suid) { 78156115Speter pc->p_svuid = suid; 78256115Speter setsugid(p); 78356115Speter } 78456115Speter return (0); 78556115Speter} 78656115Speter 78756115Speter/* 78856115Speter * setresgid(rgid, egid, sgid) is like setregid except control over the 78956115Speter * saved gid is explicit. 79056115Speter */ 79156115Speter 79256115Speter#ifndef _SYS_SYSPROTO_H_ 79356115Speterstruct setresgid_args { 79456115Speter gid_t rgid; 79556115Speter gid_t egid; 79656115Speter gid_t sgid; 79756115Speter}; 79856115Speter#endif 79956115Speter/* ARGSUSED */ 80056115Speterint 80156115Spetersetresgid(p, uap) 80256115Speter register struct proc *p; 80356115Speter struct setresgid_args *uap; 80456115Speter{ 80556115Speter register struct pcred *pc = p->p_cred; 80656115Speter register gid_t rgid, egid, sgid; 80756115Speter int error; 80856115Speter 80956115Speter rgid = uap->rgid; 81056115Speter egid = uap->egid; 81156115Speter sgid = uap->sgid; 81256115Speter if (((rgid != (gid_t)-1 && rgid != pc->p_rgid && rgid != pc->p_svgid && 81356115Speter rgid != pc->pc_ucred->cr_groups[0]) || 81456115Speter (egid != (gid_t)-1 && egid != pc->p_rgid && egid != pc->p_svgid && 81556115Speter egid != pc->pc_ucred->cr_groups[0]) || 81656115Speter (sgid != (gid_t)-1 && sgid != pc->p_rgid && sgid != pc->p_svgid && 81756115Speter sgid != pc->pc_ucred->cr_groups[0])) && 81856115Speter (error = suser_xxx(0, p, PRISON_ROOT)) != 0) 81956115Speter return (error); 82056115Speter 82156115Speter if (egid != (gid_t)-1 && pc->pc_ucred->cr_groups[0] != egid) { 82256115Speter pc->pc_ucred = crcopy(pc->pc_ucred); 82356115Speter pc->pc_ucred->cr_groups[0] = egid; 82456115Speter setsugid(p); 82556115Speter } 82656115Speter if (rgid != (gid_t)-1 && pc->p_rgid != rgid) { 82756115Speter pc->p_rgid = rgid; 82856115Speter setsugid(p); 82956115Speter } 83056115Speter if (sgid != (gid_t)-1 && pc->p_svgid != sgid) { 83156115Speter pc->p_svgid = sgid; 83256115Speter setsugid(p); 83356115Speter } 83456115Speter return (0); 83556115Speter} 83656115Speter 83756115Speter#ifndef _SYS_SYSPROTO_H_ 83856115Speterstruct getresuid_args { 83956115Speter uid_t *ruid; 84056115Speter uid_t *euid; 84156115Speter uid_t *suid; 84256115Speter}; 84356115Speter#endif 84456115Speter/* ARGSUSED */ 84556115Speterint 84656115Spetergetresuid(p, uap) 84756115Speter register struct proc *p; 84856115Speter struct getresuid_args *uap; 84956115Speter{ 85056115Speter struct pcred *pc = p->p_cred; 85156115Speter int error1 = 0, error2 = 0, error3 = 0; 85256115Speter 85356115Speter if (uap->ruid) 85456115Speter error1 = copyout((caddr_t)&pc->p_ruid, 85556115Speter (caddr_t)uap->ruid, sizeof(pc->p_ruid)); 85656115Speter if (uap->euid) 85756115Speter error2 = copyout((caddr_t)&pc->pc_ucred->cr_uid, 85856115Speter (caddr_t)uap->euid, sizeof(pc->pc_ucred->cr_uid)); 85956115Speter if (uap->suid) 86056115Speter error3 = copyout((caddr_t)&pc->p_svuid, 86156115Speter (caddr_t)uap->suid, sizeof(pc->p_svuid)); 86256115Speter return error1 ? error1 : (error2 ? error2 : error3); 86356115Speter} 86456115Speter 86556115Speter#ifndef _SYS_SYSPROTO_H_ 86656115Speterstruct getresgid_args { 86756115Speter gid_t *rgid; 86856115Speter gid_t *egid; 86956115Speter gid_t *sgid; 87056115Speter}; 87156115Speter#endif 87256115Speter/* ARGSUSED */ 87356115Speterint 87456115Spetergetresgid(p, uap) 87556115Speter register struct proc *p; 87656115Speter struct getresgid_args *uap; 87756115Speter{ 87856115Speter struct pcred *pc = p->p_cred; 87956115Speter int error1 = 0, error2 = 0, error3 = 0; 88056115Speter 88156115Speter if (uap->rgid) 88256115Speter error1 = copyout((caddr_t)&pc->p_rgid, 88356115Speter (caddr_t)uap->rgid, sizeof(pc->p_rgid)); 88456115Speter if (uap->egid) 88556115Speter error2 = copyout((caddr_t)&pc->pc_ucred->cr_groups[0], 88656115Speter (caddr_t)uap->egid, sizeof(pc->pc_ucred->cr_groups[0])); 88756115Speter if (uap->sgid) 88856115Speter error3 = copyout((caddr_t)&pc->p_svgid, 88956115Speter (caddr_t)uap->sgid, sizeof(pc->p_svgid)); 89056115Speter return error1 ? error1 : (error2 ? error2 : error3); 89156115Speter} 89256115Speter 89356115Speter 89456115Speter#ifndef _SYS_SYSPROTO_H_ 89524453Speterstruct issetugid_args { 89624453Speter int dummy; 89724453Speter}; 89824453Speter#endif 89924453Speter/* ARGSUSED */ 90024453Speterint 90130994Sphkissetugid(p, uap) 90224453Speter register struct proc *p; 90324453Speter struct issetugid_args *uap; 90424453Speter{ 90524453Speter /* 90624453Speter * Note: OpenBSD sets a P_SUGIDEXEC flag set at execve() time, 90724453Speter * we use P_SUGID because we consider changing the owners as 90824453Speter * "tainting" as well. 90924453Speter * This is significant for procs that start as root and "become" 91024453Speter * a user without an exec - programs cannot know *everything* 91124453Speter * that libc *might* have put in their data segment. 91224453Speter */ 91360216Speter p->p_retval[0] = (p->p_flag & P_SUGID) ? 1 : 0; 91424453Speter return (0); 91524453Speter} 91624453Speter 9171541Srgrimes/* 9181541Srgrimes * Check if gid is a member of the group set. 9191541Srgrimes */ 9201549Srgrimesint 9211541Srgrimesgroupmember(gid, cred) 9221541Srgrimes gid_t gid; 9231541Srgrimes register struct ucred *cred; 9241541Srgrimes{ 9251541Srgrimes register gid_t *gp; 9261541Srgrimes gid_t *egp; 9271541Srgrimes 9281541Srgrimes egp = &(cred->cr_groups[cred->cr_ngroups]); 9291541Srgrimes for (gp = cred->cr_groups; gp < egp; gp++) 9301541Srgrimes if (*gp == gid) 9311541Srgrimes return (1); 9321541Srgrimes return (0); 9331541Srgrimes} 9341541Srgrimes 93561287Srwatsonstatic int suser_permitted = 1; 93661287Srwatson 93761287SrwatsonSYSCTL_INT(_kern, OID_AUTO, suser_permitted, CTLFLAG_RW, &suser_permitted, 0, 93861287Srwatson "processes with uid 0 have privilege"); 93961287Srwatson 9401541Srgrimes/* 9411541Srgrimes * Test whether the specified credentials imply "super-user" 9421541Srgrimes * privilege; if so, and we have accounting info, set the flag 9431541Srgrimes * indicating use of super-powers. 9441541Srgrimes * Returns 0 or error. 9451541Srgrimes */ 9461549Srgrimesint 94746112Sphksuser(p) 94846112Sphk struct proc *p; 94946112Sphk{ 95046155Sphk return suser_xxx(0, p, 0); 95146112Sphk} 95246112Sphk 95346112Sphkint 95446155Sphksuser_xxx(cred, proc, flag) 9551541Srgrimes struct ucred *cred; 95646155Sphk struct proc *proc; 95746155Sphk int flag; 9581541Srgrimes{ 95961282Srwatson if (!suser_permitted) 96061282Srwatson return (EPERM); 96146155Sphk if (!cred && !proc) { 96246155Sphk printf("suser_xxx(): THINK!\n"); 96346155Sphk return (EPERM); 9641541Srgrimes } 96546155Sphk if (!cred) 96646155Sphk cred = proc->p_ucred; 96746155Sphk if (cred->cr_uid != 0) 96846155Sphk return (EPERM); 96946155Sphk if (proc && proc->p_prison && !(flag & PRISON_ROOT)) 97046155Sphk return (EPERM); 97146155Sphk if (proc) 97246155Sphk proc->p_acflag |= ASU; 97346155Sphk return (0); 9741541Srgrimes} 9751541Srgrimes 9761541Srgrimes/* 97753518Sphk * Return zero if p1 can fondle p2, return errno (EPERM/ESRCH) otherwise. 97853518Sphk */ 97953518Sphk 98053518Sphkint 98153518Sphkp_trespass(struct proc *p1, struct proc *p2) 98253518Sphk{ 98353518Sphk 98453518Sphk if (p1 == p2) 98553518Sphk return (0); 98653518Sphk if (!PRISON_CHECK(p1, p2)) 98753518Sphk return (ESRCH); 98853518Sphk if (p1->p_cred->p_ruid == p2->p_cred->p_ruid) 98953518Sphk return (0); 99053518Sphk if (p1->p_ucred->cr_uid == p2->p_cred->p_ruid) 99153518Sphk return (0); 99253518Sphk if (p1->p_cred->p_ruid == p2->p_ucred->cr_uid) 99353518Sphk return (0); 99453518Sphk if (p1->p_ucred->cr_uid == p2->p_ucred->cr_uid) 99553518Sphk return (0); 99653518Sphk if (!suser_xxx(0, p1, PRISON_ROOT)) 99753518Sphk return (0); 99853518Sphk return (EPERM); 99953518Sphk} 100053518Sphk 100153518Sphk/* 10021541Srgrimes * Allocate a zeroed cred structure. 10031541Srgrimes */ 10041541Srgrimesstruct ucred * 10051541Srgrimescrget() 10061541Srgrimes{ 10071541Srgrimes register struct ucred *cr; 10081541Srgrimes 10091541Srgrimes MALLOC(cr, struct ucred *, sizeof(*cr), M_CRED, M_WAITOK); 10101541Srgrimes bzero((caddr_t)cr, sizeof(*cr)); 10111541Srgrimes cr->cr_ref = 1; 10121541Srgrimes return (cr); 10131541Srgrimes} 10141541Srgrimes 10151541Srgrimes/* 10161541Srgrimes * Free a cred structure. 10171541Srgrimes * Throws away space when ref count gets to 0. 10181541Srgrimes */ 10191549Srgrimesvoid 10201541Srgrimescrfree(cr) 10211541Srgrimes struct ucred *cr; 10221541Srgrimes{ 10231541Srgrimes if (--cr->cr_ref == 0) 10241541Srgrimes FREE((caddr_t)cr, M_CRED); 10251541Srgrimes} 10261541Srgrimes 10271541Srgrimes/* 10281541Srgrimes * Copy cred structure to a new one and free the old one. 10291541Srgrimes */ 10301541Srgrimesstruct ucred * 10311541Srgrimescrcopy(cr) 10321541Srgrimes struct ucred *cr; 10331541Srgrimes{ 10341541Srgrimes struct ucred *newcr; 10351541Srgrimes 10361541Srgrimes if (cr->cr_ref == 1) 10371541Srgrimes return (cr); 10381541Srgrimes newcr = crget(); 10391541Srgrimes *newcr = *cr; 10401541Srgrimes crfree(cr); 10411541Srgrimes newcr->cr_ref = 1; 10421541Srgrimes return (newcr); 10431541Srgrimes} 10441541Srgrimes 10451541Srgrimes/* 10461541Srgrimes * Dup cred struct to a new held one. 10471541Srgrimes */ 10481541Srgrimesstruct ucred * 10491541Srgrimescrdup(cr) 10501541Srgrimes struct ucred *cr; 10511541Srgrimes{ 10521541Srgrimes struct ucred *newcr; 10531541Srgrimes 10541541Srgrimes newcr = crget(); 10551541Srgrimes *newcr = *cr; 10561541Srgrimes newcr->cr_ref = 1; 10571541Srgrimes return (newcr); 10581541Srgrimes} 10591541Srgrimes 10601541Srgrimes/* 10611541Srgrimes * Get login name, if available. 10621541Srgrimes */ 106312221Sbde#ifndef _SYS_SYSPROTO_H_ 10641541Srgrimesstruct getlogin_args { 10651541Srgrimes char *namebuf; 10661541Srgrimes u_int namelen; 10671541Srgrimes}; 106812221Sbde#endif 10691541Srgrimes/* ARGSUSED */ 10701549Srgrimesint 107130994Sphkgetlogin(p, uap) 10721541Srgrimes struct proc *p; 10731541Srgrimes struct getlogin_args *uap; 10741541Srgrimes{ 10751541Srgrimes 107623358Sache if (uap->namelen > MAXLOGNAME) 107723359Sache uap->namelen = MAXLOGNAME; 10781541Srgrimes return (copyout((caddr_t) p->p_pgrp->pg_session->s_login, 10791541Srgrimes (caddr_t) uap->namebuf, uap->namelen)); 10801541Srgrimes} 10811541Srgrimes 10821541Srgrimes/* 10831541Srgrimes * Set login name. 10841541Srgrimes */ 108512221Sbde#ifndef _SYS_SYSPROTO_H_ 10861541Srgrimesstruct setlogin_args { 10871541Srgrimes char *namebuf; 10881541Srgrimes}; 108912221Sbde#endif 10901541Srgrimes/* ARGSUSED */ 10911549Srgrimesint 109230994Sphksetlogin(p, uap) 10931541Srgrimes struct proc *p; 10941541Srgrimes struct setlogin_args *uap; 10951541Srgrimes{ 10961541Srgrimes int error; 109723330Sache char logintmp[MAXLOGNAME]; 10981541Srgrimes 109946155Sphk if ((error = suser_xxx(0, p, PRISON_ROOT))) 11001541Srgrimes return (error); 110122522Sdavidn error = copyinstr((caddr_t) uap->namebuf, (caddr_t) logintmp, 110236845Sdfr sizeof(logintmp), (size_t *)0); 11031541Srgrimes if (error == ENAMETOOLONG) 11041541Srgrimes error = EINVAL; 110522522Sdavidn else if (!error) 110622522Sdavidn (void) memcpy(p->p_pgrp->pg_session->s_login, logintmp, 110723330Sache sizeof(logintmp)); 11081541Srgrimes return (error); 11091541Srgrimes} 111031891Ssef 111131891Ssefvoid 111231891Ssefsetsugid(p) 111355338Sphk struct proc *p; 111431891Ssef{ 111531891Ssef p->p_flag |= P_SUGID; 111655707Ssef if (!(p->p_pfsflags & PF_ISUGID)) 111731891Ssef p->p_stops = 0; 111831891Ssef} 1119