kern_prot.c revision 150634
1139804Simp/*- 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. 987218Srwatson * Copyright (c) 2000-2001 Robert N. M. Watson. All rights reserved. 101541Srgrimes * 111541Srgrimes * Redistribution and use in source and binary forms, with or without 121541Srgrimes * modification, are permitted provided that the following conditions 131541Srgrimes * are met: 141541Srgrimes * 1. Redistributions of source code must retain the above copyright 151541Srgrimes * notice, this list of conditions and the following disclaimer. 161541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 171541Srgrimes * notice, this list of conditions and the following disclaimer in the 181541Srgrimes * documentation and/or other materials provided with the distribution. 191541Srgrimes * 4. Neither the name of the University nor the names of its contributors 201541Srgrimes * may be used to endorse or promote products derived from this software 211541Srgrimes * without specific prior written permission. 221541Srgrimes * 231541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 241541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 251541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 261541Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 271541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 281541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 291541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 301541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 311541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 321541Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 331541Srgrimes * SUCH DAMAGE. 341541Srgrimes * 351541Srgrimes * @(#)kern_prot.c 8.6 (Berkeley) 1/21/94 361541Srgrimes */ 371541Srgrimes 381541Srgrimes/* 391541Srgrimes * System calls related to processes and protection 401541Srgrimes */ 411541Srgrimes 42116182Sobrien#include <sys/cdefs.h> 43116182Sobrien__FBSDID("$FreeBSD: head/sys/kern/kern_prot.c 150634 2005-09-27 18:09:42Z jhb $"); 44116182Sobrien 4531778Seivind#include "opt_compat.h" 46101001Srwatson#include "opt_mac.h" 4731778Seivind 481541Srgrimes#include <sys/param.h> 4976166Smarkm#include <sys/systm.h> 501541Srgrimes#include <sys/acct.h> 51132548Srwatson#include <sys/kdb.h> 5241059Speter#include <sys/kernel.h> 5370317Sjake#include <sys/lock.h> 54101173Srwatson#include <sys/mac.h> 5591140Stanimura#include <sys/malloc.h> 5676166Smarkm#include <sys/mutex.h> 57150634Sjhb#include <sys/refcount.h> 5891140Stanimura#include <sys/sx.h> 591541Srgrimes#include <sys/proc.h> 6076166Smarkm#include <sys/sysproto.h> 6187218Srwatson#include <sys/jail.h> 6231891Ssef#include <sys/pioctl.h> 6365495Struckman#include <sys/resourcevar.h> 6492976Srwatson#include <sys/socket.h> 6592976Srwatson#include <sys/socketvar.h> 6661287Srwatson#include <sys/sysctl.h> 671541Srgrimes 6830354Sphkstatic MALLOC_DEFINE(M_CRED, "cred", "credentials"); 6930354Sphk 7089414SarrSYSCTL_DECL(_security); 7189414SarrSYSCTL_NODE(_security, OID_AUTO, bsd, CTLFLAG_RW, 0, 7287138Srwatson "BSD security policy"); 7387138Srwatson 7412221Sbde#ifndef _SYS_SYSPROTO_H_ 7511332Sswallacestruct getpid_args { 761541Srgrimes int dummy; 771541Srgrimes}; 7812221Sbde#endif 7958717Sdillon/* 8082749Sdillon * MPSAFE 8182749Sdillon */ 821541Srgrimes/* ARGSUSED */ 831549Srgrimesint 8493580Sjhbgetpid(struct thread *td, struct getpid_args *uap) 851541Srgrimes{ 8683366Sjulian struct proc *p = td->td_proc; 871541Srgrimes 8883366Sjulian td->td_retval[0] = p->p_pid; 89130344Sphk#if defined(COMPAT_43) 9074728Sjhb PROC_LOCK(p); 9183366Sjulian td->td_retval[1] = p->p_pptr->p_pid; 9274728Sjhb PROC_UNLOCK(p); 931541Srgrimes#endif 941541Srgrimes return (0); 951541Srgrimes} 961541Srgrimes 9712221Sbde#ifndef _SYS_SYSPROTO_H_ 9811332Sswallacestruct getppid_args { 9911332Sswallace int dummy; 10011332Sswallace}; 10112221Sbde#endif 10282749Sdillon/* 10382749Sdillon * MPSAFE 10482749Sdillon */ 1051541Srgrimes/* ARGSUSED */ 1061549Srgrimesint 10793580Sjhbgetppid(struct thread *td, struct getppid_args *uap) 1081541Srgrimes{ 10983366Sjulian struct proc *p = td->td_proc; 1101541Srgrimes 11174728Sjhb PROC_LOCK(p); 11283366Sjulian td->td_retval[0] = p->p_pptr->p_pid; 11374728Sjhb PROC_UNLOCK(p); 1141541Srgrimes return (0); 1151541Srgrimes} 1161541Srgrimes 11787466Srwatson/* 11887218Srwatson * Get process group ID; note that POSIX getpgrp takes no parameter. 11958717Sdillon */ 12012221Sbde#ifndef _SYS_SYSPROTO_H_ 12111332Sswallacestruct getpgrp_args { 12211332Sswallace int dummy; 12311332Sswallace}; 12412221Sbde#endif 12582749Sdillon/* 12682749Sdillon * MPSAFE 12782749Sdillon */ 1281549Srgrimesint 12993580Sjhbgetpgrp(struct thread *td, struct getpgrp_args *uap) 1301541Srgrimes{ 13183366Sjulian struct proc *p = td->td_proc; 1321541Srgrimes 13391140Stanimura PROC_LOCK(p); 13483366Sjulian td->td_retval[0] = p->p_pgrp->pg_id; 13591140Stanimura PROC_UNLOCK(p); 1361541Srgrimes return (0); 1371541Srgrimes} 1381541Srgrimes 13928401Speter/* Get an arbitary pid's process group id */ 14012221Sbde#ifndef _SYS_SYSPROTO_H_ 14128401Speterstruct getpgid_args { 14228401Speter pid_t pid; 14328401Speter}; 14428401Speter#endif 14582749Sdillon/* 14682749Sdillon * MPSAFE 14782749Sdillon */ 14828401Speterint 14993580Sjhbgetpgid(struct thread *td, struct getpgid_args *uap) 15028401Speter{ 151114031Sjhb struct proc *p; 15292985Sjhb int error; 15341726Struckman 15491140Stanimura if (uap->pid == 0) { 155114031Sjhb p = td->td_proc; 15691140Stanimura PROC_LOCK(p); 157114031Sjhb } else { 158114031Sjhb p = pfind(uap->pid); 159114031Sjhb if (p == NULL) 160114031Sjhb return (ESRCH); 161114031Sjhb error = p_cansee(td, p); 162114031Sjhb if (error) { 163114031Sjhb PROC_UNLOCK(p); 164114031Sjhb return (error); 165114031Sjhb } 16675893Sjhb } 167114031Sjhb td->td_retval[0] = p->p_pgrp->pg_id; 168114031Sjhb PROC_UNLOCK(p); 169114031Sjhb return (0); 17028401Speter} 17128401Speter 17228401Speter/* 17328401Speter * Get an arbitary pid's session id. 17428401Speter */ 17528401Speter#ifndef _SYS_SYSPROTO_H_ 17628401Speterstruct getsid_args { 17728401Speter pid_t pid; 17828401Speter}; 17928401Speter#endif 18082749Sdillon/* 18182749Sdillon * MPSAFE 18282749Sdillon */ 18328401Speterint 18493580Sjhbgetsid(struct thread *td, struct getsid_args *uap) 18528401Speter{ 186114031Sjhb struct proc *p; 18787218Srwatson int error; 18841726Struckman 18991140Stanimura if (uap->pid == 0) { 190114031Sjhb p = td->td_proc; 19191140Stanimura PROC_LOCK(p); 192114031Sjhb } else { 193114031Sjhb p = pfind(uap->pid); 194114031Sjhb if (p == NULL) 195114031Sjhb return (ESRCH); 196114031Sjhb error = p_cansee(td, p); 197114031Sjhb if (error) { 198114031Sjhb PROC_UNLOCK(p); 199114031Sjhb return (error); 200114031Sjhb } 20175893Sjhb } 202114031Sjhb td->td_retval[0] = p->p_session->s_sid; 203114031Sjhb PROC_UNLOCK(p); 204114031Sjhb return (0); 20528401Speter} 20628401Speter 20728401Speter#ifndef _SYS_SYSPROTO_H_ 20811332Sswallacestruct getuid_args { 20911332Sswallace int dummy; 21011332Sswallace}; 21112221Sbde#endif 21282749Sdillon/* 21382749Sdillon * MPSAFE 21482749Sdillon */ 2151541Srgrimes/* ARGSUSED */ 2161549Srgrimesint 21793580Sjhbgetuid(struct thread *td, struct getuid_args *uap) 2181541Srgrimes{ 2191541Srgrimes 22092987Sjhb td->td_retval[0] = td->td_ucred->cr_ruid; 221130344Sphk#if defined(COMPAT_43) 22292987Sjhb td->td_retval[1] = td->td_ucred->cr_uid; 2231541Srgrimes#endif 2241541Srgrimes return (0); 2251541Srgrimes} 2261541Srgrimes 22712221Sbde#ifndef _SYS_SYSPROTO_H_ 22811332Sswallacestruct geteuid_args { 22911332Sswallace int dummy; 23011332Sswallace}; 23112221Sbde#endif 23287218Srwatson/* 23387218Srwatson * MPSAFE 23487218Srwatson */ 2351541Srgrimes/* ARGSUSED */ 2361549Srgrimesint 23793580Sjhbgeteuid(struct thread *td, struct geteuid_args *uap) 2381541Srgrimes{ 23992987Sjhb 24092987Sjhb td->td_retval[0] = td->td_ucred->cr_uid; 2411541Srgrimes return (0); 2421541Srgrimes} 2431541Srgrimes 24412221Sbde#ifndef _SYS_SYSPROTO_H_ 24511332Sswallacestruct getgid_args { 24611332Sswallace int dummy; 24711332Sswallace}; 24812221Sbde#endif 24982749Sdillon/* 25082749Sdillon * MPSAFE 25182749Sdillon */ 2521541Srgrimes/* ARGSUSED */ 2531549Srgrimesint 25493580Sjhbgetgid(struct thread *td, struct getgid_args *uap) 2551541Srgrimes{ 2561541Srgrimes 25792987Sjhb td->td_retval[0] = td->td_ucred->cr_rgid; 258130344Sphk#if defined(COMPAT_43) 25992987Sjhb td->td_retval[1] = td->td_ucred->cr_groups[0]; 2601541Srgrimes#endif 2611541Srgrimes return (0); 2621541Srgrimes} 2631541Srgrimes 2641541Srgrimes/* 2651541Srgrimes * Get effective group ID. The "egid" is groups[0], and could be obtained 2661541Srgrimes * via getgroups. This syscall exists because it is somewhat painful to do 2671541Srgrimes * correctly in a library function. 2681541Srgrimes */ 26912221Sbde#ifndef _SYS_SYSPROTO_H_ 27011332Sswallacestruct getegid_args { 27111332Sswallace int dummy; 27211332Sswallace}; 27312221Sbde#endif 27482749Sdillon/* 27582749Sdillon * MPSAFE 27682749Sdillon */ 2771541Srgrimes/* ARGSUSED */ 2781549Srgrimesint 27993580Sjhbgetegid(struct thread *td, struct getegid_args *uap) 2801541Srgrimes{ 2811541Srgrimes 28292987Sjhb td->td_retval[0] = td->td_ucred->cr_groups[0]; 2831541Srgrimes return (0); 2841541Srgrimes} 2851541Srgrimes 28612221Sbde#ifndef _SYS_SYSPROTO_H_ 2871541Srgrimesstruct getgroups_args { 2881541Srgrimes u_int gidsetsize; 2891541Srgrimes gid_t *gidset; 2901541Srgrimes}; 29112221Sbde#endif 29282749Sdillon/* 29382749Sdillon * MPSAFE 29482749Sdillon */ 2951549Srgrimesint 29693580Sjhbgetgroups(struct thread *td, register struct getgroups_args *uap) 2971541Srgrimes{ 29882749Sdillon struct ucred *cred; 29977183Srwatson u_int ngrp; 30087218Srwatson int error; 3011541Srgrimes 30292987Sjhb cred = td->td_ucred; 3031541Srgrimes if ((ngrp = uap->gidsetsize) == 0) { 30483366Sjulian td->td_retval[0] = cred->cr_ngroups; 30592987Sjhb return (0); 3061541Srgrimes } 30792987Sjhb if (ngrp < cred->cr_ngroups) 30892987Sjhb return (EINVAL); 30977183Srwatson ngrp = cred->cr_ngroups; 31099009Salfred error = copyout(cred->cr_groups, uap->gidset, ngrp * sizeof(gid_t)); 31193264Sdillon if (error == 0) 31293557Sjhb td->td_retval[0] = ngrp; 31393264Sdillon return (error); 3141541Srgrimes} 3151541Srgrimes 31612221Sbde#ifndef _SYS_SYSPROTO_H_ 31712207Sbdestruct setsid_args { 31811332Sswallace int dummy; 31911332Sswallace}; 32012221Sbde#endif 32182749Sdillon/* 32282749Sdillon * MPSAFE 32382749Sdillon */ 3241541Srgrimes/* ARGSUSED */ 3251549Srgrimesint 32693580Sjhbsetsid(register struct thread *td, struct setsid_args *uap) 3271541Srgrimes{ 32891140Stanimura struct pgrp *pgrp; 32982749Sdillon int error; 33083366Sjulian struct proc *p = td->td_proc; 33191140Stanimura struct pgrp *newpgrp; 33291140Stanimura struct session *newsess; 3331541Srgrimes 33491140Stanimura error = 0; 33591140Stanimura pgrp = NULL; 33691140Stanimura 337111119Simp MALLOC(newpgrp, struct pgrp *, sizeof(struct pgrp), M_PGRP, M_WAITOK | M_ZERO); 338111119Simp MALLOC(newsess, struct session *, sizeof(struct session), M_SESSION, M_WAITOK | M_ZERO); 33991140Stanimura 34094859Sjhb sx_xlock(&proctree_lock); 34191140Stanimura 34291140Stanimura if (p->p_pgid == p->p_pid || (pgrp = pgfind(p->p_pid)) != NULL) { 34391140Stanimura if (pgrp != NULL) 34491140Stanimura PGRP_UNLOCK(pgrp); 34582749Sdillon error = EPERM; 34691140Stanimura } else { 34791140Stanimura (void)enterpgrp(p, p->p_pid, newpgrp, newsess); 34883366Sjulian td->td_retval[0] = p->p_pid; 34994859Sjhb newpgrp = NULL; 35094859Sjhb newsess = NULL; 3511541Srgrimes } 35291140Stanimura 35394859Sjhb sx_xunlock(&proctree_lock); 35491140Stanimura 35595973Stanimura if (newpgrp != NULL) 35695973Stanimura FREE(newpgrp, M_PGRP); 35795973Stanimura if (newsess != NULL) 35895973Stanimura FREE(newsess, M_SESSION); 35991140Stanimura 36094859Sjhb return (error); 3611541Srgrimes} 3621541Srgrimes 3631541Srgrimes/* 3641541Srgrimes * set process group (setpgid/old setpgrp) 3651541Srgrimes * 3661541Srgrimes * caller does setpgid(targpid, targpgid) 3671541Srgrimes * 3681541Srgrimes * pid must be caller or child of caller (ESRCH) 3691541Srgrimes * if a child 3701541Srgrimes * pid must be in same session (EPERM) 3711541Srgrimes * pid can't have done an exec (EACCES) 3721541Srgrimes * if pgid != pid 3731541Srgrimes * there must exist some pid in same session having pgid (EPERM) 3741541Srgrimes * pid must not be session leader (EPERM) 3751541Srgrimes */ 37612221Sbde#ifndef _SYS_SYSPROTO_H_ 3771541Srgrimesstruct setpgid_args { 37887218Srwatson int pid; /* target process id */ 37987218Srwatson int pgid; /* target pgrp id */ 3801541Srgrimes}; 38112221Sbde#endif 38282749Sdillon/* 38382749Sdillon * MPSAFE 38482749Sdillon */ 3851541Srgrimes/* ARGSUSED */ 3861549Srgrimesint 38793580Sjhbsetpgid(struct thread *td, register struct setpgid_args *uap) 3881541Srgrimes{ 38983366Sjulian struct proc *curp = td->td_proc; 39087218Srwatson register struct proc *targp; /* target process */ 39187218Srwatson register struct pgrp *pgrp; /* target pgrp */ 39275448Srwatson int error; 39391140Stanimura struct pgrp *newpgrp; 3941541Srgrimes 39520677Sbde if (uap->pgid < 0) 39620677Sbde return (EINVAL); 39791140Stanimura 39891140Stanimura error = 0; 39991140Stanimura 400111119Simp MALLOC(newpgrp, struct pgrp *, sizeof(struct pgrp), M_PGRP, M_WAITOK | M_ZERO); 40191140Stanimura 40294859Sjhb sx_xlock(&proctree_lock); 4031541Srgrimes if (uap->pid != 0 && uap->pid != curp->p_pid) { 40491140Stanimura if ((targp = pfind(uap->pid)) == NULL) { 40582749Sdillon error = ESRCH; 40694859Sjhb goto done; 40775893Sjhb } 40891140Stanimura if (!inferior(targp)) { 40991140Stanimura PROC_UNLOCK(targp); 41091371Stanimura error = ESRCH; 41194859Sjhb goto done; 41291140Stanimura } 413132568Srwatson if ((error = p_cansee(td, targp))) { 41475893Sjhb PROC_UNLOCK(targp); 41594859Sjhb goto done; 41675893Sjhb } 41775893Sjhb if (targp->p_pgrp == NULL || 41875893Sjhb targp->p_session != curp->p_session) { 41975893Sjhb PROC_UNLOCK(targp); 42082749Sdillon error = EPERM; 42194859Sjhb goto done; 42275893Sjhb } 42375893Sjhb if (targp->p_flag & P_EXEC) { 42475893Sjhb PROC_UNLOCK(targp); 42582749Sdillon error = EACCES; 42694859Sjhb goto done; 42775893Sjhb } 42891140Stanimura PROC_UNLOCK(targp); 42991140Stanimura } else 4301541Srgrimes targp = curp; 43175893Sjhb if (SESS_LEADER(targp)) { 43282749Sdillon error = EPERM; 43394859Sjhb goto done; 43475893Sjhb } 43587218Srwatson if (uap->pgid == 0) 4361541Srgrimes uap->pgid = targp->p_pid; 437117214Scognet if ((pgrp = pgfind(uap->pgid)) == NULL) { 438117214Scognet if (uap->pgid == targp->p_pid) { 439117214Scognet error = enterpgrp(targp, uap->pgid, newpgrp, 440117214Scognet NULL); 441117214Scognet if (error == 0) 442117214Scognet newpgrp = NULL; 443117214Scognet } else 444117214Scognet error = EPERM; 44591140Stanimura } else { 446117214Scognet if (pgrp == targp->p_pgrp) { 447117214Scognet PGRP_UNLOCK(pgrp); 44894859Sjhb goto done; 44975893Sjhb } 450117214Scognet if (pgrp->pg_id != targp->p_pid && 451117214Scognet pgrp->pg_session != curp->p_session) { 45291140Stanimura PGRP_UNLOCK(pgrp); 453117214Scognet error = EPERM; 45491140Stanimura goto done; 45591140Stanimura } 45691140Stanimura PGRP_UNLOCK(pgrp); 45791140Stanimura error = enterthispgrp(targp, pgrp); 45882749Sdillon } 45991140Stanimuradone: 46094859Sjhb sx_xunlock(&proctree_lock); 46194859Sjhb KASSERT((error == 0) || (newpgrp != NULL), 46294859Sjhb ("setpgid failed and newpgrp is NULL")); 46395973Stanimura if (newpgrp != NULL) 46491140Stanimura FREE(newpgrp, M_PGRP); 46582749Sdillon return (error); 4661541Srgrimes} 4671541Srgrimes 46824448Speter/* 46924448Speter * Use the clause in B.4.2.2 that allows setuid/setgid to be 4.2/4.3BSD 47072093Sasmodai * compatible. It says that setting the uid/gid to euid/egid is a special 47124448Speter * case of "appropriate privilege". Once the rules are expanded out, this 47224448Speter * basically means that setuid(nnn) sets all three id's, in all permitted 47324448Speter * cases unless _POSIX_SAVED_IDS is enabled. In that case, setuid(getuid()) 47424448Speter * does not set the saved id - this is dangerous for traditional BSD 47524448Speter * programs. For this reason, we *really* do not want to set 47624448Speter * _POSIX_SAVED_IDS and do not want to clear POSIX_APPENDIX_B_4_2_2. 47724448Speter */ 47824448Speter#define POSIX_APPENDIX_B_4_2_2 47924448Speter 48012221Sbde#ifndef _SYS_SYSPROTO_H_ 4811541Srgrimesstruct setuid_args { 4821541Srgrimes uid_t uid; 4831541Srgrimes}; 48412221Sbde#endif 48582749Sdillon/* 48682749Sdillon * MPSAFE 48782749Sdillon */ 4881541Srgrimes/* ARGSUSED */ 4891549Srgrimesint 49093580Sjhbsetuid(struct thread *td, struct setuid_args *uap) 4911541Srgrimes{ 49283366Sjulian struct proc *p = td->td_proc; 49377183Srwatson struct ucred *newcred, *oldcred; 49477183Srwatson uid_t uid; 49598417Salfred struct uidinfo *uip; 49687218Srwatson int error; 4971541Srgrimes 49877183Srwatson uid = uap->uid; 49994619Sjhb newcred = crget(); 50098417Salfred uip = uifind(uid); 50194619Sjhb PROC_LOCK(p); 50287219Srwatson oldcred = p->p_ucred; 50387466Srwatson 504145147Srwatson#ifdef MAC 505145147Srwatson error = mac_check_proc_setuid(p, oldcred, uid); 506145147Srwatson if (error) 507145147Srwatson goto fail; 508145147Srwatson#endif 509145147Srwatson 51024448Speter /* 51124448Speter * See if we have "permission" by POSIX 1003.1 rules. 51224448Speter * 51387218Srwatson * Note that setuid(geteuid()) is a special case of 51424448Speter * "appropriate privileges" in appendix B.4.2.2. We need 51572093Sasmodai * to use this clause to be compatible with traditional BSD 51624448Speter * semantics. Basically, it means that "setuid(xx)" sets all 51724448Speter * three id's (assuming you have privs). 51824448Speter * 51924448Speter * Notes on the logic. We do things in three steps. 52024448Speter * 1: We determine if the euid is going to change, and do EPERM 52124448Speter * right away. We unconditionally change the euid later if this 52224448Speter * test is satisfied, simplifying that part of the logic. 52387218Srwatson * 2: We determine if the real and/or saved uids are going to 52424448Speter * change. Determined by compile options. 52524448Speter * 3: Change euid last. (after tests in #2 for "appropriate privs") 52624448Speter */ 52777183Srwatson if (uid != oldcred->cr_ruid && /* allow setuid(getuid()) */ 52817994Sache#ifdef _POSIX_SAVED_IDS 52977183Srwatson uid != oldcred->cr_svuid && /* allow setuid(saved gid) */ 53017994Sache#endif 53124448Speter#ifdef POSIX_APPENDIX_B_4_2_2 /* Use BSD-compat clause from B.4.2.2 */ 53277183Srwatson uid != oldcred->cr_uid && /* allow setuid(geteuid()) */ 53324448Speter#endif 534145147Srwatson (error = suser_cred(oldcred, SUSER_ALLOWJAIL)) != 0) 535145147Srwatson goto fail; 53624448Speter 53798417Salfred /* 53898417Salfred * Copy credentials so other references do not see our changes. 53998417Salfred */ 54094619Sjhb crcopy(newcred, oldcred); 54124448Speter#ifdef _POSIX_SAVED_IDS 5421541Srgrimes /* 54324448Speter * Do we have "appropriate privileges" (are we root or uid == euid) 54424448Speter * If so, we are changing the real uid and/or saved uid. 5451541Srgrimes */ 54617994Sache if ( 54724448Speter#ifdef POSIX_APPENDIX_B_4_2_2 /* Use the clause from B.4.2.2 */ 54877183Srwatson uid == oldcred->cr_uid || 54917994Sache#endif 550132653Scperciva suser_cred(oldcred, SUSER_ALLOWJAIL) == 0) /* we are using privs */ 55117994Sache#endif 55224448Speter { 55324448Speter /* 55465495Struckman * Set the real uid and transfer proc count to new user. 55524448Speter */ 55677183Srwatson if (uid != oldcred->cr_ruid) { 55798417Salfred change_ruid(newcred, uip); 55865495Struckman setsugid(p); 55924448Speter } 56024448Speter /* 56124448Speter * Set saved uid 56224448Speter * 56324448Speter * XXX always set saved uid even if not _POSIX_SAVED_IDS, as 56424448Speter * the security of seteuid() depends on it. B.4.2.2 says it 56524448Speter * is important that we should do this. 56624448Speter */ 56777183Srwatson if (uid != oldcred->cr_svuid) { 56877183Srwatson change_svuid(newcred, uid); 56931891Ssef setsugid(p); 57024448Speter } 5718141Sache } 57224448Speter 57324448Speter /* 57424448Speter * In all permitted cases, we are changing the euid. 57524448Speter */ 57677183Srwatson if (uid != oldcred->cr_uid) { 57798417Salfred change_euid(newcred, uip); 57831891Ssef setsugid(p); 57924448Speter } 58077183Srwatson p->p_ucred = newcred; 58194619Sjhb PROC_UNLOCK(p); 58298417Salfred uifree(uip); 58377183Srwatson crfree(oldcred); 58494619Sjhb return (0); 585145147Srwatson 586145147Srwatsonfail: 587145147Srwatson PROC_UNLOCK(p); 588145147Srwatson uifree(uip); 589145147Srwatson crfree(newcred); 590145147Srwatson return (error); 5911541Srgrimes} 5921541Srgrimes 59312221Sbde#ifndef _SYS_SYSPROTO_H_ 5941541Srgrimesstruct seteuid_args { 5951541Srgrimes uid_t euid; 5961541Srgrimes}; 59712221Sbde#endif 59882749Sdillon/* 59982749Sdillon * MPSAFE 60082749Sdillon */ 6011541Srgrimes/* ARGSUSED */ 6021549Srgrimesint 60393580Sjhbseteuid(struct thread *td, struct seteuid_args *uap) 6041541Srgrimes{ 60583366Sjulian struct proc *p = td->td_proc; 60677183Srwatson struct ucred *newcred, *oldcred; 60777183Srwatson uid_t euid; 60898417Salfred struct uidinfo *euip; 60987218Srwatson int error; 6101541Srgrimes 6111541Srgrimes euid = uap->euid; 61294619Sjhb newcred = crget(); 61398417Salfred euip = uifind(euid); 61494619Sjhb PROC_LOCK(p); 61577183Srwatson oldcred = p->p_ucred; 616145147Srwatson 617145147Srwatson#ifdef MAC 618145147Srwatson error = mac_check_proc_seteuid(p, oldcred, euid); 619145147Srwatson if (error) 620145147Srwatson goto fail; 621145147Srwatson#endif 622145147Srwatson 62377183Srwatson if (euid != oldcred->cr_ruid && /* allow seteuid(getuid()) */ 62477183Srwatson euid != oldcred->cr_svuid && /* allow seteuid(saved uid) */ 625145147Srwatson (error = suser_cred(oldcred, SUSER_ALLOWJAIL)) != 0) 626145147Srwatson goto fail; 627145147Srwatson 6281541Srgrimes /* 6291541Srgrimes * Everything's okay, do it. Copy credentials so other references do 6301541Srgrimes * not see our changes. 6311541Srgrimes */ 63294619Sjhb crcopy(newcred, oldcred); 63377183Srwatson if (oldcred->cr_uid != euid) { 63498417Salfred change_euid(newcred, euip); 63531891Ssef setsugid(p); 63624449Speter } 63777183Srwatson p->p_ucred = newcred; 63894619Sjhb PROC_UNLOCK(p); 63998417Salfred uifree(euip); 64077183Srwatson crfree(oldcred); 64194619Sjhb return (0); 642145147Srwatson 643145147Srwatsonfail: 644145147Srwatson PROC_UNLOCK(p); 645145147Srwatson uifree(euip); 646145147Srwatson crfree(newcred); 647145147Srwatson return (error); 6481541Srgrimes} 6491541Srgrimes 65012221Sbde#ifndef _SYS_SYSPROTO_H_ 6511541Srgrimesstruct setgid_args { 6521541Srgrimes gid_t gid; 6531541Srgrimes}; 65412221Sbde#endif 65582749Sdillon/* 65682749Sdillon * MPSAFE 65782749Sdillon */ 6581541Srgrimes/* ARGSUSED */ 6591549Srgrimesint 66093580Sjhbsetgid(struct thread *td, struct setgid_args *uap) 6611541Srgrimes{ 66283366Sjulian struct proc *p = td->td_proc; 66377183Srwatson struct ucred *newcred, *oldcred; 66477183Srwatson gid_t gid; 66587218Srwatson int error; 6661541Srgrimes 66777183Srwatson gid = uap->gid; 66894619Sjhb newcred = crget(); 66994619Sjhb PROC_LOCK(p); 67077183Srwatson oldcred = p->p_ucred; 67187466Srwatson 672145147Srwatson#ifdef MAC 673145147Srwatson error = mac_check_proc_setgid(p, oldcred, gid); 674145147Srwatson if (error) 675145147Srwatson goto fail; 676145147Srwatson#endif 677145147Srwatson 67824448Speter /* 67924448Speter * See if we have "permission" by POSIX 1003.1 rules. 68024448Speter * 68124448Speter * Note that setgid(getegid()) is a special case of 68224448Speter * "appropriate privileges" in appendix B.4.2.2. We need 68372093Sasmodai * to use this clause to be compatible with traditional BSD 68424448Speter * semantics. Basically, it means that "setgid(xx)" sets all 68524448Speter * three id's (assuming you have privs). 68624448Speter * 68724448Speter * For notes on the logic here, see setuid() above. 68824448Speter */ 68977183Srwatson if (gid != oldcred->cr_rgid && /* allow setgid(getgid()) */ 69017994Sache#ifdef _POSIX_SAVED_IDS 69177183Srwatson gid != oldcred->cr_svgid && /* allow setgid(saved gid) */ 69217994Sache#endif 69324448Speter#ifdef POSIX_APPENDIX_B_4_2_2 /* Use BSD-compat clause from B.4.2.2 */ 69477183Srwatson gid != oldcred->cr_groups[0] && /* allow setgid(getegid()) */ 69524448Speter#endif 696145147Srwatson (error = suser_cred(oldcred, SUSER_ALLOWJAIL)) != 0) 697145147Srwatson goto fail; 69824448Speter 69994619Sjhb crcopy(newcred, oldcred); 70017994Sache#ifdef _POSIX_SAVED_IDS 70124448Speter /* 70224448Speter * Do we have "appropriate privileges" (are we root or gid == egid) 70324448Speter * If so, we are changing the real uid and saved gid. 70424448Speter */ 70524448Speter if ( 70624448Speter#ifdef POSIX_APPENDIX_B_4_2_2 /* use the clause from B.4.2.2 */ 70777183Srwatson gid == oldcred->cr_groups[0] || 70817994Sache#endif 709132653Scperciva suser_cred(oldcred, SUSER_ALLOWJAIL) == 0) /* we are using privs */ 71024448Speter#endif 71124448Speter { 71224448Speter /* 71324448Speter * Set real gid 71424448Speter */ 71577183Srwatson if (oldcred->cr_rgid != gid) { 71677183Srwatson change_rgid(newcred, gid); 71731891Ssef setsugid(p); 71824448Speter } 71924448Speter /* 72024448Speter * Set saved gid 72124448Speter * 72224448Speter * XXX always set saved gid even if not _POSIX_SAVED_IDS, as 72324448Speter * the security of setegid() depends on it. B.4.2.2 says it 72424448Speter * is important that we should do this. 72524448Speter */ 72677183Srwatson if (oldcred->cr_svgid != gid) { 72777183Srwatson change_svgid(newcred, gid); 72831891Ssef setsugid(p); 72924448Speter } 7308141Sache } 73124448Speter /* 73224448Speter * In all cases permitted cases, we are changing the egid. 73324448Speter * Copy credentials so other references do not see our changes. 73424448Speter */ 73577183Srwatson if (oldcred->cr_groups[0] != gid) { 73677183Srwatson change_egid(newcred, gid); 73731891Ssef setsugid(p); 73824448Speter } 73977183Srwatson p->p_ucred = newcred; 74094619Sjhb PROC_UNLOCK(p); 74177183Srwatson crfree(oldcred); 74294619Sjhb return (0); 743145147Srwatson 744145147Srwatsonfail: 745145147Srwatson PROC_UNLOCK(p); 746145147Srwatson crfree(newcred); 747145147Srwatson return (error); 7481541Srgrimes} 7491541Srgrimes 75012221Sbde#ifndef _SYS_SYSPROTO_H_ 7511541Srgrimesstruct setegid_args { 7521541Srgrimes gid_t egid; 7531541Srgrimes}; 75412221Sbde#endif 75582749Sdillon/* 75682749Sdillon * MPSAFE 75782749Sdillon */ 7581541Srgrimes/* ARGSUSED */ 7591549Srgrimesint 76093580Sjhbsetegid(struct thread *td, struct setegid_args *uap) 7611541Srgrimes{ 76283366Sjulian struct proc *p = td->td_proc; 76377183Srwatson struct ucred *newcred, *oldcred; 76477183Srwatson gid_t egid; 76587218Srwatson int error; 7661541Srgrimes 7671541Srgrimes egid = uap->egid; 76894619Sjhb newcred = crget(); 76994619Sjhb PROC_LOCK(p); 77077183Srwatson oldcred = p->p_ucred; 771145147Srwatson 772145147Srwatson#ifdef MAC 773145147Srwatson error = mac_check_proc_setegid(p, oldcred, egid); 774145147Srwatson if (error) 775145147Srwatson goto fail; 776145147Srwatson#endif 777145147Srwatson 77877183Srwatson if (egid != oldcred->cr_rgid && /* allow setegid(getgid()) */ 77977183Srwatson egid != oldcred->cr_svgid && /* allow setegid(saved gid) */ 780145147Srwatson (error = suser_cred(oldcred, SUSER_ALLOWJAIL)) != 0) 781145147Srwatson goto fail; 782145147Srwatson 78394619Sjhb crcopy(newcred, oldcred); 78477183Srwatson if (oldcred->cr_groups[0] != egid) { 78577183Srwatson change_egid(newcred, egid); 78631891Ssef setsugid(p); 78724449Speter } 78877183Srwatson p->p_ucred = newcred; 78994619Sjhb PROC_UNLOCK(p); 79077183Srwatson crfree(oldcred); 79194619Sjhb return (0); 792145147Srwatson 793145147Srwatsonfail: 794145147Srwatson PROC_UNLOCK(p); 795145147Srwatson crfree(newcred); 796145147Srwatson return (error); 7971541Srgrimes} 7981541Srgrimes 79912221Sbde#ifndef _SYS_SYSPROTO_H_ 8001541Srgrimesstruct setgroups_args { 8011541Srgrimes u_int gidsetsize; 8021541Srgrimes gid_t *gidset; 8031541Srgrimes}; 80412221Sbde#endif 80582749Sdillon/* 80682749Sdillon * MPSAFE 80782749Sdillon */ 8081541Srgrimes/* ARGSUSED */ 8091549Srgrimesint 81093580Sjhbsetgroups(struct thread *td, struct setgroups_args *uap) 8111541Srgrimes{ 81283366Sjulian struct proc *p = td->td_proc; 81394619Sjhb struct ucred *newcred, *tempcred, *oldcred; 81477183Srwatson u_int ngrp; 8151541Srgrimes int error; 8161541Srgrimes 81787220Srwatson ngrp = uap->gidsetsize; 81894619Sjhb if (ngrp > NGROUPS) 81994619Sjhb return (EINVAL); 82094619Sjhb tempcred = crget(); 82199009Salfred error = copyin(uap->gidset, tempcred->cr_groups, ngrp * sizeof(gid_t)); 82294619Sjhb if (error != 0) { 82394619Sjhb crfree(tempcred); 82494619Sjhb return (error); 82594619Sjhb } 82694619Sjhb newcred = crget(); 82794619Sjhb PROC_LOCK(p); 82877183Srwatson oldcred = p->p_ucred; 829145147Srwatson 830145147Srwatson#ifdef MAC 831145147Srwatson error = mac_check_proc_setgroups(p, oldcred, ngrp, 832145147Srwatson tempcred->cr_groups); 833145147Srwatson if (error) 834145147Srwatson goto fail; 835145147Srwatson#endif 836145147Srwatson 837132653Scperciva error = suser_cred(oldcred, SUSER_ALLOWJAIL); 838145147Srwatson if (error) 839145147Srwatson goto fail; 840145147Srwatson 84124447Speter /* 84224447Speter * XXX A little bit lazy here. We could test if anything has 84324447Speter * changed before crcopy() and setting P_SUGID. 84424447Speter */ 84594619Sjhb crcopy(newcred, oldcred); 84624447Speter if (ngrp < 1) { 84724447Speter /* 84824447Speter * setgroups(0, NULL) is a legitimate way of clearing the 84924447Speter * groups vector on non-BSD systems (which generally do not 85024447Speter * have the egid in the groups[0]). We risk security holes 85124447Speter * when running non-BSD software if we do not do the same. 85224447Speter */ 85377183Srwatson newcred->cr_ngroups = 1; 85424447Speter } else { 85594619Sjhb bcopy(tempcred->cr_groups, newcred->cr_groups, 85694619Sjhb ngrp * sizeof(gid_t)); 85777183Srwatson newcred->cr_ngroups = ngrp; 85824447Speter } 85931891Ssef setsugid(p); 86077183Srwatson p->p_ucred = newcred; 86194619Sjhb PROC_UNLOCK(p); 86294619Sjhb crfree(tempcred); 86377183Srwatson crfree(oldcred); 86494619Sjhb return (0); 865145147Srwatson 866145147Srwatsonfail: 867145147Srwatson PROC_UNLOCK(p); 868145147Srwatson crfree(newcred); 869145147Srwatson crfree(tempcred); 870145147Srwatson return (error); 8711541Srgrimes} 8721541Srgrimes 87312221Sbde#ifndef _SYS_SYSPROTO_H_ 8741541Srgrimesstruct setreuid_args { 8759238Sache uid_t ruid; 8769238Sache uid_t euid; 8771541Srgrimes}; 87812221Sbde#endif 87982749Sdillon/* 88082749Sdillon * MPSAFE 88182749Sdillon */ 8821541Srgrimes/* ARGSUSED */ 8831549Srgrimesint 88493580Sjhbsetreuid(register struct thread *td, struct setreuid_args *uap) 8851541Srgrimes{ 88683366Sjulian struct proc *p = td->td_proc; 88777183Srwatson struct ucred *newcred, *oldcred; 88887218Srwatson uid_t euid, ruid; 88998417Salfred struct uidinfo *euip, *ruip; 89087218Srwatson int error; 8911541Srgrimes 89287218Srwatson euid = uap->euid; 8939238Sache ruid = uap->ruid; 89494619Sjhb newcred = crget(); 89598417Salfred euip = uifind(euid); 89698417Salfred ruip = uifind(ruid); 89794619Sjhb PROC_LOCK(p); 89877183Srwatson oldcred = p->p_ucred; 899145147Srwatson 900145147Srwatson#ifdef MAC 901145147Srwatson error = mac_check_proc_setreuid(p, oldcred, ruid, euid); 902145147Srwatson if (error) 903145147Srwatson goto fail; 904145147Srwatson#endif 905145147Srwatson 90677183Srwatson if (((ruid != (uid_t)-1 && ruid != oldcred->cr_ruid && 90777183Srwatson ruid != oldcred->cr_svuid) || 90877183Srwatson (euid != (uid_t)-1 && euid != oldcred->cr_uid && 90977183Srwatson euid != oldcred->cr_ruid && euid != oldcred->cr_svuid)) && 910145147Srwatson (error = suser_cred(oldcred, SUSER_ALLOWJAIL)) != 0) 911145147Srwatson goto fail; 912145147Srwatson 91394619Sjhb crcopy(newcred, oldcred); 91477183Srwatson if (euid != (uid_t)-1 && oldcred->cr_uid != euid) { 91598417Salfred change_euid(newcred, euip); 91631891Ssef setsugid(p); 91724450Speter } 91877183Srwatson if (ruid != (uid_t)-1 && oldcred->cr_ruid != ruid) { 91998417Salfred change_ruid(newcred, ruip); 92031891Ssef setsugid(p); 9218135Sache } 92277183Srwatson if ((ruid != (uid_t)-1 || newcred->cr_uid != newcred->cr_ruid) && 92377183Srwatson newcred->cr_svuid != newcred->cr_uid) { 92477183Srwatson change_svuid(newcred, newcred->cr_uid); 92531891Ssef setsugid(p); 92624450Speter } 92777183Srwatson p->p_ucred = newcred; 92894619Sjhb PROC_UNLOCK(p); 92998417Salfred uifree(ruip); 93098417Salfred uifree(euip); 93177183Srwatson crfree(oldcred); 93294619Sjhb return (0); 933145147Srwatson 934145147Srwatsonfail: 935145147Srwatson PROC_UNLOCK(p); 936145147Srwatson uifree(ruip); 937145147Srwatson uifree(euip); 938145147Srwatson crfree(newcred); 939145147Srwatson return (error); 9401541Srgrimes} 9411541Srgrimes 94212221Sbde#ifndef _SYS_SYSPROTO_H_ 9431541Srgrimesstruct setregid_args { 9449238Sache gid_t rgid; 9459238Sache gid_t egid; 9461541Srgrimes}; 94712221Sbde#endif 94882749Sdillon/* 94982749Sdillon * MPSAFE 95082749Sdillon */ 9511541Srgrimes/* ARGSUSED */ 9521549Srgrimesint 95393580Sjhbsetregid(register struct thread *td, struct setregid_args *uap) 9541541Srgrimes{ 95583366Sjulian struct proc *p = td->td_proc; 95677183Srwatson struct ucred *newcred, *oldcred; 95787218Srwatson gid_t egid, rgid; 95887218Srwatson int error; 9591541Srgrimes 96087218Srwatson egid = uap->egid; 9619238Sache rgid = uap->rgid; 96294619Sjhb newcred = crget(); 96394619Sjhb PROC_LOCK(p); 96477183Srwatson oldcred = p->p_ucred; 965145147Srwatson 966145147Srwatson#ifdef MAC 967145147Srwatson error = mac_check_proc_setregid(p, oldcred, rgid, egid); 968145147Srwatson if (error) 969145147Srwatson goto fail; 970145147Srwatson#endif 971145147Srwatson 97277183Srwatson if (((rgid != (gid_t)-1 && rgid != oldcred->cr_rgid && 97377183Srwatson rgid != oldcred->cr_svgid) || 97477183Srwatson (egid != (gid_t)-1 && egid != oldcred->cr_groups[0] && 97577183Srwatson egid != oldcred->cr_rgid && egid != oldcred->cr_svgid)) && 976145147Srwatson (error = suser_cred(oldcred, SUSER_ALLOWJAIL)) != 0) 977145147Srwatson goto fail; 97894619Sjhb 97994619Sjhb crcopy(newcred, oldcred); 98077183Srwatson if (egid != (gid_t)-1 && oldcred->cr_groups[0] != egid) { 98177183Srwatson change_egid(newcred, egid); 98231891Ssef setsugid(p); 98324450Speter } 98477183Srwatson if (rgid != (gid_t)-1 && oldcred->cr_rgid != rgid) { 98577183Srwatson change_rgid(newcred, rgid); 98631891Ssef setsugid(p); 98724450Speter } 98877183Srwatson if ((rgid != (gid_t)-1 || newcred->cr_groups[0] != newcred->cr_rgid) && 98977183Srwatson newcred->cr_svgid != newcred->cr_groups[0]) { 99077183Srwatson change_svgid(newcred, newcred->cr_groups[0]); 99131891Ssef setsugid(p); 99224450Speter } 99377812Sru p->p_ucred = newcred; 99494619Sjhb PROC_UNLOCK(p); 99577812Sru crfree(oldcred); 99694619Sjhb return (0); 997145147Srwatson 998145147Srwatsonfail: 999145147Srwatson PROC_UNLOCK(p); 1000145147Srwatson crfree(newcred); 1001145147Srwatson return (error); 10021541Srgrimes} 10031541Srgrimes 100456115Speter/* 100556115Speter * setresuid(ruid, euid, suid) is like setreuid except control over the 100656115Speter * saved uid is explicit. 100756115Speter */ 100856115Speter 100924453Speter#ifndef _SYS_SYSPROTO_H_ 101056115Speterstruct setresuid_args { 101156115Speter uid_t ruid; 101256115Speter uid_t euid; 101356115Speter uid_t suid; 101456115Speter}; 101556115Speter#endif 101682749Sdillon/* 101782749Sdillon * MPSAFE 101882749Sdillon */ 101956115Speter/* ARGSUSED */ 102056115Speterint 102193580Sjhbsetresuid(register struct thread *td, struct setresuid_args *uap) 102256115Speter{ 102383366Sjulian struct proc *p = td->td_proc; 102477183Srwatson struct ucred *newcred, *oldcred; 102587218Srwatson uid_t euid, ruid, suid; 102698417Salfred struct uidinfo *euip, *ruip; 102756115Speter int error; 102856115Speter 102987218Srwatson euid = uap->euid; 103056115Speter ruid = uap->ruid; 103156115Speter suid = uap->suid; 103294619Sjhb newcred = crget(); 103398417Salfred euip = uifind(euid); 103498417Salfred ruip = uifind(ruid); 103594619Sjhb PROC_LOCK(p); 103677183Srwatson oldcred = p->p_ucred; 1037145147Srwatson 1038145147Srwatson#ifdef MAC 1039145147Srwatson error = mac_check_proc_setresuid(p, oldcred, ruid, euid, suid); 1040145147Srwatson if (error) 1041145147Srwatson goto fail; 1042145147Srwatson#endif 1043145147Srwatson 104477183Srwatson if (((ruid != (uid_t)-1 && ruid != oldcred->cr_ruid && 104577183Srwatson ruid != oldcred->cr_svuid && 104677183Srwatson ruid != oldcred->cr_uid) || 104777183Srwatson (euid != (uid_t)-1 && euid != oldcred->cr_ruid && 104877183Srwatson euid != oldcred->cr_svuid && 104977183Srwatson euid != oldcred->cr_uid) || 105077183Srwatson (suid != (uid_t)-1 && suid != oldcred->cr_ruid && 105177183Srwatson suid != oldcred->cr_svuid && 105277183Srwatson suid != oldcred->cr_uid)) && 1053145147Srwatson (error = suser_cred(oldcred, SUSER_ALLOWJAIL)) != 0) 1054145147Srwatson goto fail; 105594619Sjhb 105694619Sjhb crcopy(newcred, oldcred); 105777183Srwatson if (euid != (uid_t)-1 && oldcred->cr_uid != euid) { 105898417Salfred change_euid(newcred, euip); 105956115Speter setsugid(p); 106056115Speter } 106177183Srwatson if (ruid != (uid_t)-1 && oldcred->cr_ruid != ruid) { 106298417Salfred change_ruid(newcred, ruip); 106356115Speter setsugid(p); 106456115Speter } 106577183Srwatson if (suid != (uid_t)-1 && oldcred->cr_svuid != suid) { 106677183Srwatson change_svuid(newcred, suid); 106756115Speter setsugid(p); 106856115Speter } 106977183Srwatson p->p_ucred = newcred; 107094619Sjhb PROC_UNLOCK(p); 107198417Salfred uifree(ruip); 107298417Salfred uifree(euip); 107377183Srwatson crfree(oldcred); 107494619Sjhb return (0); 1075145147Srwatson 1076145147Srwatsonfail: 1077145147Srwatson PROC_UNLOCK(p); 1078145147Srwatson uifree(ruip); 1079145147Srwatson uifree(euip); 1080145147Srwatson crfree(newcred); 1081145147Srwatson return (error); 1082145147Srwatson 108356115Speter} 108456115Speter 108556115Speter/* 108656115Speter * setresgid(rgid, egid, sgid) is like setregid except control over the 108756115Speter * saved gid is explicit. 108856115Speter */ 108956115Speter 109056115Speter#ifndef _SYS_SYSPROTO_H_ 109156115Speterstruct setresgid_args { 109256115Speter gid_t rgid; 109356115Speter gid_t egid; 109456115Speter gid_t sgid; 109556115Speter}; 109656115Speter#endif 109787466Srwatson/* 109882749Sdillon * MPSAFE 109982749Sdillon */ 110056115Speter/* ARGSUSED */ 110156115Speterint 110293580Sjhbsetresgid(register struct thread *td, struct setresgid_args *uap) 110356115Speter{ 110483366Sjulian struct proc *p = td->td_proc; 110577183Srwatson struct ucred *newcred, *oldcred; 110687218Srwatson gid_t egid, rgid, sgid; 110756115Speter int error; 110856115Speter 110987218Srwatson egid = uap->egid; 111056115Speter rgid = uap->rgid; 111156115Speter sgid = uap->sgid; 111294619Sjhb newcred = crget(); 111394619Sjhb PROC_LOCK(p); 111477183Srwatson oldcred = p->p_ucred; 1115145147Srwatson 1116145147Srwatson#ifdef MAC 1117145147Srwatson error = mac_check_proc_setresgid(p, oldcred, rgid, egid, sgid); 1118145147Srwatson if (error) 1119145147Srwatson goto fail; 1120145147Srwatson#endif 1121145147Srwatson 112277183Srwatson if (((rgid != (gid_t)-1 && rgid != oldcred->cr_rgid && 112377183Srwatson rgid != oldcred->cr_svgid && 112477183Srwatson rgid != oldcred->cr_groups[0]) || 112577183Srwatson (egid != (gid_t)-1 && egid != oldcred->cr_rgid && 112677183Srwatson egid != oldcred->cr_svgid && 112777183Srwatson egid != oldcred->cr_groups[0]) || 112877183Srwatson (sgid != (gid_t)-1 && sgid != oldcred->cr_rgid && 112977183Srwatson sgid != oldcred->cr_svgid && 113077183Srwatson sgid != oldcred->cr_groups[0])) && 1131145147Srwatson (error = suser_cred(oldcred, SUSER_ALLOWJAIL)) != 0) 1132145147Srwatson goto fail; 113394619Sjhb 113494619Sjhb crcopy(newcred, oldcred); 113577183Srwatson if (egid != (gid_t)-1 && oldcred->cr_groups[0] != egid) { 113677183Srwatson change_egid(newcred, egid); 113756115Speter setsugid(p); 113856115Speter } 113977183Srwatson if (rgid != (gid_t)-1 && oldcred->cr_rgid != rgid) { 114077183Srwatson change_rgid(newcred, rgid); 114156115Speter setsugid(p); 114256115Speter } 114377183Srwatson if (sgid != (gid_t)-1 && oldcred->cr_svgid != sgid) { 114477183Srwatson change_svgid(newcred, sgid); 114556115Speter setsugid(p); 114656115Speter } 114777183Srwatson p->p_ucred = newcred; 114894619Sjhb PROC_UNLOCK(p); 114977183Srwatson crfree(oldcred); 115094619Sjhb return (0); 1151145147Srwatson 1152145147Srwatsonfail: 1153145147Srwatson PROC_UNLOCK(p); 1154145147Srwatson crfree(newcred); 1155145147Srwatson return (error); 115656115Speter} 115756115Speter 115856115Speter#ifndef _SYS_SYSPROTO_H_ 115956115Speterstruct getresuid_args { 116056115Speter uid_t *ruid; 116156115Speter uid_t *euid; 116256115Speter uid_t *suid; 116356115Speter}; 116456115Speter#endif 116582749Sdillon/* 116682749Sdillon * MPSAFE 116782749Sdillon */ 116856115Speter/* ARGSUSED */ 116956115Speterint 117093580Sjhbgetresuid(register struct thread *td, struct getresuid_args *uap) 117156115Speter{ 117282749Sdillon struct ucred *cred; 117356115Speter int error1 = 0, error2 = 0, error3 = 0; 117456115Speter 117593264Sdillon cred = td->td_ucred; 117656115Speter if (uap->ruid) 117799009Salfred error1 = copyout(&cred->cr_ruid, 117899009Salfred uap->ruid, sizeof(cred->cr_ruid)); 117956115Speter if (uap->euid) 118099009Salfred error2 = copyout(&cred->cr_uid, 118199009Salfred uap->euid, sizeof(cred->cr_uid)); 118256115Speter if (uap->suid) 118399009Salfred error3 = copyout(&cred->cr_svuid, 118499009Salfred uap->suid, sizeof(cred->cr_svuid)); 118587218Srwatson return (error1 ? error1 : error2 ? error2 : error3); 118656115Speter} 118756115Speter 118856115Speter#ifndef _SYS_SYSPROTO_H_ 118956115Speterstruct getresgid_args { 119056115Speter gid_t *rgid; 119156115Speter gid_t *egid; 119256115Speter gid_t *sgid; 119356115Speter}; 119456115Speter#endif 119582749Sdillon/* 119682749Sdillon * MPSAFE 119782749Sdillon */ 119856115Speter/* ARGSUSED */ 119956115Speterint 120093580Sjhbgetresgid(register struct thread *td, struct getresgid_args *uap) 120156115Speter{ 120282749Sdillon struct ucred *cred; 120356115Speter int error1 = 0, error2 = 0, error3 = 0; 120456115Speter 120593264Sdillon cred = td->td_ucred; 120656115Speter if (uap->rgid) 120799009Salfred error1 = copyout(&cred->cr_rgid, 120899009Salfred uap->rgid, sizeof(cred->cr_rgid)); 120956115Speter if (uap->egid) 121099009Salfred error2 = copyout(&cred->cr_groups[0], 121199009Salfred uap->egid, sizeof(cred->cr_groups[0])); 121256115Speter if (uap->sgid) 121399009Salfred error3 = copyout(&cred->cr_svgid, 121499009Salfred uap->sgid, sizeof(cred->cr_svgid)); 121587218Srwatson return (error1 ? error1 : error2 ? error2 : error3); 121656115Speter} 121756115Speter 121856115Speter#ifndef _SYS_SYSPROTO_H_ 121924453Speterstruct issetugid_args { 122024453Speter int dummy; 122124453Speter}; 122224453Speter#endif 122387218Srwatson/* 1224116121Sjhb * MPSAFE 122587218Srwatson */ 122624453Speter/* ARGSUSED */ 122724453Speterint 122893580Sjhbissetugid(register struct thread *td, struct issetugid_args *uap) 122924453Speter{ 123083366Sjulian struct proc *p = td->td_proc; 123183366Sjulian 123224453Speter /* 123324453Speter * Note: OpenBSD sets a P_SUGIDEXEC flag set at execve() time, 123424453Speter * we use P_SUGID because we consider changing the owners as 123524453Speter * "tainting" as well. 123624453Speter * This is significant for procs that start as root and "become" 123724453Speter * a user without an exec - programs cannot know *everything* 123824453Speter * that libc *might* have put in their data segment. 123924453Speter */ 124091140Stanimura PROC_LOCK(p); 124183366Sjulian td->td_retval[0] = (p->p_flag & P_SUGID) ? 1 : 0; 124291140Stanimura PROC_UNLOCK(p); 124324453Speter return (0); 124424453Speter} 124524453Speter 124682749Sdillon/* 124782749Sdillon * MPSAFE 124882749Sdillon */ 124975426Srwatsonint 125093580Sjhb__setugid(struct thread *td, struct __setugid_args *uap) 125175426Srwatson{ 125282749Sdillon#ifdef REGRESSION 125394619Sjhb struct proc *p; 125475426Srwatson 125594619Sjhb p = td->td_proc; 125675426Srwatson switch (uap->flag) { 125775426Srwatson case 0: 125894619Sjhb PROC_LOCK(p); 125994619Sjhb p->p_flag &= ~P_SUGID; 126094619Sjhb PROC_UNLOCK(p); 126194619Sjhb return (0); 126275426Srwatson case 1: 126394619Sjhb PROC_LOCK(p); 126494619Sjhb p->p_flag |= P_SUGID; 126594619Sjhb PROC_UNLOCK(p); 126694619Sjhb return (0); 126775426Srwatson default: 126894619Sjhb return (EINVAL); 126975426Srwatson } 127075426Srwatson#else /* !REGRESSION */ 127187218Srwatson 127275426Srwatson return (ENOSYS); 127387218Srwatson#endif /* REGRESSION */ 127475426Srwatson} 127575426Srwatson 12761541Srgrimes/* 12771541Srgrimes * Check if gid is a member of the group set. 127893264Sdillon * 127993264Sdillon * MPSAFE (cred must be held) 12801541Srgrimes */ 12811549Srgrimesint 128293580Sjhbgroupmember(gid_t gid, struct ucred *cred) 12831541Srgrimes{ 12841541Srgrimes register gid_t *gp; 12851541Srgrimes gid_t *egp; 12861541Srgrimes 12871541Srgrimes egp = &(cred->cr_groups[cred->cr_ngroups]); 12881541Srgrimes for (gp = cred->cr_groups; gp < egp; gp++) 12891541Srgrimes if (*gp == gid) 12901541Srgrimes return (1); 12911541Srgrimes return (0); 12921541Srgrimes} 12931541Srgrimes 129482424Srwatson/* 129589414Sarr * `suser_enabled' (which can be set by the security.suser_enabled 129682466Srwatson * sysctl) determines whether the system 'super-user' policy is in effect. 129782466Srwatson * If it is nonzero, an effective uid of 0 connotes special privilege, 129882466Srwatson * overriding many mandatory and discretionary protections. If it is zero, 129982466Srwatson * uid 0 is offered no special privilege in the kernel security policy. 130082466Srwatson * Setting it to zero may seriously impact the functionality of many 130182466Srwatson * existing userland programs, and should not be done without careful 130282466Srwatson * consideration of the consequences. 130382424Srwatson */ 130482693Srwatsonint suser_enabled = 1; 130589414SarrSYSCTL_INT(_security_bsd, OID_AUTO, suser_enabled, CTLFLAG_RW, 130682693Srwatson &suser_enabled, 0, "processes with uid 0 have privilege"); 130789414SarrTUNABLE_INT("security.bsd.suser_enabled", &suser_enabled); 130861287Srwatson 13091541Srgrimes/* 131082466Srwatson * Test whether the specified credentials imply "super-user" privilege. 1311132255Scperciva * Return 0 or EPERM. 13121541Srgrimes */ 13131549Srgrimesint 131493593Sjhbsuser_cred(struct ucred *cred, int flag) 131546112Sphk{ 131687218Srwatson 131782693Srwatson if (!suser_enabled) 131861282Srwatson return (EPERM); 1319132255Scperciva if (((flag & SUSER_RUID) ? cred->cr_ruid : cred->cr_uid) != 0) 132046155Sphk return (EPERM); 1321132653Scperciva if (jailed(cred) && !(flag & SUSER_ALLOWJAIL)) 132246155Sphk return (EPERM); 132346155Sphk return (0); 13241541Srgrimes} 13251541Srgrimes 132683639Srwatson/* 132793593Sjhb * Shortcut to hide contents of struct td and struct proc from the 132893593Sjhb * caller, promoting binary compatibility. 132993593Sjhb */ 133093593Sjhbint 133193593Sjhbsuser(struct thread *td) 133293593Sjhb{ 133393593Sjhb 1334132548Srwatson#ifdef INVARIANTS 1335132548Srwatson if (td != curthread) { 1336132548Srwatson printf("suser: thread %p (%d %s) != curthread %p (%d %s)\n", 1337132548Srwatson td, td->td_proc->p_pid, td->td_proc->p_comm, 1338132548Srwatson curthread, curthread->td_proc->p_pid, 1339132548Srwatson curthread->td_proc->p_comm); 1340132548Srwatson#ifdef KDB 1341132548Srwatson kdb_backtrace(); 1342132548Srwatson#endif 1343132548Srwatson } 1344132548Srwatson#endif 134593593Sjhb return (suser_cred(td->td_ucred, 0)); 134693593Sjhb} 134793593Sjhb 134893593Sjhb/* 134987218Srwatson * Test the active securelevel against a given level. securelevel_gt() 135087218Srwatson * implements (securelevel > level). securelevel_ge() implements 135187218Srwatson * (securelevel >= level). Note that the logic is inverted -- these 135287218Srwatson * functions return EPERM on "success" and 0 on "failure". 135383639Srwatson * 135493264Sdillon * MPSAFE 135583639Srwatson */ 135683639Srwatsonint 135783639Srwatsonsecurelevel_gt(struct ucred *cr, int level) 135883639Srwatson{ 135987218Srwatson int active_securelevel; 136083639Srwatson 136187218Srwatson active_securelevel = securelevel; 136293732Sjhb KASSERT(cr != NULL, ("securelevel_gt: null cr")); 1363140678Srwatson if (cr->cr_prison != NULL) 136487218Srwatson active_securelevel = imax(cr->cr_prison->pr_securelevel, 136587218Srwatson active_securelevel); 136687218Srwatson return (active_securelevel > level ? EPERM : 0); 136783639Srwatson} 136883639Srwatson 136983639Srwatsonint 137083639Srwatsonsecurelevel_ge(struct ucred *cr, int level) 137183639Srwatson{ 137287218Srwatson int active_securelevel; 137383639Srwatson 137487218Srwatson active_securelevel = securelevel; 137593732Sjhb KASSERT(cr != NULL, ("securelevel_ge: null cr")); 1376140678Srwatson if (cr->cr_prison != NULL) 137787218Srwatson active_securelevel = imax(cr->cr_prison->pr_securelevel, 137887218Srwatson active_securelevel); 137987218Srwatson return (active_securelevel >= level ? EPERM : 0); 138083639Srwatson} 138183639Srwatson 138284736Srwatson/* 138387144Srwatson * 'see_other_uids' determines whether or not visibility of processes 138487218Srwatson * and sockets with credentials holding different real uids is possible 138587138Srwatson * using a variety of system MIBs. 138687218Srwatson * XXX: data declarations should be together near the beginning of the file. 138784736Srwatson */ 138887144Srwatsonstatic int see_other_uids = 1; 138989414SarrSYSCTL_INT(_security_bsd, OID_AUTO, see_other_uids, CTLFLAG_RW, 139087218Srwatson &see_other_uids, 0, 139184736Srwatson "Unprivileged processes may see subjects/objects with different real uid"); 139284736Srwatson 139382466Srwatson/*- 139492923Srwatson * Determine if u1 "can see" the subject specified by u2, according to the 139592923Srwatson * 'see_other_uids' policy. 139692923Srwatson * Returns: 0 for permitted, ESRCH otherwise 139792923Srwatson * Locks: none 139892923Srwatson * References: *u1 and *u2 must not change during the call 139992923Srwatson * u1 may equal u2, in which case only one reference is required 140092923Srwatson */ 140192923Srwatsonstatic int 140292923Srwatsoncr_seeotheruids(struct ucred *u1, struct ucred *u2) 140392923Srwatson{ 140492923Srwatson 140592923Srwatson if (!see_other_uids && u1->cr_ruid != u2->cr_ruid) { 1406132653Scperciva if (suser_cred(u1, SUSER_ALLOWJAIL) != 0) 140792923Srwatson return (ESRCH); 140892923Srwatson } 140992923Srwatson return (0); 141092923Srwatson} 141192923Srwatson 1412122869Srwatson/* 1413122869Srwatson * 'see_other_gids' determines whether or not visibility of processes 1414122869Srwatson * and sockets with credentials holding different real gids is possible 1415122869Srwatson * using a variety of system MIBs. 1416122869Srwatson * XXX: data declarations should be together near the beginning of the file. 1417122869Srwatson */ 1418122869Srwatsonstatic int see_other_gids = 1; 1419122869SrwatsonSYSCTL_INT(_security_bsd, OID_AUTO, see_other_gids, CTLFLAG_RW, 1420122869Srwatson &see_other_gids, 0, 1421122869Srwatson "Unprivileged processes may see subjects/objects with different real gid"); 1422122869Srwatson 1423122869Srwatson/* 1424122869Srwatson * Determine if u1 can "see" the subject specified by u2, according to the 1425122869Srwatson * 'see_other_gids' policy. 1426122869Srwatson * Returns: 0 for permitted, ESRCH otherwise 1427122869Srwatson * Locks: none 1428122869Srwatson * References: *u1 and *u2 must not change during the call 1429122869Srwatson * u1 may equal u2, in which case only one reference is required 1430122869Srwatson */ 1431122869Srwatsonstatic int 1432122869Srwatsoncr_seeothergids(struct ucred *u1, struct ucred *u2) 1433122869Srwatson{ 1434122869Srwatson int i, match; 1435122869Srwatson 1436122869Srwatson if (!see_other_gids) { 1437122869Srwatson match = 0; 1438122869Srwatson for (i = 0; i < u1->cr_ngroups; i++) { 1439122869Srwatson if (groupmember(u1->cr_groups[i], u2)) 1440122869Srwatson match = 1; 1441122869Srwatson if (match) 1442122869Srwatson break; 1443122869Srwatson } 1444122869Srwatson if (!match) { 1445132653Scperciva if (suser_cred(u1, SUSER_ALLOWJAIL) != 0) 1446122869Srwatson return (ESRCH); 1447122869Srwatson } 1448122869Srwatson } 1449122869Srwatson return (0); 1450122869Srwatson} 1451122869Srwatson 145292923Srwatson/*- 145382466Srwatson * Determine if u1 "can see" the subject specified by u2. 145474956Srwatson * Returns: 0 for permitted, an errno value otherwise 145574956Srwatson * Locks: none 145687218Srwatson * References: *u1 and *u2 must not change during the call 145774956Srwatson * u1 may equal u2, in which case only one reference is required 145874956Srwatson */ 145974956Srwatsonint 146083742Srwatsoncr_cansee(struct ucred *u1, struct ucred *u2) 146165237Srwatson{ 146272786Srwatson int error; 146353518Sphk 146474956Srwatson if ((error = prison_check(u1, u2))) 146572786Srwatson return (error); 1466101003Srwatson#ifdef MAC 1467101003Srwatson if ((error = mac_check_cred_visible(u1, u2))) 1468101003Srwatson return (error); 1469101003Srwatson#endif 147092923Srwatson if ((error = cr_seeotheruids(u1, u2))) 147192923Srwatson return (error); 1472122869Srwatson if ((error = cr_seeothergids(u1, u2))) 1473122869Srwatson return (error); 147465237Srwatson return (0); 147565237Srwatson} 147665237Srwatson 147782466Srwatson/*- 147896886Sjhb * Determine if td "can see" the subject specified by p. 147982424Srwatson * Returns: 0 for permitted, an errno value otherwise 148096886Sjhb * Locks: Sufficient locks to protect p->p_ucred must be held. td really 148196886Sjhb * should be curthread. 148296886Sjhb * References: td and p must be valid for the lifetime of the call 148382424Srwatson */ 148479335Srwatsonint 148596886Sjhbp_cansee(struct thread *td, struct proc *p) 148674956Srwatson{ 148774956Srwatson 148883742Srwatson /* Wrap cr_cansee() for all functionality. */ 148996886Sjhb KASSERT(td == curthread, ("%s: td not curthread", __func__)); 149096886Sjhb PROC_LOCK_ASSERT(p, MA_OWNED); 149196886Sjhb return (cr_cansee(td->td_ucred, p->p_ucred)); 149274956Srwatson} 149374956Srwatson 1494120052Srwatson/* 1495120052Srwatson * 'conservative_signals' prevents the delivery of a broad class of 1496120052Srwatson * signals by unprivileged processes to processes that have changed their 1497120052Srwatson * credentials since the last invocation of execve(). This can prevent 1498120052Srwatson * the leakage of cached information or retained privileges as a result 1499120052Srwatson * of a common class of signal-related vulnerabilities. However, this 1500120052Srwatson * may interfere with some applications that expect to be able to 1501120052Srwatson * deliver these signals to peer processes after having given up 1502120052Srwatson * privilege. 1503120052Srwatson */ 1504120052Srwatsonstatic int conservative_signals = 1; 1505120052SrwatsonSYSCTL_INT(_security_bsd, OID_AUTO, conservative_signals, CTLFLAG_RW, 1506120052Srwatson &conservative_signals, 0, "Unprivileged processes prevented from " 1507120052Srwatson "sending certain signals to processes whose credentials have changed"); 150882466Srwatson/*- 150988943Srwatson * Determine whether cred may deliver the specified signal to proc. 151088943Srwatson * Returns: 0 for permitted, an errno value otherwise. 151188943Srwatson * Locks: A lock must be held for proc. 151288943Srwatson * References: cred and proc must be valid for the lifetime of the call. 151375437Srwatson */ 151475437Srwatsonint 1515141815Ssobomaxcr_cansignal(struct ucred *cred, struct proc *proc, int signum) 151653518Sphk{ 151782466Srwatson int error; 151884826Sjhb 151996886Sjhb PROC_LOCK_ASSERT(proc, MA_OWNED); 152075437Srwatson /* 152188943Srwatson * Jail semantics limit the scope of signalling to proc in the 152288943Srwatson * same jail as cred, if cred is in jail. 152375437Srwatson */ 152488943Srwatson error = prison_check(cred, proc->p_ucred); 152588943Srwatson if (error) 152672786Srwatson return (error); 1527101003Srwatson#ifdef MAC 1528101003Srwatson if ((error = mac_check_proc_signal(cred, proc, signum))) 1529101003Srwatson return (error); 1530101003Srwatson#endif 1531122869Srwatson if ((error = cr_seeotheruids(cred, proc->p_ucred))) 153292923Srwatson return (error); 1533122869Srwatson if ((error = cr_seeothergids(cred, proc->p_ucred))) 1534122869Srwatson return (error); 153565237Srwatson 153665237Srwatson /* 153782424Srwatson * UNIX signal semantics depend on the status of the P_SUGID 153882424Srwatson * bit on the target process. If the bit is set, then additional 153982424Srwatson * restrictions are placed on the set of available signals. 154075437Srwatson */ 1541141815Ssobomax if (conservative_signals && (proc->p_flag & P_SUGID)) { 154275437Srwatson switch (signum) { 154375437Srwatson case 0: 154475437Srwatson case SIGKILL: 154575437Srwatson case SIGINT: 154675437Srwatson case SIGTERM: 1547120052Srwatson case SIGALRM: 154875437Srwatson case SIGSTOP: 154975437Srwatson case SIGTTIN: 155075437Srwatson case SIGTTOU: 155175437Srwatson case SIGTSTP: 155275437Srwatson case SIGHUP: 155375437Srwatson case SIGUSR1: 155475437Srwatson case SIGUSR2: 155582466Srwatson /* 155682466Srwatson * Generally, permit job and terminal control 155782466Srwatson * signals. 155882466Srwatson */ 155975437Srwatson break; 156075437Srwatson default: 156188943Srwatson /* Not permitted without privilege. */ 1562132653Scperciva error = suser_cred(cred, SUSER_ALLOWJAIL); 156375437Srwatson if (error) 156475437Srwatson return (error); 156575437Srwatson } 156665237Srwatson } 156765237Srwatson 156875480Srwatson /* 156982424Srwatson * Generally, the target credential's ruid or svuid must match the 157075480Srwatson * subject credential's ruid or euid. 157175480Srwatson */ 157288943Srwatson if (cred->cr_ruid != proc->p_ucred->cr_ruid && 157388943Srwatson cred->cr_ruid != proc->p_ucred->cr_svuid && 157488943Srwatson cred->cr_uid != proc->p_ucred->cr_ruid && 157588943Srwatson cred->cr_uid != proc->p_ucred->cr_svuid) { 157688943Srwatson /* Not permitted without privilege. */ 1577132653Scperciva error = suser_cred(cred, SUSER_ALLOWJAIL); 157875480Srwatson if (error) 157975480Srwatson return (error); 158075480Srwatson } 158175480Srwatson 158287218Srwatson return (0); 158353518Sphk} 158453518Sphk 158588943Srwatson 158682466Srwatson/*- 158796886Sjhb * Determine whether td may deliver the specified signal to p. 158888943Srwatson * Returns: 0 for permitted, an errno value otherwise 158996886Sjhb * Locks: Sufficient locks to protect various components of td and p 159096886Sjhb * must be held. td must be curthread, and a lock must be 159196886Sjhb * held for p. 159296886Sjhb * References: td and p must be valid for the lifetime of the call 159388943Srwatson */ 159488943Srwatsonint 1595141815Ssobomaxp_cansignal(struct thread *td, struct proc *p, int signum) 159688943Srwatson{ 159788943Srwatson 159896886Sjhb KASSERT(td == curthread, ("%s: td not curthread", __func__)); 159996886Sjhb PROC_LOCK_ASSERT(p, MA_OWNED); 160096886Sjhb if (td->td_proc == p) 160188943Srwatson return (0); 160288943Srwatson 160388943Srwatson /* 160488943Srwatson * UNIX signalling semantics require that processes in the same 160588943Srwatson * session always be able to deliver SIGCONT to one another, 160688943Srwatson * overriding the remaining protections. 160788943Srwatson */ 160896886Sjhb /* XXX: This will require an additional lock of some sort. */ 160996886Sjhb if (signum == SIGCONT && td->td_proc->p_session == p->p_session) 161088943Srwatson return (0); 1611143108Ssobomax /* 1612143800Ssobomax * Some compat layers use SIGTHR and higher signals for 1613143800Ssobomax * communication between different kernel threads of the same 1614143800Ssobomax * process, so that they expect that it's always possible to 1615143800Ssobomax * deliver them, even for suid applications where cr_cansignal() can 1616143108Ssobomax * deny such ability for security consideration. It should be 1617143108Ssobomax * pretty safe to do since the only way to create two processes 1618143108Ssobomax * with the same p_leader is via rfork(2). 1619143108Ssobomax */ 1620143805Ssobomax if (td->td_proc->p_leader != NULL && signum >= SIGTHR && 1621143805Ssobomax signum < SIGTHR + 4 && td->td_proc->p_leader == p->p_leader) 1622143108Ssobomax return (0); 162388943Srwatson 1624141815Ssobomax return (cr_cansignal(td->td_ucred, p, signum)); 162588943Srwatson} 162688943Srwatson 162788943Srwatson/*- 162896886Sjhb * Determine whether td may reschedule p. 162982466Srwatson * Returns: 0 for permitted, an errno value otherwise 163096886Sjhb * Locks: Sufficient locks to protect various components of td and p 163196886Sjhb * must be held. td must be curthread, and a lock must 163296886Sjhb * be held for p. 163396886Sjhb * References: td and p must be valid for the lifetime of the call 163482424Srwatson */ 163579335Srwatsonint 163696886Sjhbp_cansched(struct thread *td, struct proc *p) 163765237Srwatson{ 163872786Srwatson int error; 163965237Srwatson 164096886Sjhb KASSERT(td == curthread, ("%s: td not curthread", __func__)); 164196886Sjhb PROC_LOCK_ASSERT(p, MA_OWNED); 164296886Sjhb if (td->td_proc == p) 164365237Srwatson return (0); 164496886Sjhb if ((error = prison_check(td->td_ucred, p->p_ucred))) 164572786Srwatson return (error); 1646101003Srwatson#ifdef MAC 1647101003Srwatson if ((error = mac_check_proc_sched(td->td_ucred, p))) 1648101003Srwatson return (error); 1649101003Srwatson#endif 165096886Sjhb if ((error = cr_seeotheruids(td->td_ucred, p->p_ucred))) 165192923Srwatson return (error); 1652122869Srwatson if ((error = cr_seeothergids(td->td_ucred, p->p_ucred))) 1653122869Srwatson return (error); 165496886Sjhb if (td->td_ucred->cr_ruid == p->p_ucred->cr_ruid) 165565237Srwatson return (0); 165696886Sjhb if (td->td_ucred->cr_uid == p->p_ucred->cr_ruid) 165765237Srwatson return (0); 1658132653Scperciva if (suser_cred(td->td_ucred, SUSER_ALLOWJAIL) == 0) 165965237Srwatson return (0); 166065237Srwatson 166165237Srwatson#ifdef CAPABILITIES 1662132653Scperciva if (!cap_check(NULL, td, CAP_SYS_NICE, SUSER_ALLOWJAIL)) 166365237Srwatson return (0); 166465237Srwatson#endif 166565237Srwatson 166665237Srwatson return (EPERM); 166765237Srwatson} 166865237Srwatson 166982424Srwatson/* 167087280Srwatson * The 'unprivileged_proc_debug' flag may be used to disable a variety of 167187280Srwatson * unprivileged inter-process debugging services, including some procfs 167287280Srwatson * functionality, ptrace(), and ktrace(). In the past, inter-process 167387280Srwatson * debugging has been involved in a variety of security problems, and sites 167487280Srwatson * not requiring the service might choose to disable it when hardening 167587280Srwatson * systems. 167682424Srwatson * 167782424Srwatson * XXX: Should modifying and reading this variable require locking? 167887218Srwatson * XXX: data declarations should be together near the beginning of the file. 167982424Srwatson */ 168087144Srwatsonstatic int unprivileged_proc_debug = 1; 168189414SarrSYSCTL_INT(_security_bsd, OID_AUTO, unprivileged_proc_debug, CTLFLAG_RW, 168287218Srwatson &unprivileged_proc_debug, 0, 168380735Srwatson "Unprivileged processes may use process debugging facilities"); 168480735Srwatson 168582466Srwatson/*- 168696886Sjhb * Determine whether td may debug p. 168782466Srwatson * Returns: 0 for permitted, an errno value otherwise 168896886Sjhb * Locks: Sufficient locks to protect various components of td and p 168996886Sjhb * must be held. td must be curthread, and a lock must 169096886Sjhb * be held for p. 169196886Sjhb * References: td and p must be valid for the lifetime of the call 169282424Srwatson */ 169379335Srwatsonint 169496886Sjhbp_candebug(struct thread *td, struct proc *p) 169565237Srwatson{ 169687218Srwatson int credentialchanged, error, grpsubset, i, uidsubset; 169765237Srwatson 169896886Sjhb KASSERT(td == curthread, ("%s: td not curthread", __func__)); 169996886Sjhb PROC_LOCK_ASSERT(p, MA_OWNED); 170087144Srwatson if (!unprivileged_proc_debug) { 1701132653Scperciva error = suser_cred(td->td_ucred, SUSER_ALLOWJAIL); 170284727Srwatson if (error) 170384727Srwatson return (error); 170484727Srwatson } 170596886Sjhb if (td->td_proc == p) 170684636Sdes return (0); 170796886Sjhb if ((error = prison_check(td->td_ucred, p->p_ucred))) 170872786Srwatson return (error); 1709101003Srwatson#ifdef MAC 1710101003Srwatson if ((error = mac_check_proc_debug(td->td_ucred, p))) 1711101003Srwatson return (error); 1712101003Srwatson#endif 171396886Sjhb if ((error = cr_seeotheruids(td->td_ucred, p->p_ucred))) 171492923Srwatson return (error); 1715122869Srwatson if ((error = cr_seeothergids(td->td_ucred, p->p_ucred))) 1716122869Srwatson return (error); 171765237Srwatson 171882466Srwatson /* 171996886Sjhb * Is p's group set a subset of td's effective group set? This 172096886Sjhb * includes p's egid, group access list, rgid, and svgid. 172182466Srwatson */ 172285895Srwatson grpsubset = 1; 172396886Sjhb for (i = 0; i < p->p_ucred->cr_ngroups; i++) { 172496886Sjhb if (!groupmember(p->p_ucred->cr_groups[i], td->td_ucred)) { 172585895Srwatson grpsubset = 0; 172685895Srwatson break; 172785895Srwatson } 172885895Srwatson } 172985895Srwatson grpsubset = grpsubset && 173096886Sjhb groupmember(p->p_ucred->cr_rgid, td->td_ucred) && 173196886Sjhb groupmember(p->p_ucred->cr_svgid, td->td_ucred); 173285895Srwatson 173385895Srwatson /* 173496886Sjhb * Are the uids present in p's credential equal to td's 173596886Sjhb * effective uid? This includes p's euid, svuid, and ruid. 173685895Srwatson */ 173796886Sjhb uidsubset = (td->td_ucred->cr_uid == p->p_ucred->cr_uid && 173896886Sjhb td->td_ucred->cr_uid == p->p_ucred->cr_svuid && 173996886Sjhb td->td_ucred->cr_uid == p->p_ucred->cr_ruid); 174085895Srwatson 174185895Srwatson /* 174285895Srwatson * Has the credential of the process changed since the last exec()? 174385895Srwatson */ 174496886Sjhb credentialchanged = (p->p_flag & P_SUGID); 174585895Srwatson 174685895Srwatson /* 174796886Sjhb * If p's gids aren't a subset, or the uids aren't a subset, 174885895Srwatson * or the credential has changed, require appropriate privilege 174996886Sjhb * for td to debug p. For POSIX.1e capabilities, this will 175085895Srwatson * require CAP_SYS_PTRACE. 175185895Srwatson */ 175285895Srwatson if (!grpsubset || !uidsubset || credentialchanged) { 1753132653Scperciva error = suser_cred(td->td_ucred, SUSER_ALLOWJAIL); 175484727Srwatson if (error) 175565237Srwatson return (error); 175682466Srwatson } 175765237Srwatson 175887218Srwatson /* Can't trace init when securelevel > 0. */ 175996886Sjhb if (p == initproc) { 176096886Sjhb error = securelevel_gt(td->td_ucred, 0); 176183639Srwatson if (error) 176283639Srwatson return (error); 176383639Srwatson } 176465237Srwatson 176585880Srwatson /* 176685880Srwatson * Can't trace a process that's currently exec'ing. 176785880Srwatson * XXX: Note, this is not a security policy decision, it's a 176885880Srwatson * basic correctness/functionality decision. Therefore, this check 176985880Srwatson * should be moved to the caller's of p_candebug(). 177085880Srwatson */ 177196886Sjhb if ((p->p_flag & P_INEXEC) != 0) 177285598Sdes return (EAGAIN); 177387466Srwatson 177465237Srwatson return (0); 177565237Srwatson} 177665237Srwatson 177792976Srwatson/*- 177892976Srwatson * Determine whether the subject represented by cred can "see" a socket. 177992976Srwatson * Returns: 0 for permitted, ENOENT otherwise. 178092976Srwatson */ 178192976Srwatsonint 178292976Srwatsoncr_canseesocket(struct ucred *cred, struct socket *so) 178392976Srwatson{ 178492976Srwatson int error; 178592976Srwatson 178692976Srwatson error = prison_check(cred, so->so_cred); 178792976Srwatson if (error) 178892976Srwatson return (ENOENT); 1789101003Srwatson#ifdef MAC 1790130398Srwatson SOCK_LOCK(so); 1791101003Srwatson error = mac_check_socket_visible(cred, so); 1792130398Srwatson SOCK_UNLOCK(so); 1793101003Srwatson if (error) 1794101003Srwatson return (error); 1795101003Srwatson#endif 179692976Srwatson if (cr_seeotheruids(cred, so->so_cred)) 179792976Srwatson return (ENOENT); 1798122869Srwatson if (cr_seeothergids(cred, so->so_cred)) 1799122869Srwatson return (ENOENT); 180092976Srwatson 180192976Srwatson return (0); 180292976Srwatson} 180392976Srwatson 1804145234Srwatson/*- 1805145234Srwatson * Determine whether td can wait for the exit of p. 1806145234Srwatson * Returns: 0 for permitted, an errno value otherwise 1807145234Srwatson * Locks: Sufficient locks to protect various components of td and p 1808145234Srwatson * must be held. td must be curthread, and a lock must 1809145234Srwatson * be held for p. 1810145234Srwatson * References: td and p must be valid for the lifetime of the call 1811145234Srwatson 1812145234Srwatson */ 1813145234Srwatsonint 1814145234Srwatsonp_canwait(struct thread *td, struct proc *p) 1815145234Srwatson{ 1816145234Srwatson int error; 1817145234Srwatson 1818145234Srwatson KASSERT(td == curthread, ("%s: td not curthread", __func__)); 1819145234Srwatson PROC_LOCK_ASSERT(p, MA_OWNED); 1820145234Srwatson if ((error = prison_check(td->td_ucred, p->p_ucred))) 1821145234Srwatson return (error); 1822145234Srwatson#ifdef MAC 1823145234Srwatson if ((error = mac_check_proc_wait(td->td_ucred, p))) 1824145234Srwatson return (error); 1825145234Srwatson#endif 1826145234Srwatson#if 0 1827145234Srwatson /* XXXMAC: This could have odd effects on some shells. */ 1828145234Srwatson if ((error = cr_seeotheruids(td->td_ucred, p->p_ucred))) 1829145234Srwatson return (error); 1830145234Srwatson#endif 1831145234Srwatson 1832145234Srwatson return (0); 1833145234Srwatson} 1834145234Srwatson 183553518Sphk/* 18361541Srgrimes * Allocate a zeroed cred structure. 1837116406Srwatson * MPSAFE 18381541Srgrimes */ 18391541Srgrimesstruct ucred * 184093580Sjhbcrget(void) 18411541Srgrimes{ 18421541Srgrimes register struct ucred *cr; 18431541Srgrimes 1844111119Simp MALLOC(cr, struct ucred *, sizeof(*cr), M_CRED, M_WAITOK | M_ZERO); 1845150634Sjhb refcount_init(&cr->cr_ref, 1); 1846101001Srwatson#ifdef MAC 1847101001Srwatson mac_init_cred(cr); 1848101001Srwatson#endif 18491541Srgrimes return (cr); 18501541Srgrimes} 18511541Srgrimes 18521541Srgrimes/* 185382466Srwatson * Claim another reference to a ucred structure. 1854116406Srwatson * MPSAFE 185569401Salfred */ 185684827Sjhbstruct ucred * 185793580Sjhbcrhold(struct ucred *cr) 185869401Salfred{ 185969401Salfred 1860150634Sjhb refcount_acquire(&cr->cr_ref); 186184827Sjhb return (cr); 186269401Salfred} 186369401Salfred 186469401Salfred/* 18651541Srgrimes * Free a cred structure. 18661541Srgrimes * Throws away space when ref count gets to 0. 1867116406Srwatson * MPSAFE 18681541Srgrimes */ 18691549Srgrimesvoid 187093580Sjhbcrfree(struct ucred *cr) 18711541Srgrimes{ 187269239Salfred 187375632Salfred KASSERT(cr->cr_ref > 0, ("bad ucred refcount: %d", cr->cr_ref)); 1874150634Sjhb KASSERT(cr->cr_ref != 0xdeadc0de, ("dangling reference to ucred")); 1875150634Sjhb if (refcount_release(&cr->cr_ref)) { 187665495Struckman /* 187765495Struckman * Some callers of crget(), such as nfs_statfs(), 187865495Struckman * allocate a temporary credential, but don't 187965495Struckman * allocate a uidinfo structure. 188065495Struckman */ 188165495Struckman if (cr->cr_uidinfo != NULL) 188265495Struckman uifree(cr->cr_uidinfo); 188377277Srwatson if (cr->cr_ruidinfo != NULL) 188477277Srwatson uifree(cr->cr_ruidinfo); 188572786Srwatson /* 188672786Srwatson * Free a prison, if any. 188772786Srwatson */ 188872786Srwatson if (jailed(cr)) 188972786Srwatson prison_free(cr->cr_prison); 1890101001Srwatson#ifdef MAC 1891101001Srwatson mac_destroy_cred(cr); 1892101001Srwatson#endif 189399009Salfred FREE(cr, M_CRED); 189490756Sdillon } 18951541Srgrimes} 18961541Srgrimes 18971541Srgrimes/* 189884827Sjhb * Check to see if this ucred is shared. 1899116406Srwatson * MPSAFE 19001541Srgrimes */ 190184827Sjhbint 190293580Sjhbcrshared(struct ucred *cr) 19031541Srgrimes{ 19041541Srgrimes 1905150634Sjhb return (cr->cr_ref > 1); 19061541Srgrimes} 19071541Srgrimes 19081541Srgrimes/* 190984827Sjhb * Copy a ucred's contents from a template. Does not block. 1910116406Srwatson * MPSAFE 191184827Sjhb */ 191284827Sjhbvoid 191393580Sjhbcrcopy(struct ucred *dest, struct ucred *src) 191484827Sjhb{ 191584827Sjhb 191684827Sjhb KASSERT(crshared(dest) == 0, ("crcopy of shared ucred")); 191784827Sjhb bcopy(&src->cr_startcopy, &dest->cr_startcopy, 191887218Srwatson (unsigned)((caddr_t)&src->cr_endcopy - 191984827Sjhb (caddr_t)&src->cr_startcopy)); 192084827Sjhb uihold(dest->cr_uidinfo); 192184827Sjhb uihold(dest->cr_ruidinfo); 192284827Sjhb if (jailed(dest)) 192384827Sjhb prison_hold(dest->cr_prison); 1924101001Srwatson#ifdef MAC 1925123173Srwatson mac_copy_cred(src, dest); 1926101001Srwatson#endif 192784827Sjhb} 192884827Sjhb 192984827Sjhb/* 19301541Srgrimes * Dup cred struct to a new held one. 1931116406Srwatson * MPSAFE 19321541Srgrimes */ 19331541Srgrimesstruct ucred * 193493580Sjhbcrdup(struct ucred *cr) 19351541Srgrimes{ 19361541Srgrimes struct ucred *newcr; 19371541Srgrimes 193884827Sjhb newcr = crget(); 193984827Sjhb crcopy(newcr, cr); 19401541Srgrimes return (newcr); 19411541Srgrimes} 19421541Srgrimes 19431541Srgrimes/* 194491354Sdd * Fill in a struct xucred based on a struct ucred. 1945116406Srwatson * MPSAFE 194691354Sdd */ 194791354Sddvoid 194893580Sjhbcru2x(struct ucred *cr, struct xucred *xcr) 194991354Sdd{ 195091354Sdd 195191354Sdd bzero(xcr, sizeof(*xcr)); 195291354Sdd xcr->cr_version = XUCRED_VERSION; 195391354Sdd xcr->cr_uid = cr->cr_uid; 195491354Sdd xcr->cr_ngroups = cr->cr_ngroups; 195591354Sdd bcopy(cr->cr_groups, xcr->cr_groups, sizeof(cr->cr_groups)); 195691354Sdd} 195791354Sdd 195891354Sdd/* 195990748Sjulian * small routine to swap a thread's current ucred for the correct one 196090748Sjulian * taken from the process. 1961116406Srwatson * MPSAFE 196290748Sjulian */ 196390748Sjulianvoid 196490748Sjuliancred_update_thread(struct thread *td) 196590748Sjulian{ 196690748Sjulian struct proc *p; 196791405Sjhb struct ucred *cred; 196890748Sjulian 196990748Sjulian p = td->td_proc; 197091405Sjhb cred = td->td_ucred; 197190748Sjulian PROC_LOCK(p); 197290748Sjulian td->td_ucred = crhold(p->p_ucred); 197390748Sjulian PROC_UNLOCK(p); 197491405Sjhb if (cred != NULL) 197591405Sjhb crfree(cred); 197690748Sjulian} 197790748Sjulian 197890748Sjulian/* 19791541Srgrimes * Get login name, if available. 19801541Srgrimes */ 198112221Sbde#ifndef _SYS_SYSPROTO_H_ 19821541Srgrimesstruct getlogin_args { 19831541Srgrimes char *namebuf; 19841541Srgrimes u_int namelen; 19851541Srgrimes}; 198612221Sbde#endif 198782749Sdillon/* 198882749Sdillon * MPSAFE 198982749Sdillon */ 19901541Srgrimes/* ARGSUSED */ 19911549Srgrimesint 199293580Sjhbgetlogin(struct thread *td, struct getlogin_args *uap) 19931541Srgrimes{ 199482749Sdillon int error; 199591140Stanimura char login[MAXLOGNAME]; 199683366Sjulian struct proc *p = td->td_proc; 19971541Srgrimes 199823358Sache if (uap->namelen > MAXLOGNAME) 199923359Sache uap->namelen = MAXLOGNAME; 200091140Stanimura PROC_LOCK(p); 200191140Stanimura SESS_LOCK(p->p_session); 200291140Stanimura bcopy(p->p_session->s_login, login, uap->namelen); 200391140Stanimura SESS_UNLOCK(p->p_session); 200491140Stanimura PROC_UNLOCK(p); 200599009Salfred error = copyout(login, uap->namebuf, uap->namelen); 200682749Sdillon return(error); 20071541Srgrimes} 20081541Srgrimes 20091541Srgrimes/* 20101541Srgrimes * Set login name. 20111541Srgrimes */ 201212221Sbde#ifndef _SYS_SYSPROTO_H_ 20131541Srgrimesstruct setlogin_args { 20141541Srgrimes char *namebuf; 20151541Srgrimes}; 201612221Sbde#endif 201782749Sdillon/* 201882749Sdillon * MPSAFE 201982749Sdillon */ 20201541Srgrimes/* ARGSUSED */ 20211549Srgrimesint 202293580Sjhbsetlogin(struct thread *td, struct setlogin_args *uap) 20231541Srgrimes{ 202483366Sjulian struct proc *p = td->td_proc; 20251541Srgrimes int error; 202623330Sache char logintmp[MAXLOGNAME]; 20271541Srgrimes 2028132653Scperciva error = suser_cred(td->td_ucred, SUSER_ALLOWJAIL); 202994619Sjhb if (error) 203094619Sjhb return (error); 203199009Salfred error = copyinstr(uap->namebuf, logintmp, sizeof(logintmp), NULL); 203287218Srwatson if (error == ENAMETOOLONG) 20331541Srgrimes error = EINVAL; 203491140Stanimura else if (!error) { 203591140Stanimura PROC_LOCK(p); 203691140Stanimura SESS_LOCK(p->p_session); 203791140Stanimura (void) memcpy(p->p_session->s_login, logintmp, 203823330Sache sizeof(logintmp)); 203991140Stanimura SESS_UNLOCK(p->p_session); 204091140Stanimura PROC_UNLOCK(p); 204191140Stanimura } 20421541Srgrimes return (error); 20431541Srgrimes} 204431891Ssef 204531891Ssefvoid 204693580Sjhbsetsugid(struct proc *p) 204731891Ssef{ 204898403Salfred 204998403Salfred PROC_LOCK_ASSERT(p, MA_OWNED); 205031891Ssef p->p_flag |= P_SUGID; 205155707Ssef if (!(p->p_pfsflags & PF_ISUGID)) 205231891Ssef p->p_stops = 0; 205331891Ssef} 205465495Struckman 205582466Srwatson/*- 205682466Srwatson * Change a process's effective uid. 205777183Srwatson * Side effects: newcred->cr_uid and newcred->cr_uidinfo will be modified. 205877183Srwatson * References: newcred must be an exclusive credential reference for the 205977183Srwatson * duration of the call. 206065495Struckman */ 206165495Struckmanvoid 206298417Salfredchange_euid(struct ucred *newcred, struct uidinfo *euip) 206365495Struckman{ 206465495Struckman 206598417Salfred newcred->cr_uid = euip->ui_uid; 206698417Salfred uihold(euip); 206777183Srwatson uifree(newcred->cr_uidinfo); 206898417Salfred newcred->cr_uidinfo = euip; 206965495Struckman} 207065495Struckman 207182466Srwatson/*- 207282466Srwatson * Change a process's effective gid. 207377183Srwatson * Side effects: newcred->cr_gid will be modified. 207477183Srwatson * References: newcred must be an exclusive credential reference for the 207577183Srwatson * duration of the call. 207665495Struckman */ 207767629Sgallatinvoid 207893580Sjhbchange_egid(struct ucred *newcred, gid_t egid) 207965495Struckman{ 208065495Struckman 208177183Srwatson newcred->cr_groups[0] = egid; 208265495Struckman} 208377183Srwatson 208482466Srwatson/*- 208582466Srwatson * Change a process's real uid. 208677183Srwatson * Side effects: newcred->cr_ruid will be updated, newcred->cr_ruidinfo 208777183Srwatson * will be updated, and the old and new cr_ruidinfo proc 208877183Srwatson * counts will be updated. 208977183Srwatson * References: newcred must be an exclusive credential reference for the 209077183Srwatson * duration of the call. 209177183Srwatson */ 209277183Srwatsonvoid 209398417Salfredchange_ruid(struct ucred *newcred, struct uidinfo *ruip) 209477183Srwatson{ 209577183Srwatson 209677183Srwatson (void)chgproccnt(newcred->cr_ruidinfo, -1, 0); 209798417Salfred newcred->cr_ruid = ruip->ui_uid; 209898417Salfred uihold(ruip); 209977183Srwatson uifree(newcred->cr_ruidinfo); 210098417Salfred newcred->cr_ruidinfo = ruip; 210177183Srwatson (void)chgproccnt(newcred->cr_ruidinfo, 1, 0); 210277183Srwatson} 210377183Srwatson 210482466Srwatson/*- 210582466Srwatson * Change a process's real gid. 210677183Srwatson * Side effects: newcred->cr_rgid will be updated. 210777183Srwatson * References: newcred must be an exclusive credential reference for the 210877183Srwatson * duration of the call. 210977183Srwatson */ 211077183Srwatsonvoid 211193580Sjhbchange_rgid(struct ucred *newcred, gid_t rgid) 211277183Srwatson{ 211377183Srwatson 211477183Srwatson newcred->cr_rgid = rgid; 211577183Srwatson} 211677183Srwatson 211782466Srwatson/*- 211882466Srwatson * Change a process's saved uid. 211977183Srwatson * Side effects: newcred->cr_svuid will be updated. 212077183Srwatson * References: newcred must be an exclusive credential reference for the 212177183Srwatson * duration of the call. 212277183Srwatson */ 212377183Srwatsonvoid 212493580Sjhbchange_svuid(struct ucred *newcred, uid_t svuid) 212577183Srwatson{ 212677183Srwatson 212777183Srwatson newcred->cr_svuid = svuid; 212877183Srwatson} 212977183Srwatson 213082466Srwatson/*- 213182466Srwatson * Change a process's saved gid. 213277183Srwatson * Side effects: newcred->cr_svgid will be updated. 213377183Srwatson * References: newcred must be an exclusive credential reference for the 213477183Srwatson * duration of the call. 213577183Srwatson */ 213677183Srwatsonvoid 213793580Sjhbchange_svgid(struct ucred *newcred, gid_t svgid) 213877183Srwatson{ 213977183Srwatson 214077183Srwatson newcred->cr_svgid = svgid; 214177183Srwatson} 2142