kern_prot.c revision 225617
1139804Simp/*- 21541Srgrimes * Copyright (c) 1982, 1986, 1989, 1990, 1991, 1993 3165897Srwatson * The Regents of the University of California. 41541Srgrimes * (c) UNIX System Laboratories, Inc. 5165897Srwatson * Copyright (c) 2000-2001 Robert N. M. Watson. 6165897Srwatson * All rights reserved. 7165897Srwatson * 81541Srgrimes * All or some portions of this file are derived from material licensed 91541Srgrimes * to the University of California by American Telephone and Telegraph 101541Srgrimes * Co. or Unix System Laboratories, Inc. and are reproduced herein with 111541Srgrimes * the permission of UNIX System Laboratories, Inc. 121541Srgrimes * 131541Srgrimes * Redistribution and use in source and binary forms, with or without 141541Srgrimes * modification, are permitted provided that the following conditions 151541Srgrimes * are met: 161541Srgrimes * 1. Redistributions of source code must retain the above copyright 171541Srgrimes * notice, this list of conditions and the following disclaimer. 181541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 191541Srgrimes * notice, this list of conditions and the following disclaimer in the 201541Srgrimes * documentation and/or other materials provided with the distribution. 211541Srgrimes * 4. Neither the name of the University nor the names of its contributors 221541Srgrimes * may be used to endorse or promote products derived from this software 231541Srgrimes * without specific prior written permission. 241541Srgrimes * 251541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 261541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 271541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 281541Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 291541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 301541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 311541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 321541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 331541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 341541Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 351541Srgrimes * SUCH DAMAGE. 361541Srgrimes * 371541Srgrimes * @(#)kern_prot.c 8.6 (Berkeley) 1/21/94 381541Srgrimes */ 391541Srgrimes 401541Srgrimes/* 411541Srgrimes * System calls related to processes and protection 421541Srgrimes */ 431541Srgrimes 44116182Sobrien#include <sys/cdefs.h> 45116182Sobrien__FBSDID("$FreeBSD: head/sys/kern/kern_prot.c 225617 2011-09-16 13:58:51Z kmacy $"); 46116182Sobrien 4731778Seivind#include "opt_compat.h" 48183982Sbz#include "opt_inet.h" 49183982Sbz#include "opt_inet6.h" 5031778Seivind 511541Srgrimes#include <sys/param.h> 5276166Smarkm#include <sys/systm.h> 531541Srgrimes#include <sys/acct.h> 54132548Srwatson#include <sys/kdb.h> 5541059Speter#include <sys/kernel.h> 5670317Sjake#include <sys/lock.h> 57219304Strasz#include <sys/loginclass.h> 5891140Stanimura#include <sys/malloc.h> 5976166Smarkm#include <sys/mutex.h> 60150634Sjhb#include <sys/refcount.h> 6191140Stanimura#include <sys/sx.h> 62164032Srwatson#include <sys/priv.h> 631541Srgrimes#include <sys/proc.h> 6476166Smarkm#include <sys/sysproto.h> 6587218Srwatson#include <sys/jail.h> 6631891Ssef#include <sys/pioctl.h> 67220212Strasz#include <sys/racct.h> 6865495Struckman#include <sys/resourcevar.h> 6992976Srwatson#include <sys/socket.h> 7092976Srwatson#include <sys/socketvar.h> 71160139Sjhb#include <sys/syscallsubr.h> 7261287Srwatson#include <sys/sysctl.h> 731541Srgrimes 74219028Snetchild#ifdef REGRESSION 75219028SnetchildFEATURE(regression, 76219028Snetchild "Kernel support for interfaces nessesary for regression testing (SECURITY RISK!)"); 77219028Snetchild#endif 78219028Snetchild 79183982Sbz#if defined(INET) || defined(INET6) 80183982Sbz#include <netinet/in.h> 81183982Sbz#include <netinet/in_pcb.h> 82183982Sbz#endif 83183982Sbz 84155370Swsalamon#include <security/audit/audit.h> 85163606Srwatson#include <security/mac/mac_framework.h> 86155370Swsalamon 8730354Sphkstatic MALLOC_DEFINE(M_CRED, "cred", "credentials"); 8830354Sphk 89162383SrwatsonSYSCTL_NODE(_security, OID_AUTO, bsd, CTLFLAG_RW, 0, "BSD security policy"); 9087138Srwatson 91194498Sbrooksstatic void crextend(struct ucred *cr, int n); 92194498Sbrooksstatic void crsetgroups_locked(struct ucred *cr, int ngrp, 93194498Sbrooks gid_t *groups); 94194498Sbrooks 9512221Sbde#ifndef _SYS_SYSPROTO_H_ 9611332Sswallacestruct getpid_args { 971541Srgrimes int dummy; 981541Srgrimes}; 9912221Sbde#endif 1001541Srgrimes/* ARGSUSED */ 1011549Srgrimesint 102225617Skmacysys_getpid(struct thread *td, struct getpid_args *uap) 1031541Srgrimes{ 10483366Sjulian struct proc *p = td->td_proc; 1051541Srgrimes 10683366Sjulian td->td_retval[0] = p->p_pid; 107130344Sphk#if defined(COMPAT_43) 10874728Sjhb PROC_LOCK(p); 10983366Sjulian td->td_retval[1] = p->p_pptr->p_pid; 11074728Sjhb PROC_UNLOCK(p); 1111541Srgrimes#endif 1121541Srgrimes return (0); 1131541Srgrimes} 1141541Srgrimes 11512221Sbde#ifndef _SYS_SYSPROTO_H_ 11611332Sswallacestruct getppid_args { 11711332Sswallace int dummy; 11811332Sswallace}; 11912221Sbde#endif 1201541Srgrimes/* ARGSUSED */ 1211549Srgrimesint 122225617Skmacysys_getppid(struct thread *td, struct getppid_args *uap) 1231541Srgrimes{ 12483366Sjulian struct proc *p = td->td_proc; 1251541Srgrimes 12674728Sjhb PROC_LOCK(p); 12783366Sjulian td->td_retval[0] = p->p_pptr->p_pid; 12874728Sjhb PROC_UNLOCK(p); 1291541Srgrimes return (0); 1301541Srgrimes} 1311541Srgrimes 13287466Srwatson/* 13387218Srwatson * Get process group ID; note that POSIX getpgrp takes no parameter. 13458717Sdillon */ 13512221Sbde#ifndef _SYS_SYSPROTO_H_ 13611332Sswallacestruct getpgrp_args { 13711332Sswallace int dummy; 13811332Sswallace}; 13912221Sbde#endif 1401549Srgrimesint 141225617Skmacysys_getpgrp(struct thread *td, struct getpgrp_args *uap) 1421541Srgrimes{ 14383366Sjulian struct proc *p = td->td_proc; 1441541Srgrimes 14591140Stanimura PROC_LOCK(p); 14683366Sjulian td->td_retval[0] = p->p_pgrp->pg_id; 14791140Stanimura PROC_UNLOCK(p); 1481541Srgrimes return (0); 1491541Srgrimes} 1501541Srgrimes 15128401Speter/* Get an arbitary pid's process group id */ 15212221Sbde#ifndef _SYS_SYSPROTO_H_ 15328401Speterstruct getpgid_args { 15428401Speter pid_t pid; 15528401Speter}; 15628401Speter#endif 15728401Speterint 158225617Skmacysys_getpgid(struct thread *td, struct getpgid_args *uap) 15928401Speter{ 160114031Sjhb struct proc *p; 16192985Sjhb int error; 16241726Struckman 16391140Stanimura if (uap->pid == 0) { 164114031Sjhb p = td->td_proc; 16591140Stanimura PROC_LOCK(p); 166114031Sjhb } else { 167114031Sjhb p = pfind(uap->pid); 168114031Sjhb if (p == NULL) 169114031Sjhb return (ESRCH); 170114031Sjhb error = p_cansee(td, p); 171114031Sjhb if (error) { 172114031Sjhb PROC_UNLOCK(p); 173114031Sjhb return (error); 174114031Sjhb } 17575893Sjhb } 176114031Sjhb td->td_retval[0] = p->p_pgrp->pg_id; 177114031Sjhb PROC_UNLOCK(p); 178114031Sjhb return (0); 17928401Speter} 18028401Speter 18128401Speter/* 18228401Speter * Get an arbitary pid's session id. 18328401Speter */ 18428401Speter#ifndef _SYS_SYSPROTO_H_ 18528401Speterstruct getsid_args { 18628401Speter pid_t pid; 18728401Speter}; 18828401Speter#endif 18928401Speterint 190225617Skmacysys_getsid(struct thread *td, struct getsid_args *uap) 19128401Speter{ 192114031Sjhb struct proc *p; 19387218Srwatson int error; 19441726Struckman 19591140Stanimura if (uap->pid == 0) { 196114031Sjhb p = td->td_proc; 19791140Stanimura PROC_LOCK(p); 198114031Sjhb } else { 199114031Sjhb p = pfind(uap->pid); 200114031Sjhb if (p == NULL) 201114031Sjhb return (ESRCH); 202114031Sjhb error = p_cansee(td, p); 203114031Sjhb if (error) { 204114031Sjhb PROC_UNLOCK(p); 205114031Sjhb return (error); 206114031Sjhb } 20775893Sjhb } 208114031Sjhb td->td_retval[0] = p->p_session->s_sid; 209114031Sjhb PROC_UNLOCK(p); 210114031Sjhb return (0); 21128401Speter} 21228401Speter 21328401Speter#ifndef _SYS_SYSPROTO_H_ 21411332Sswallacestruct getuid_args { 21511332Sswallace int dummy; 21611332Sswallace}; 21712221Sbde#endif 2181541Srgrimes/* ARGSUSED */ 2191549Srgrimesint 220225617Skmacysys_getuid(struct thread *td, struct getuid_args *uap) 2211541Srgrimes{ 2221541Srgrimes 22392987Sjhb td->td_retval[0] = td->td_ucred->cr_ruid; 224130344Sphk#if defined(COMPAT_43) 22592987Sjhb td->td_retval[1] = td->td_ucred->cr_uid; 2261541Srgrimes#endif 2271541Srgrimes return (0); 2281541Srgrimes} 2291541Srgrimes 23012221Sbde#ifndef _SYS_SYSPROTO_H_ 23111332Sswallacestruct geteuid_args { 23211332Sswallace int dummy; 23311332Sswallace}; 23412221Sbde#endif 2351541Srgrimes/* ARGSUSED */ 2361549Srgrimesint 237225617Skmacysys_geteuid(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 2491541Srgrimes/* ARGSUSED */ 2501549Srgrimesint 251225617Skmacysys_getgid(struct thread *td, struct getgid_args *uap) 2521541Srgrimes{ 2531541Srgrimes 25492987Sjhb td->td_retval[0] = td->td_ucred->cr_rgid; 255130344Sphk#if defined(COMPAT_43) 25692987Sjhb td->td_retval[1] = td->td_ucred->cr_groups[0]; 2571541Srgrimes#endif 2581541Srgrimes return (0); 2591541Srgrimes} 2601541Srgrimes 2611541Srgrimes/* 2621541Srgrimes * Get effective group ID. The "egid" is groups[0], and could be obtained 2631541Srgrimes * via getgroups. This syscall exists because it is somewhat painful to do 2641541Srgrimes * correctly in a library function. 2651541Srgrimes */ 26612221Sbde#ifndef _SYS_SYSPROTO_H_ 26711332Sswallacestruct getegid_args { 26811332Sswallace int dummy; 26911332Sswallace}; 27012221Sbde#endif 2711541Srgrimes/* ARGSUSED */ 2721549Srgrimesint 273225617Skmacysys_getegid(struct thread *td, struct getegid_args *uap) 2741541Srgrimes{ 2751541Srgrimes 27692987Sjhb td->td_retval[0] = td->td_ucred->cr_groups[0]; 2771541Srgrimes return (0); 2781541Srgrimes} 2791541Srgrimes 28012221Sbde#ifndef _SYS_SYSPROTO_H_ 2811541Srgrimesstruct getgroups_args { 2821541Srgrimes u_int gidsetsize; 2831541Srgrimes gid_t *gidset; 2841541Srgrimes}; 28512221Sbde#endif 2861549Srgrimesint 287225617Skmacysys_getgroups(struct thread *td, register struct getgroups_args *uap) 2881541Srgrimes{ 289194498Sbrooks gid_t *groups; 29077183Srwatson u_int ngrp; 29187218Srwatson int error; 2921541Srgrimes 293202342Sbrooks if (uap->gidsetsize < td->td_ucred->cr_ngroups) { 294202342Sbrooks if (uap->gidsetsize == 0) 295202342Sbrooks ngrp = 0; 296202342Sbrooks else 297202342Sbrooks return (EINVAL); 298202342Sbrooks } else 299202342Sbrooks ngrp = td->td_ucred->cr_ngroups; 300194498Sbrooks groups = malloc(ngrp * sizeof(*groups), M_TEMP, M_WAITOK); 301160139Sjhb error = kern_getgroups(td, &ngrp, groups); 302160139Sjhb if (error) 303194498Sbrooks goto out; 304160139Sjhb if (uap->gidsetsize > 0) 305160139Sjhb error = copyout(groups, uap->gidset, ngrp * sizeof(gid_t)); 306160139Sjhb if (error == 0) 307160139Sjhb td->td_retval[0] = ngrp; 308194498Sbrooksout: 309194498Sbrooks free(groups, M_TEMP); 310160139Sjhb return (error); 311160139Sjhb} 312160139Sjhb 313160139Sjhbint 314160139Sjhbkern_getgroups(struct thread *td, u_int *ngrp, gid_t *groups) 315160139Sjhb{ 316160139Sjhb struct ucred *cred; 317160139Sjhb 31892987Sjhb cred = td->td_ucred; 319160139Sjhb if (*ngrp == 0) { 320160139Sjhb *ngrp = cred->cr_ngroups; 32192987Sjhb return (0); 3221541Srgrimes } 323160139Sjhb if (*ngrp < cred->cr_ngroups) 32492987Sjhb return (EINVAL); 325160139Sjhb *ngrp = cred->cr_ngroups; 326160139Sjhb bcopy(cred->cr_groups, groups, *ngrp * sizeof(gid_t)); 327160139Sjhb return (0); 3281541Srgrimes} 3291541Srgrimes 33012221Sbde#ifndef _SYS_SYSPROTO_H_ 33112207Sbdestruct setsid_args { 33211332Sswallace int dummy; 33311332Sswallace}; 33412221Sbde#endif 3351541Srgrimes/* ARGSUSED */ 3361549Srgrimesint 337225617Skmacysys_setsid(register struct thread *td, struct setsid_args *uap) 3381541Srgrimes{ 33991140Stanimura struct pgrp *pgrp; 34082749Sdillon int error; 34183366Sjulian struct proc *p = td->td_proc; 34291140Stanimura struct pgrp *newpgrp; 34391140Stanimura struct session *newsess; 3441541Srgrimes 34591140Stanimura error = 0; 34691140Stanimura pgrp = NULL; 34791140Stanimura 348184205Sdes newpgrp = malloc(sizeof(struct pgrp), M_PGRP, M_WAITOK | M_ZERO); 349184205Sdes newsess = malloc(sizeof(struct session), M_SESSION, M_WAITOK | M_ZERO); 35091140Stanimura 35194859Sjhb sx_xlock(&proctree_lock); 35291140Stanimura 35391140Stanimura if (p->p_pgid == p->p_pid || (pgrp = pgfind(p->p_pid)) != NULL) { 35491140Stanimura if (pgrp != NULL) 35591140Stanimura PGRP_UNLOCK(pgrp); 35682749Sdillon error = EPERM; 35791140Stanimura } else { 35891140Stanimura (void)enterpgrp(p, p->p_pid, newpgrp, newsess); 35983366Sjulian td->td_retval[0] = p->p_pid; 36094859Sjhb newpgrp = NULL; 36194859Sjhb newsess = NULL; 3621541Srgrimes } 36391140Stanimura 36494859Sjhb sx_xunlock(&proctree_lock); 36591140Stanimura 36695973Stanimura if (newpgrp != NULL) 367184205Sdes free(newpgrp, M_PGRP); 36895973Stanimura if (newsess != NULL) 369184205Sdes free(newsess, M_SESSION); 37091140Stanimura 37194859Sjhb return (error); 3721541Srgrimes} 3731541Srgrimes 3741541Srgrimes/* 3751541Srgrimes * set process group (setpgid/old setpgrp) 3761541Srgrimes * 3771541Srgrimes * caller does setpgid(targpid, targpgid) 3781541Srgrimes * 3791541Srgrimes * pid must be caller or child of caller (ESRCH) 3801541Srgrimes * if a child 3811541Srgrimes * pid must be in same session (EPERM) 3821541Srgrimes * pid can't have done an exec (EACCES) 3831541Srgrimes * if pgid != pid 3841541Srgrimes * there must exist some pid in same session having pgid (EPERM) 3851541Srgrimes * pid must not be session leader (EPERM) 3861541Srgrimes */ 38712221Sbde#ifndef _SYS_SYSPROTO_H_ 3881541Srgrimesstruct setpgid_args { 38987218Srwatson int pid; /* target process id */ 39087218Srwatson int pgid; /* target pgrp id */ 3911541Srgrimes}; 39212221Sbde#endif 3931541Srgrimes/* ARGSUSED */ 3941549Srgrimesint 395225617Skmacysys_setpgid(struct thread *td, register struct setpgid_args *uap) 3961541Srgrimes{ 39783366Sjulian struct proc *curp = td->td_proc; 39887218Srwatson register struct proc *targp; /* target process */ 39987218Srwatson register struct pgrp *pgrp; /* target pgrp */ 40075448Srwatson int error; 40191140Stanimura struct pgrp *newpgrp; 4021541Srgrimes 40320677Sbde if (uap->pgid < 0) 40420677Sbde return (EINVAL); 40591140Stanimura 40691140Stanimura error = 0; 40791140Stanimura 408184205Sdes newpgrp = malloc(sizeof(struct pgrp), M_PGRP, M_WAITOK | M_ZERO); 40991140Stanimura 41094859Sjhb sx_xlock(&proctree_lock); 4111541Srgrimes if (uap->pid != 0 && uap->pid != curp->p_pid) { 41291140Stanimura if ((targp = pfind(uap->pid)) == NULL) { 41382749Sdillon error = ESRCH; 41494859Sjhb goto done; 41575893Sjhb } 41691140Stanimura if (!inferior(targp)) { 41791140Stanimura PROC_UNLOCK(targp); 41891371Stanimura error = ESRCH; 41994859Sjhb goto done; 42091140Stanimura } 421132568Srwatson if ((error = p_cansee(td, targp))) { 42275893Sjhb PROC_UNLOCK(targp); 42394859Sjhb goto done; 42475893Sjhb } 42575893Sjhb if (targp->p_pgrp == NULL || 42675893Sjhb targp->p_session != curp->p_session) { 42775893Sjhb PROC_UNLOCK(targp); 42882749Sdillon error = EPERM; 42994859Sjhb goto done; 43075893Sjhb } 43175893Sjhb if (targp->p_flag & P_EXEC) { 43275893Sjhb PROC_UNLOCK(targp); 43382749Sdillon error = EACCES; 43494859Sjhb goto done; 43575893Sjhb } 43691140Stanimura PROC_UNLOCK(targp); 43791140Stanimura } else 4381541Srgrimes targp = curp; 43975893Sjhb if (SESS_LEADER(targp)) { 44082749Sdillon error = EPERM; 44194859Sjhb goto done; 44275893Sjhb } 44387218Srwatson if (uap->pgid == 0) 4441541Srgrimes uap->pgid = targp->p_pid; 445117214Scognet if ((pgrp = pgfind(uap->pgid)) == NULL) { 446117214Scognet if (uap->pgid == targp->p_pid) { 447117214Scognet error = enterpgrp(targp, uap->pgid, newpgrp, 448117214Scognet NULL); 449117214Scognet if (error == 0) 450117214Scognet newpgrp = NULL; 451117214Scognet } else 452117214Scognet error = EPERM; 45391140Stanimura } else { 454117214Scognet if (pgrp == targp->p_pgrp) { 455117214Scognet PGRP_UNLOCK(pgrp); 45694859Sjhb goto done; 45775893Sjhb } 458117214Scognet if (pgrp->pg_id != targp->p_pid && 459117214Scognet pgrp->pg_session != curp->p_session) { 46091140Stanimura PGRP_UNLOCK(pgrp); 461117214Scognet error = EPERM; 46291140Stanimura goto done; 46391140Stanimura } 46491140Stanimura PGRP_UNLOCK(pgrp); 46591140Stanimura error = enterthispgrp(targp, pgrp); 46682749Sdillon } 46791140Stanimuradone: 46894859Sjhb sx_xunlock(&proctree_lock); 46994859Sjhb KASSERT((error == 0) || (newpgrp != NULL), 47094859Sjhb ("setpgid failed and newpgrp is NULL")); 47195973Stanimura if (newpgrp != NULL) 472184205Sdes free(newpgrp, M_PGRP); 47382749Sdillon return (error); 4741541Srgrimes} 4751541Srgrimes 47624448Speter/* 47724448Speter * Use the clause in B.4.2.2 that allows setuid/setgid to be 4.2/4.3BSD 47872093Sasmodai * compatible. It says that setting the uid/gid to euid/egid is a special 47924448Speter * case of "appropriate privilege". Once the rules are expanded out, this 48024448Speter * basically means that setuid(nnn) sets all three id's, in all permitted 48124448Speter * cases unless _POSIX_SAVED_IDS is enabled. In that case, setuid(getuid()) 48224448Speter * does not set the saved id - this is dangerous for traditional BSD 48324448Speter * programs. For this reason, we *really* do not want to set 48424448Speter * _POSIX_SAVED_IDS and do not want to clear POSIX_APPENDIX_B_4_2_2. 48524448Speter */ 48624448Speter#define POSIX_APPENDIX_B_4_2_2 48724448Speter 48812221Sbde#ifndef _SYS_SYSPROTO_H_ 4891541Srgrimesstruct setuid_args { 4901541Srgrimes uid_t uid; 4911541Srgrimes}; 49212221Sbde#endif 4931541Srgrimes/* ARGSUSED */ 4941549Srgrimesint 495225617Skmacysys_setuid(struct thread *td, struct setuid_args *uap) 4961541Srgrimes{ 49783366Sjulian struct proc *p = td->td_proc; 49877183Srwatson struct ucred *newcred, *oldcred; 49977183Srwatson uid_t uid; 50098417Salfred struct uidinfo *uip; 50187218Srwatson int error; 5021541Srgrimes 50377183Srwatson uid = uap->uid; 504195104Srwatson AUDIT_ARG_UID(uid); 50594619Sjhb newcred = crget(); 50698417Salfred uip = uifind(uid); 50794619Sjhb PROC_LOCK(p); 508194498Sbrooks /* 509194498Sbrooks * Copy credentials so other references do not see our changes. 510194498Sbrooks */ 511194498Sbrooks oldcred = crcopysafe(p, newcred); 51287466Srwatson 513145147Srwatson#ifdef MAC 514189529Srwatson error = mac_cred_check_setuid(oldcred, uid); 515145147Srwatson if (error) 516145147Srwatson goto fail; 517145147Srwatson#endif 518145147Srwatson 51924448Speter /* 52024448Speter * See if we have "permission" by POSIX 1003.1 rules. 52124448Speter * 52287218Srwatson * Note that setuid(geteuid()) is a special case of 52324448Speter * "appropriate privileges" in appendix B.4.2.2. We need 52472093Sasmodai * to use this clause to be compatible with traditional BSD 52524448Speter * semantics. Basically, it means that "setuid(xx)" sets all 52624448Speter * three id's (assuming you have privs). 52724448Speter * 52824448Speter * Notes on the logic. We do things in three steps. 52924448Speter * 1: We determine if the euid is going to change, and do EPERM 53024448Speter * right away. We unconditionally change the euid later if this 53124448Speter * test is satisfied, simplifying that part of the logic. 53287218Srwatson * 2: We determine if the real and/or saved uids are going to 53324448Speter * change. Determined by compile options. 53424448Speter * 3: Change euid last. (after tests in #2 for "appropriate privs") 53524448Speter */ 53677183Srwatson if (uid != oldcred->cr_ruid && /* allow setuid(getuid()) */ 53717994Sache#ifdef _POSIX_SAVED_IDS 53877183Srwatson uid != oldcred->cr_svuid && /* allow setuid(saved gid) */ 53917994Sache#endif 54024448Speter#ifdef POSIX_APPENDIX_B_4_2_2 /* Use BSD-compat clause from B.4.2.2 */ 54177183Srwatson uid != oldcred->cr_uid && /* allow setuid(geteuid()) */ 54224448Speter#endif 543170587Srwatson (error = priv_check_cred(oldcred, PRIV_CRED_SETUID, 0)) != 0) 544145147Srwatson goto fail; 54524448Speter 54624448Speter#ifdef _POSIX_SAVED_IDS 5471541Srgrimes /* 54824448Speter * Do we have "appropriate privileges" (are we root or uid == euid) 54924448Speter * If so, we are changing the real uid and/or saved uid. 5501541Srgrimes */ 55117994Sache if ( 55224448Speter#ifdef POSIX_APPENDIX_B_4_2_2 /* Use the clause from B.4.2.2 */ 55377183Srwatson uid == oldcred->cr_uid || 55417994Sache#endif 555164032Srwatson /* We are using privs. */ 556170587Srwatson priv_check_cred(oldcred, PRIV_CRED_SETUID, 0) == 0) 55717994Sache#endif 55824448Speter { 55924448Speter /* 56065495Struckman * Set the real uid and transfer proc count to new user. 56124448Speter */ 56277183Srwatson if (uid != oldcred->cr_ruid) { 56398417Salfred change_ruid(newcred, uip); 56465495Struckman setsugid(p); 56524448Speter } 56624448Speter /* 56724448Speter * Set saved uid 56824448Speter * 56924448Speter * XXX always set saved uid even if not _POSIX_SAVED_IDS, as 57024448Speter * the security of seteuid() depends on it. B.4.2.2 says it 57124448Speter * is important that we should do this. 57224448Speter */ 57377183Srwatson if (uid != oldcred->cr_svuid) { 57477183Srwatson change_svuid(newcred, uid); 57531891Ssef setsugid(p); 57624448Speter } 5778141Sache } 57824448Speter 57924448Speter /* 58024448Speter * In all permitted cases, we are changing the euid. 58124448Speter */ 58277183Srwatson if (uid != oldcred->cr_uid) { 58398417Salfred change_euid(newcred, uip); 58431891Ssef setsugid(p); 58524448Speter } 58677183Srwatson p->p_ucred = newcred; 58794619Sjhb PROC_UNLOCK(p); 588220212Strasz#ifdef RACCT 589220212Strasz racct_proc_ucred_changed(p, oldcred, newcred); 590220212Strasz#endif 59198417Salfred uifree(uip); 59277183Srwatson crfree(oldcred); 59394619Sjhb return (0); 594145147Srwatson 595145147Srwatsonfail: 596145147Srwatson PROC_UNLOCK(p); 597145147Srwatson uifree(uip); 598145147Srwatson crfree(newcred); 599145147Srwatson return (error); 6001541Srgrimes} 6011541Srgrimes 60212221Sbde#ifndef _SYS_SYSPROTO_H_ 6031541Srgrimesstruct seteuid_args { 6041541Srgrimes uid_t euid; 6051541Srgrimes}; 60612221Sbde#endif 6071541Srgrimes/* ARGSUSED */ 6081549Srgrimesint 609225617Skmacysys_seteuid(struct thread *td, struct seteuid_args *uap) 6101541Srgrimes{ 61183366Sjulian struct proc *p = td->td_proc; 61277183Srwatson struct ucred *newcred, *oldcred; 61377183Srwatson uid_t euid; 61498417Salfred struct uidinfo *euip; 61587218Srwatson int error; 6161541Srgrimes 6171541Srgrimes euid = uap->euid; 618195104Srwatson AUDIT_ARG_EUID(euid); 61994619Sjhb newcred = crget(); 62098417Salfred euip = uifind(euid); 62194619Sjhb PROC_LOCK(p); 622194498Sbrooks /* 623194498Sbrooks * Copy credentials so other references do not see our changes. 624194498Sbrooks */ 625194498Sbrooks oldcred = crcopysafe(p, newcred); 626145147Srwatson 627145147Srwatson#ifdef MAC 628189529Srwatson error = mac_cred_check_seteuid(oldcred, euid); 629145147Srwatson if (error) 630145147Srwatson goto fail; 631145147Srwatson#endif 632145147Srwatson 63377183Srwatson if (euid != oldcred->cr_ruid && /* allow seteuid(getuid()) */ 63477183Srwatson euid != oldcred->cr_svuid && /* allow seteuid(saved uid) */ 635170587Srwatson (error = priv_check_cred(oldcred, PRIV_CRED_SETEUID, 0)) != 0) 636145147Srwatson goto fail; 637145147Srwatson 6381541Srgrimes /* 639194498Sbrooks * Everything's okay, do it. 6401541Srgrimes */ 64177183Srwatson if (oldcred->cr_uid != euid) { 64298417Salfred change_euid(newcred, euip); 64331891Ssef setsugid(p); 64424449Speter } 64577183Srwatson p->p_ucred = newcred; 64694619Sjhb PROC_UNLOCK(p); 64798417Salfred uifree(euip); 64877183Srwatson crfree(oldcred); 64994619Sjhb return (0); 650145147Srwatson 651145147Srwatsonfail: 652145147Srwatson PROC_UNLOCK(p); 653145147Srwatson uifree(euip); 654145147Srwatson crfree(newcred); 655145147Srwatson return (error); 6561541Srgrimes} 6571541Srgrimes 65812221Sbde#ifndef _SYS_SYSPROTO_H_ 6591541Srgrimesstruct setgid_args { 6601541Srgrimes gid_t gid; 6611541Srgrimes}; 66212221Sbde#endif 6631541Srgrimes/* ARGSUSED */ 6641549Srgrimesint 665225617Skmacysys_setgid(struct thread *td, struct setgid_args *uap) 6661541Srgrimes{ 66783366Sjulian struct proc *p = td->td_proc; 66877183Srwatson struct ucred *newcred, *oldcred; 66977183Srwatson gid_t gid; 67087218Srwatson int error; 6711541Srgrimes 67277183Srwatson gid = uap->gid; 673195104Srwatson AUDIT_ARG_GID(gid); 67494619Sjhb newcred = crget(); 67594619Sjhb PROC_LOCK(p); 676194498Sbrooks oldcred = crcopysafe(p, newcred); 67787466Srwatson 678145147Srwatson#ifdef MAC 679189529Srwatson error = mac_cred_check_setgid(oldcred, gid); 680145147Srwatson if (error) 681145147Srwatson goto fail; 682145147Srwatson#endif 683145147Srwatson 68424448Speter /* 68524448Speter * See if we have "permission" by POSIX 1003.1 rules. 68624448Speter * 68724448Speter * Note that setgid(getegid()) is a special case of 68824448Speter * "appropriate privileges" in appendix B.4.2.2. We need 68972093Sasmodai * to use this clause to be compatible with traditional BSD 69024448Speter * semantics. Basically, it means that "setgid(xx)" sets all 69124448Speter * three id's (assuming you have privs). 69224448Speter * 69324448Speter * For notes on the logic here, see setuid() above. 69424448Speter */ 69577183Srwatson if (gid != oldcred->cr_rgid && /* allow setgid(getgid()) */ 69617994Sache#ifdef _POSIX_SAVED_IDS 69777183Srwatson gid != oldcred->cr_svgid && /* allow setgid(saved gid) */ 69817994Sache#endif 69924448Speter#ifdef POSIX_APPENDIX_B_4_2_2 /* Use BSD-compat clause from B.4.2.2 */ 70077183Srwatson gid != oldcred->cr_groups[0] && /* allow setgid(getegid()) */ 70124448Speter#endif 702170587Srwatson (error = priv_check_cred(oldcred, PRIV_CRED_SETGID, 0)) != 0) 703145147Srwatson goto fail; 70424448Speter 70517994Sache#ifdef _POSIX_SAVED_IDS 70624448Speter /* 70724448Speter * Do we have "appropriate privileges" (are we root or gid == egid) 70824448Speter * If so, we are changing the real uid and saved gid. 70924448Speter */ 71024448Speter if ( 71124448Speter#ifdef POSIX_APPENDIX_B_4_2_2 /* use the clause from B.4.2.2 */ 71277183Srwatson gid == oldcred->cr_groups[0] || 71317994Sache#endif 714164032Srwatson /* We are using privs. */ 715170587Srwatson priv_check_cred(oldcred, PRIV_CRED_SETGID, 0) == 0) 71624448Speter#endif 71724448Speter { 71824448Speter /* 71924448Speter * Set real gid 72024448Speter */ 72177183Srwatson if (oldcred->cr_rgid != gid) { 72277183Srwatson change_rgid(newcred, gid); 72331891Ssef setsugid(p); 72424448Speter } 72524448Speter /* 72624448Speter * Set saved gid 72724448Speter * 72824448Speter * XXX always set saved gid even if not _POSIX_SAVED_IDS, as 72924448Speter * the security of setegid() depends on it. B.4.2.2 says it 73024448Speter * is important that we should do this. 73124448Speter */ 73277183Srwatson if (oldcred->cr_svgid != gid) { 73377183Srwatson change_svgid(newcred, gid); 73431891Ssef setsugid(p); 73524448Speter } 7368141Sache } 73724448Speter /* 73824448Speter * In all cases permitted cases, we are changing the egid. 73924448Speter * Copy credentials so other references do not see our changes. 74024448Speter */ 74177183Srwatson if (oldcred->cr_groups[0] != gid) { 74277183Srwatson change_egid(newcred, gid); 74331891Ssef setsugid(p); 74424448Speter } 74577183Srwatson p->p_ucred = newcred; 74694619Sjhb PROC_UNLOCK(p); 74777183Srwatson crfree(oldcred); 74894619Sjhb return (0); 749145147Srwatson 750145147Srwatsonfail: 751145147Srwatson PROC_UNLOCK(p); 752145147Srwatson crfree(newcred); 753145147Srwatson return (error); 7541541Srgrimes} 7551541Srgrimes 75612221Sbde#ifndef _SYS_SYSPROTO_H_ 7571541Srgrimesstruct setegid_args { 7581541Srgrimes gid_t egid; 7591541Srgrimes}; 76012221Sbde#endif 7611541Srgrimes/* ARGSUSED */ 7621549Srgrimesint 763225617Skmacysys_setegid(struct thread *td, struct setegid_args *uap) 7641541Srgrimes{ 76583366Sjulian struct proc *p = td->td_proc; 76677183Srwatson struct ucred *newcred, *oldcred; 76777183Srwatson gid_t egid; 76887218Srwatson int error; 7691541Srgrimes 7701541Srgrimes egid = uap->egid; 771195104Srwatson AUDIT_ARG_EGID(egid); 77294619Sjhb newcred = crget(); 77394619Sjhb PROC_LOCK(p); 774194498Sbrooks oldcred = crcopysafe(p, newcred); 775145147Srwatson 776145147Srwatson#ifdef MAC 777189529Srwatson error = mac_cred_check_setegid(oldcred, egid); 778145147Srwatson if (error) 779145147Srwatson goto fail; 780145147Srwatson#endif 781145147Srwatson 78277183Srwatson if (egid != oldcred->cr_rgid && /* allow setegid(getgid()) */ 78377183Srwatson egid != oldcred->cr_svgid && /* allow setegid(saved gid) */ 784170587Srwatson (error = priv_check_cred(oldcred, PRIV_CRED_SETEGID, 0)) != 0) 785145147Srwatson goto fail; 786145147Srwatson 78777183Srwatson if (oldcred->cr_groups[0] != egid) { 78877183Srwatson change_egid(newcred, egid); 78931891Ssef setsugid(p); 79024449Speter } 79177183Srwatson p->p_ucred = newcred; 79294619Sjhb PROC_UNLOCK(p); 79377183Srwatson crfree(oldcred); 79494619Sjhb return (0); 795145147Srwatson 796145147Srwatsonfail: 797145147Srwatson PROC_UNLOCK(p); 798145147Srwatson crfree(newcred); 799145147Srwatson return (error); 8001541Srgrimes} 8011541Srgrimes 80212221Sbde#ifndef _SYS_SYSPROTO_H_ 8031541Srgrimesstruct setgroups_args { 8041541Srgrimes u_int gidsetsize; 8051541Srgrimes gid_t *gidset; 8061541Srgrimes}; 80712221Sbde#endif 8081541Srgrimes/* ARGSUSED */ 8091549Srgrimesint 810225617Skmacysys_setgroups(struct thread *td, struct setgroups_args *uap) 8111541Srgrimes{ 812194498Sbrooks gid_t *groups = NULL; 813160139Sjhb int error; 814160139Sjhb 815202143Sbrooks if (uap->gidsetsize > ngroups_max + 1) 816160139Sjhb return (EINVAL); 817194498Sbrooks groups = malloc(uap->gidsetsize * sizeof(gid_t), M_TEMP, M_WAITOK); 818160139Sjhb error = copyin(uap->gidset, groups, uap->gidsetsize * sizeof(gid_t)); 819160139Sjhb if (error) 820194498Sbrooks goto out; 821194498Sbrooks error = kern_setgroups(td, uap->gidsetsize, groups); 822194498Sbrooksout: 823194498Sbrooks free(groups, M_TEMP); 824194498Sbrooks return (error); 825160139Sjhb} 826160139Sjhb 827160139Sjhbint 828160139Sjhbkern_setgroups(struct thread *td, u_int ngrp, gid_t *groups) 829160139Sjhb{ 83083366Sjulian struct proc *p = td->td_proc; 831160139Sjhb struct ucred *newcred, *oldcred; 8321541Srgrimes int error; 8331541Srgrimes 834202143Sbrooks if (ngrp > ngroups_max + 1) 83594619Sjhb return (EINVAL); 836195104Srwatson AUDIT_ARG_GROUPSET(groups, ngrp); 83794619Sjhb newcred = crget(); 838194498Sbrooks crextend(newcred, ngrp); 83994619Sjhb PROC_LOCK(p); 840194498Sbrooks oldcred = crcopysafe(p, newcred); 841145147Srwatson 842145147Srwatson#ifdef MAC 843189529Srwatson error = mac_cred_check_setgroups(oldcred, ngrp, groups); 844145147Srwatson if (error) 845145147Srwatson goto fail; 846145147Srwatson#endif 847145147Srwatson 848170587Srwatson error = priv_check_cred(oldcred, PRIV_CRED_SETGROUPS, 0); 849145147Srwatson if (error) 850145147Srwatson goto fail; 851145147Srwatson 85224447Speter if (ngrp < 1) { 85324447Speter /* 85424447Speter * setgroups(0, NULL) is a legitimate way of clearing the 85524447Speter * groups vector on non-BSD systems (which generally do not 85624447Speter * have the egid in the groups[0]). We risk security holes 85724447Speter * when running non-BSD software if we do not do the same. 85824447Speter */ 85977183Srwatson newcred->cr_ngroups = 1; 86024447Speter } else { 861194498Sbrooks crsetgroups_locked(newcred, ngrp, groups); 86224447Speter } 86331891Ssef setsugid(p); 86477183Srwatson p->p_ucred = newcred; 86594619Sjhb PROC_UNLOCK(p); 86677183Srwatson crfree(oldcred); 86794619Sjhb return (0); 868145147Srwatson 869145147Srwatsonfail: 870145147Srwatson PROC_UNLOCK(p); 871145147Srwatson crfree(newcred); 872145147Srwatson return (error); 8731541Srgrimes} 8741541Srgrimes 87512221Sbde#ifndef _SYS_SYSPROTO_H_ 8761541Srgrimesstruct setreuid_args { 8779238Sache uid_t ruid; 8789238Sache uid_t euid; 8791541Srgrimes}; 88012221Sbde#endif 8811541Srgrimes/* ARGSUSED */ 8821549Srgrimesint 883225617Skmacysys_setreuid(register struct thread *td, struct setreuid_args *uap) 8841541Srgrimes{ 88583366Sjulian struct proc *p = td->td_proc; 88677183Srwatson struct ucred *newcred, *oldcred; 88787218Srwatson uid_t euid, ruid; 88898417Salfred struct uidinfo *euip, *ruip; 88987218Srwatson int error; 8901541Srgrimes 89187218Srwatson euid = uap->euid; 8929238Sache ruid = uap->ruid; 893195104Srwatson AUDIT_ARG_EUID(euid); 894195104Srwatson AUDIT_ARG_RUID(ruid); 89594619Sjhb newcred = crget(); 89698417Salfred euip = uifind(euid); 89798417Salfred ruip = uifind(ruid); 89894619Sjhb PROC_LOCK(p); 899194498Sbrooks oldcred = crcopysafe(p, newcred); 900145147Srwatson 901145147Srwatson#ifdef MAC 902189529Srwatson error = mac_cred_check_setreuid(oldcred, ruid, euid); 903145147Srwatson if (error) 904145147Srwatson goto fail; 905145147Srwatson#endif 906145147Srwatson 90777183Srwatson if (((ruid != (uid_t)-1 && ruid != oldcred->cr_ruid && 90877183Srwatson ruid != oldcred->cr_svuid) || 90977183Srwatson (euid != (uid_t)-1 && euid != oldcred->cr_uid && 91077183Srwatson euid != oldcred->cr_ruid && euid != oldcred->cr_svuid)) && 911170587Srwatson (error = priv_check_cred(oldcred, PRIV_CRED_SETREUID, 0)) != 0) 912145147Srwatson goto fail; 913145147Srwatson 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); 929220212Strasz#ifdef RACCT 930220212Strasz racct_proc_ucred_changed(p, oldcred, newcred); 931220212Strasz#endif 93298417Salfred uifree(ruip); 93398417Salfred uifree(euip); 93477183Srwatson crfree(oldcred); 93594619Sjhb return (0); 936145147Srwatson 937145147Srwatsonfail: 938145147Srwatson PROC_UNLOCK(p); 939145147Srwatson uifree(ruip); 940145147Srwatson uifree(euip); 941145147Srwatson crfree(newcred); 942145147Srwatson return (error); 9431541Srgrimes} 9441541Srgrimes 94512221Sbde#ifndef _SYS_SYSPROTO_H_ 9461541Srgrimesstruct setregid_args { 9479238Sache gid_t rgid; 9489238Sache gid_t egid; 9491541Srgrimes}; 95012221Sbde#endif 9511541Srgrimes/* ARGSUSED */ 9521549Srgrimesint 953225617Skmacysys_setregid(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; 962195104Srwatson AUDIT_ARG_EGID(egid); 963195104Srwatson AUDIT_ARG_RGID(rgid); 96494619Sjhb newcred = crget(); 96594619Sjhb PROC_LOCK(p); 966194498Sbrooks oldcred = crcopysafe(p, newcred); 967145147Srwatson 968145147Srwatson#ifdef MAC 969189529Srwatson error = mac_cred_check_setregid(oldcred, rgid, egid); 970145147Srwatson if (error) 971145147Srwatson goto fail; 972145147Srwatson#endif 973145147Srwatson 97477183Srwatson if (((rgid != (gid_t)-1 && rgid != oldcred->cr_rgid && 97577183Srwatson rgid != oldcred->cr_svgid) || 97677183Srwatson (egid != (gid_t)-1 && egid != oldcred->cr_groups[0] && 97777183Srwatson egid != oldcred->cr_rgid && egid != oldcred->cr_svgid)) && 978170587Srwatson (error = priv_check_cred(oldcred, PRIV_CRED_SETREGID, 0)) != 0) 979145147Srwatson goto fail; 98094619Sjhb 98177183Srwatson if (egid != (gid_t)-1 && oldcred->cr_groups[0] != egid) { 98277183Srwatson change_egid(newcred, egid); 98331891Ssef setsugid(p); 98424450Speter } 98577183Srwatson if (rgid != (gid_t)-1 && oldcred->cr_rgid != rgid) { 98677183Srwatson change_rgid(newcred, rgid); 98731891Ssef setsugid(p); 98824450Speter } 98977183Srwatson if ((rgid != (gid_t)-1 || newcred->cr_groups[0] != newcred->cr_rgid) && 99077183Srwatson newcred->cr_svgid != newcred->cr_groups[0]) { 99177183Srwatson change_svgid(newcred, newcred->cr_groups[0]); 99231891Ssef setsugid(p); 99324450Speter } 99477812Sru p->p_ucred = newcred; 99594619Sjhb PROC_UNLOCK(p); 99677812Sru crfree(oldcred); 99794619Sjhb return (0); 998145147Srwatson 999145147Srwatsonfail: 1000145147Srwatson PROC_UNLOCK(p); 1001145147Srwatson crfree(newcred); 1002145147Srwatson return (error); 10031541Srgrimes} 10041541Srgrimes 100556115Speter/* 1006167232Srwatson * setresuid(ruid, euid, suid) is like setreuid except control over the saved 1007167232Srwatson * uid is explicit. 100856115Speter */ 100924453Speter#ifndef _SYS_SYSPROTO_H_ 101056115Speterstruct setresuid_args { 101156115Speter uid_t ruid; 101256115Speter uid_t euid; 101356115Speter uid_t suid; 101456115Speter}; 101556115Speter#endif 101656115Speter/* ARGSUSED */ 101756115Speterint 1018225617Skmacysys_setresuid(register struct thread *td, struct setresuid_args *uap) 101956115Speter{ 102083366Sjulian struct proc *p = td->td_proc; 102177183Srwatson struct ucred *newcred, *oldcred; 102287218Srwatson uid_t euid, ruid, suid; 102398417Salfred struct uidinfo *euip, *ruip; 102456115Speter int error; 102556115Speter 102687218Srwatson euid = uap->euid; 102756115Speter ruid = uap->ruid; 102856115Speter suid = uap->suid; 1029195104Srwatson AUDIT_ARG_EUID(euid); 1030195104Srwatson AUDIT_ARG_RUID(ruid); 1031195104Srwatson AUDIT_ARG_SUID(suid); 103294619Sjhb newcred = crget(); 103398417Salfred euip = uifind(euid); 103498417Salfred ruip = uifind(ruid); 103594619Sjhb PROC_LOCK(p); 1036194498Sbrooks oldcred = crcopysafe(p, newcred); 1037145147Srwatson 1038145147Srwatson#ifdef MAC 1039189529Srwatson error = mac_cred_check_setresuid(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)) && 1053170587Srwatson (error = priv_check_cred(oldcred, PRIV_CRED_SETRESUID, 0)) != 0) 1054145147Srwatson goto fail; 105594619Sjhb 105677183Srwatson if (euid != (uid_t)-1 && oldcred->cr_uid != euid) { 105798417Salfred change_euid(newcred, euip); 105856115Speter setsugid(p); 105956115Speter } 106077183Srwatson if (ruid != (uid_t)-1 && oldcred->cr_ruid != ruid) { 106198417Salfred change_ruid(newcred, ruip); 106256115Speter setsugid(p); 106356115Speter } 106477183Srwatson if (suid != (uid_t)-1 && oldcred->cr_svuid != suid) { 106577183Srwatson change_svuid(newcred, suid); 106656115Speter setsugid(p); 106756115Speter } 106877183Srwatson p->p_ucred = newcred; 106994619Sjhb PROC_UNLOCK(p); 1070220212Strasz#ifdef RACCT 1071220212Strasz racct_proc_ucred_changed(p, oldcred, newcred); 1072220212Strasz#endif 107398417Salfred uifree(ruip); 107498417Salfred uifree(euip); 107577183Srwatson crfree(oldcred); 107694619Sjhb return (0); 1077145147Srwatson 1078145147Srwatsonfail: 1079145147Srwatson PROC_UNLOCK(p); 1080145147Srwatson uifree(ruip); 1081145147Srwatson uifree(euip); 1082145147Srwatson crfree(newcred); 1083145147Srwatson return (error); 1084145147Srwatson 108556115Speter} 108656115Speter 108756115Speter/* 1088167232Srwatson * setresgid(rgid, egid, sgid) is like setregid except control over the saved 1089167232Srwatson * gid is explicit. 109056115Speter */ 109156115Speter#ifndef _SYS_SYSPROTO_H_ 109256115Speterstruct setresgid_args { 109356115Speter gid_t rgid; 109456115Speter gid_t egid; 109556115Speter gid_t sgid; 109656115Speter}; 109756115Speter#endif 109856115Speter/* ARGSUSED */ 109956115Speterint 1100225617Skmacysys_setresgid(register struct thread *td, struct setresgid_args *uap) 110156115Speter{ 110283366Sjulian struct proc *p = td->td_proc; 110377183Srwatson struct ucred *newcred, *oldcred; 110487218Srwatson gid_t egid, rgid, sgid; 110556115Speter int error; 110656115Speter 110787218Srwatson egid = uap->egid; 110856115Speter rgid = uap->rgid; 110956115Speter sgid = uap->sgid; 1110195104Srwatson AUDIT_ARG_EGID(egid); 1111195104Srwatson AUDIT_ARG_RGID(rgid); 1112195104Srwatson AUDIT_ARG_SGID(sgid); 111394619Sjhb newcred = crget(); 111494619Sjhb PROC_LOCK(p); 1115194498Sbrooks oldcred = crcopysafe(p, newcred); 1116145147Srwatson 1117145147Srwatson#ifdef MAC 1118189529Srwatson error = mac_cred_check_setresgid(oldcred, rgid, egid, sgid); 1119145147Srwatson if (error) 1120145147Srwatson goto fail; 1121145147Srwatson#endif 1122145147Srwatson 112377183Srwatson if (((rgid != (gid_t)-1 && rgid != oldcred->cr_rgid && 112477183Srwatson rgid != oldcred->cr_svgid && 112577183Srwatson rgid != oldcred->cr_groups[0]) || 112677183Srwatson (egid != (gid_t)-1 && egid != oldcred->cr_rgid && 112777183Srwatson egid != oldcred->cr_svgid && 112877183Srwatson egid != oldcred->cr_groups[0]) || 112977183Srwatson (sgid != (gid_t)-1 && sgid != oldcred->cr_rgid && 113077183Srwatson sgid != oldcred->cr_svgid && 113177183Srwatson sgid != oldcred->cr_groups[0])) && 1132170587Srwatson (error = priv_check_cred(oldcred, PRIV_CRED_SETRESGID, 0)) != 0) 1133145147Srwatson goto fail; 113494619Sjhb 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 116556115Speter/* ARGSUSED */ 116656115Speterint 1167225617Skmacysys_getresuid(register struct thread *td, struct getresuid_args *uap) 116856115Speter{ 116982749Sdillon struct ucred *cred; 117056115Speter int error1 = 0, error2 = 0, error3 = 0; 117156115Speter 117293264Sdillon cred = td->td_ucred; 117356115Speter if (uap->ruid) 117499009Salfred error1 = copyout(&cred->cr_ruid, 117599009Salfred uap->ruid, sizeof(cred->cr_ruid)); 117656115Speter if (uap->euid) 117799009Salfred error2 = copyout(&cred->cr_uid, 117899009Salfred uap->euid, sizeof(cred->cr_uid)); 117956115Speter if (uap->suid) 118099009Salfred error3 = copyout(&cred->cr_svuid, 118199009Salfred uap->suid, sizeof(cred->cr_svuid)); 118287218Srwatson return (error1 ? error1 : error2 ? error2 : error3); 118356115Speter} 118456115Speter 118556115Speter#ifndef _SYS_SYSPROTO_H_ 118656115Speterstruct getresgid_args { 118756115Speter gid_t *rgid; 118856115Speter gid_t *egid; 118956115Speter gid_t *sgid; 119056115Speter}; 119156115Speter#endif 119256115Speter/* ARGSUSED */ 119356115Speterint 1194225617Skmacysys_getresgid(register struct thread *td, struct getresgid_args *uap) 119556115Speter{ 119682749Sdillon struct ucred *cred; 119756115Speter int error1 = 0, error2 = 0, error3 = 0; 119856115Speter 119993264Sdillon cred = td->td_ucred; 120056115Speter if (uap->rgid) 120199009Salfred error1 = copyout(&cred->cr_rgid, 120299009Salfred uap->rgid, sizeof(cred->cr_rgid)); 120356115Speter if (uap->egid) 120499009Salfred error2 = copyout(&cred->cr_groups[0], 120599009Salfred uap->egid, sizeof(cred->cr_groups[0])); 120656115Speter if (uap->sgid) 120799009Salfred error3 = copyout(&cred->cr_svgid, 120899009Salfred uap->sgid, sizeof(cred->cr_svgid)); 120987218Srwatson return (error1 ? error1 : error2 ? error2 : error3); 121056115Speter} 121156115Speter 121256115Speter#ifndef _SYS_SYSPROTO_H_ 121324453Speterstruct issetugid_args { 121424453Speter int dummy; 121524453Speter}; 121624453Speter#endif 121724453Speter/* ARGSUSED */ 121824453Speterint 1219225617Skmacysys_issetugid(register struct thread *td, struct issetugid_args *uap) 122024453Speter{ 122183366Sjulian struct proc *p = td->td_proc; 122283366Sjulian 122324453Speter /* 122424453Speter * Note: OpenBSD sets a P_SUGIDEXEC flag set at execve() time, 122524453Speter * we use P_SUGID because we consider changing the owners as 122624453Speter * "tainting" as well. 122724453Speter * This is significant for procs that start as root and "become" 122824453Speter * a user without an exec - programs cannot know *everything* 122924453Speter * that libc *might* have put in their data segment. 123024453Speter */ 123191140Stanimura PROC_LOCK(p); 123283366Sjulian td->td_retval[0] = (p->p_flag & P_SUGID) ? 1 : 0; 123391140Stanimura PROC_UNLOCK(p); 123424453Speter return (0); 123524453Speter} 123624453Speter 123775426Srwatsonint 1238225617Skmacysys___setugid(struct thread *td, struct __setugid_args *uap) 123975426Srwatson{ 124082749Sdillon#ifdef REGRESSION 124194619Sjhb struct proc *p; 124275426Srwatson 124394619Sjhb p = td->td_proc; 124475426Srwatson switch (uap->flag) { 124575426Srwatson case 0: 124694619Sjhb PROC_LOCK(p); 124794619Sjhb p->p_flag &= ~P_SUGID; 124894619Sjhb PROC_UNLOCK(p); 124994619Sjhb return (0); 125075426Srwatson case 1: 125194619Sjhb PROC_LOCK(p); 125294619Sjhb p->p_flag |= P_SUGID; 125394619Sjhb PROC_UNLOCK(p); 125494619Sjhb return (0); 125575426Srwatson default: 125694619Sjhb return (EINVAL); 125775426Srwatson } 125875426Srwatson#else /* !REGRESSION */ 125987218Srwatson 126075426Srwatson return (ENOSYS); 126187218Srwatson#endif /* REGRESSION */ 126275426Srwatson} 126375426Srwatson 12641541Srgrimes/* 12651541Srgrimes * Check if gid is a member of the group set. 12661541Srgrimes */ 12671549Srgrimesint 126893580Sjhbgroupmember(gid_t gid, struct ucred *cred) 12691541Srgrimes{ 1270194556Sbrooks int l; 1271194556Sbrooks int h; 1272194556Sbrooks int m; 12731541Srgrimes 1274194556Sbrooks if (cred->cr_groups[0] == gid) 1275194556Sbrooks return(1); 1276194556Sbrooks 1277194556Sbrooks /* 1278194556Sbrooks * If gid was not our primary group, perform a binary search 1279194556Sbrooks * of the supplemental groups. This is possible because we 1280194556Sbrooks * sort the groups in crsetgroups(). 1281194556Sbrooks */ 1282194556Sbrooks l = 1; 1283194556Sbrooks h = cred->cr_ngroups; 1284194556Sbrooks while (l < h) { 1285194556Sbrooks m = l + ((h - l) / 2); 1286194556Sbrooks if (cred->cr_groups[m] < gid) 1287194556Sbrooks l = m + 1; 1288194556Sbrooks else 1289194556Sbrooks h = m; 1290194556Sbrooks } 1291194556Sbrooks if ((l < cred->cr_ngroups) && (cred->cr_groups[l] == gid)) 1292194556Sbrooks return (1); 1293194556Sbrooks 12941541Srgrimes return (0); 12951541Srgrimes} 12961541Srgrimes 129782424Srwatson/* 129887218Srwatson * Test the active securelevel against a given level. securelevel_gt() 129987218Srwatson * implements (securelevel > level). securelevel_ge() implements 130087218Srwatson * (securelevel >= level). Note that the logic is inverted -- these 130187218Srwatson * functions return EPERM on "success" and 0 on "failure". 130283639Srwatson * 1303192895Sjamie * Due to care taken when setting the securelevel, we know that no jail will 1304192895Sjamie * be less secure that its parent (or the physical system), so it is sufficient 1305192895Sjamie * to test the current jail only. 1306192895Sjamie * 1307164032Srwatson * XXXRW: Possibly since this has to do with privilege, it should move to 1308164032Srwatson * kern_priv.c. 130983639Srwatson */ 131083639Srwatsonint 131183639Srwatsonsecurelevel_gt(struct ucred *cr, int level) 131283639Srwatson{ 131383639Srwatson 1314192895Sjamie return (cr->cr_prison->pr_securelevel > level ? EPERM : 0); 131583639Srwatson} 131683639Srwatson 131783639Srwatsonint 131883639Srwatsonsecurelevel_ge(struct ucred *cr, int level) 131983639Srwatson{ 132083639Srwatson 1321192895Sjamie return (cr->cr_prison->pr_securelevel >= level ? EPERM : 0); 132283639Srwatson} 132383639Srwatson 132484736Srwatson/* 132587144Srwatson * 'see_other_uids' determines whether or not visibility of processes 132687218Srwatson * and sockets with credentials holding different real uids is possible 132787138Srwatson * using a variety of system MIBs. 132887218Srwatson * XXX: data declarations should be together near the beginning of the file. 132984736Srwatson */ 133087144Srwatsonstatic int see_other_uids = 1; 133189414SarrSYSCTL_INT(_security_bsd, OID_AUTO, see_other_uids, CTLFLAG_RW, 133287218Srwatson &see_other_uids, 0, 133384736Srwatson "Unprivileged processes may see subjects/objects with different real uid"); 133484736Srwatson 1335210226Strasz/*- 133692923Srwatson * Determine if u1 "can see" the subject specified by u2, according to the 133792923Srwatson * 'see_other_uids' policy. 133892923Srwatson * Returns: 0 for permitted, ESRCH otherwise 133992923Srwatson * Locks: none 134092923Srwatson * References: *u1 and *u2 must not change during the call 134192923Srwatson * u1 may equal u2, in which case only one reference is required 134292923Srwatson */ 134392923Srwatsonstatic int 134492923Srwatsoncr_seeotheruids(struct ucred *u1, struct ucred *u2) 134592923Srwatson{ 134692923Srwatson 134792923Srwatson if (!see_other_uids && u1->cr_ruid != u2->cr_ruid) { 1348170587Srwatson if (priv_check_cred(u1, PRIV_SEEOTHERUIDS, 0) != 0) 134992923Srwatson return (ESRCH); 135092923Srwatson } 135192923Srwatson return (0); 135292923Srwatson} 135392923Srwatson 1354122869Srwatson/* 1355122869Srwatson * 'see_other_gids' determines whether or not visibility of processes 1356122869Srwatson * and sockets with credentials holding different real gids is possible 1357122869Srwatson * using a variety of system MIBs. 1358122869Srwatson * XXX: data declarations should be together near the beginning of the file. 1359122869Srwatson */ 1360122869Srwatsonstatic int see_other_gids = 1; 1361122869SrwatsonSYSCTL_INT(_security_bsd, OID_AUTO, see_other_gids, CTLFLAG_RW, 1362122869Srwatson &see_other_gids, 0, 1363122869Srwatson "Unprivileged processes may see subjects/objects with different real gid"); 1364122869Srwatson 1365122869Srwatson/* 1366122869Srwatson * Determine if u1 can "see" the subject specified by u2, according to the 1367122869Srwatson * 'see_other_gids' policy. 1368122869Srwatson * Returns: 0 for permitted, ESRCH otherwise 1369122869Srwatson * Locks: none 1370122869Srwatson * References: *u1 and *u2 must not change during the call 1371122869Srwatson * u1 may equal u2, in which case only one reference is required 1372122869Srwatson */ 1373122869Srwatsonstatic int 1374122869Srwatsoncr_seeothergids(struct ucred *u1, struct ucred *u2) 1375122869Srwatson{ 1376122869Srwatson int i, match; 1377122869Srwatson 1378122869Srwatson if (!see_other_gids) { 1379122869Srwatson match = 0; 1380122869Srwatson for (i = 0; i < u1->cr_ngroups; i++) { 1381122869Srwatson if (groupmember(u1->cr_groups[i], u2)) 1382122869Srwatson match = 1; 1383122869Srwatson if (match) 1384122869Srwatson break; 1385122869Srwatson } 1386122869Srwatson if (!match) { 1387170587Srwatson if (priv_check_cred(u1, PRIV_SEEOTHERGIDS, 0) != 0) 1388122869Srwatson return (ESRCH); 1389122869Srwatson } 1390122869Srwatson } 1391122869Srwatson return (0); 1392122869Srwatson} 1393122869Srwatson 1394210226Strasz/*- 139582466Srwatson * Determine if u1 "can see" the subject specified by u2. 139674956Srwatson * Returns: 0 for permitted, an errno value otherwise 139774956Srwatson * Locks: none 139887218Srwatson * References: *u1 and *u2 must not change during the call 139974956Srwatson * u1 may equal u2, in which case only one reference is required 140074956Srwatson */ 140174956Srwatsonint 140283742Srwatsoncr_cansee(struct ucred *u1, struct ucred *u2) 140365237Srwatson{ 140472786Srwatson int error; 140553518Sphk 140674956Srwatson if ((error = prison_check(u1, u2))) 140772786Srwatson return (error); 1408101003Srwatson#ifdef MAC 1409172930Srwatson if ((error = mac_cred_check_visible(u1, u2))) 1410101003Srwatson return (error); 1411101003Srwatson#endif 141292923Srwatson if ((error = cr_seeotheruids(u1, u2))) 141392923Srwatson return (error); 1414122869Srwatson if ((error = cr_seeothergids(u1, u2))) 1415122869Srwatson return (error); 141665237Srwatson return (0); 141765237Srwatson} 141865237Srwatson 1419210226Strasz/*- 142096886Sjhb * Determine if td "can see" the subject specified by p. 142182424Srwatson * Returns: 0 for permitted, an errno value otherwise 142296886Sjhb * Locks: Sufficient locks to protect p->p_ucred must be held. td really 142396886Sjhb * should be curthread. 142496886Sjhb * References: td and p must be valid for the lifetime of the call 142582424Srwatson */ 142679335Srwatsonint 142796886Sjhbp_cansee(struct thread *td, struct proc *p) 142874956Srwatson{ 142974956Srwatson 143083742Srwatson /* Wrap cr_cansee() for all functionality. */ 143196886Sjhb KASSERT(td == curthread, ("%s: td not curthread", __func__)); 143296886Sjhb PROC_LOCK_ASSERT(p, MA_OWNED); 143396886Sjhb return (cr_cansee(td->td_ucred, p->p_ucred)); 143474956Srwatson} 143574956Srwatson 1436120052Srwatson/* 1437120052Srwatson * 'conservative_signals' prevents the delivery of a broad class of 1438120052Srwatson * signals by unprivileged processes to processes that have changed their 1439120052Srwatson * credentials since the last invocation of execve(). This can prevent 1440120052Srwatson * the leakage of cached information or retained privileges as a result 1441120052Srwatson * of a common class of signal-related vulnerabilities. However, this 1442120052Srwatson * may interfere with some applications that expect to be able to 1443120052Srwatson * deliver these signals to peer processes after having given up 1444120052Srwatson * privilege. 1445120052Srwatson */ 1446120052Srwatsonstatic int conservative_signals = 1; 1447120052SrwatsonSYSCTL_INT(_security_bsd, OID_AUTO, conservative_signals, CTLFLAG_RW, 1448120052Srwatson &conservative_signals, 0, "Unprivileged processes prevented from " 1449120052Srwatson "sending certain signals to processes whose credentials have changed"); 1450210226Strasz/*- 145188943Srwatson * Determine whether cred may deliver the specified signal to proc. 145288943Srwatson * Returns: 0 for permitted, an errno value otherwise. 145388943Srwatson * Locks: A lock must be held for proc. 145488943Srwatson * References: cred and proc must be valid for the lifetime of the call. 145575437Srwatson */ 145675437Srwatsonint 1457141815Ssobomaxcr_cansignal(struct ucred *cred, struct proc *proc, int signum) 145853518Sphk{ 145982466Srwatson int error; 146084826Sjhb 146196886Sjhb PROC_LOCK_ASSERT(proc, MA_OWNED); 146275437Srwatson /* 146388943Srwatson * Jail semantics limit the scope of signalling to proc in the 146488943Srwatson * same jail as cred, if cred is in jail. 146575437Srwatson */ 146688943Srwatson error = prison_check(cred, proc->p_ucred); 146788943Srwatson if (error) 146872786Srwatson return (error); 1469101003Srwatson#ifdef MAC 1470172930Srwatson if ((error = mac_proc_check_signal(cred, proc, signum))) 1471101003Srwatson return (error); 1472101003Srwatson#endif 1473122869Srwatson if ((error = cr_seeotheruids(cred, proc->p_ucred))) 147492923Srwatson return (error); 1475122869Srwatson if ((error = cr_seeothergids(cred, proc->p_ucred))) 1476122869Srwatson return (error); 147765237Srwatson 147865237Srwatson /* 147982424Srwatson * UNIX signal semantics depend on the status of the P_SUGID 148082424Srwatson * bit on the target process. If the bit is set, then additional 148182424Srwatson * restrictions are placed on the set of available signals. 148275437Srwatson */ 1483141815Ssobomax if (conservative_signals && (proc->p_flag & P_SUGID)) { 148475437Srwatson switch (signum) { 148575437Srwatson case 0: 148675437Srwatson case SIGKILL: 148775437Srwatson case SIGINT: 148875437Srwatson case SIGTERM: 1489120052Srwatson case SIGALRM: 149075437Srwatson case SIGSTOP: 149175437Srwatson case SIGTTIN: 149275437Srwatson case SIGTTOU: 149375437Srwatson case SIGTSTP: 149475437Srwatson case SIGHUP: 149575437Srwatson case SIGUSR1: 149675437Srwatson case SIGUSR2: 149782466Srwatson /* 149882466Srwatson * Generally, permit job and terminal control 149982466Srwatson * signals. 150082466Srwatson */ 150175437Srwatson break; 150275437Srwatson default: 150388943Srwatson /* Not permitted without privilege. */ 1504170587Srwatson error = priv_check_cred(cred, PRIV_SIGNAL_SUGID, 0); 150575437Srwatson if (error) 150675437Srwatson return (error); 150775437Srwatson } 150865237Srwatson } 150965237Srwatson 151075480Srwatson /* 151182424Srwatson * Generally, the target credential's ruid or svuid must match the 151275480Srwatson * subject credential's ruid or euid. 151375480Srwatson */ 151488943Srwatson if (cred->cr_ruid != proc->p_ucred->cr_ruid && 151588943Srwatson cred->cr_ruid != proc->p_ucred->cr_svuid && 151688943Srwatson cred->cr_uid != proc->p_ucred->cr_ruid && 151788943Srwatson cred->cr_uid != proc->p_ucred->cr_svuid) { 1518170587Srwatson error = priv_check_cred(cred, PRIV_SIGNAL_DIFFCRED, 0); 151975480Srwatson if (error) 152075480Srwatson return (error); 152175480Srwatson } 152275480Srwatson 152387218Srwatson return (0); 152453518Sphk} 152553518Sphk 1526210226Strasz/*- 152796886Sjhb * Determine whether td may deliver the specified signal to p. 152888943Srwatson * Returns: 0 for permitted, an errno value otherwise 152996886Sjhb * Locks: Sufficient locks to protect various components of td and p 153096886Sjhb * must be held. td must be curthread, and a lock must be 153196886Sjhb * held for p. 153296886Sjhb * References: td and p must be valid for the lifetime of the call 153388943Srwatson */ 153488943Srwatsonint 1535141815Ssobomaxp_cansignal(struct thread *td, struct proc *p, int signum) 153688943Srwatson{ 153788943Srwatson 153896886Sjhb KASSERT(td == curthread, ("%s: td not curthread", __func__)); 153996886Sjhb PROC_LOCK_ASSERT(p, MA_OWNED); 154096886Sjhb if (td->td_proc == p) 154188943Srwatson return (0); 154288943Srwatson 154388943Srwatson /* 154488943Srwatson * UNIX signalling semantics require that processes in the same 154588943Srwatson * session always be able to deliver SIGCONT to one another, 154688943Srwatson * overriding the remaining protections. 154788943Srwatson */ 154896886Sjhb /* XXX: This will require an additional lock of some sort. */ 154996886Sjhb if (signum == SIGCONT && td->td_proc->p_session == p->p_session) 155088943Srwatson return (0); 1551143108Ssobomax /* 1552143800Ssobomax * Some compat layers use SIGTHR and higher signals for 1553143800Ssobomax * communication between different kernel threads of the same 1554143800Ssobomax * process, so that they expect that it's always possible to 1555143800Ssobomax * deliver them, even for suid applications where cr_cansignal() can 1556143108Ssobomax * deny such ability for security consideration. It should be 1557143108Ssobomax * pretty safe to do since the only way to create two processes 1558143108Ssobomax * with the same p_leader is via rfork(2). 1559143108Ssobomax */ 1560143805Ssobomax if (td->td_proc->p_leader != NULL && signum >= SIGTHR && 1561143805Ssobomax signum < SIGTHR + 4 && td->td_proc->p_leader == p->p_leader) 1562143108Ssobomax return (0); 156388943Srwatson 1564141815Ssobomax return (cr_cansignal(td->td_ucred, p, signum)); 156588943Srwatson} 156688943Srwatson 1567210226Strasz/*- 156896886Sjhb * Determine whether td may reschedule p. 156982466Srwatson * Returns: 0 for permitted, an errno value otherwise 157096886Sjhb * Locks: Sufficient locks to protect various components of td and p 157196886Sjhb * must be held. td must be curthread, and a lock must 157296886Sjhb * be held for p. 157396886Sjhb * References: td and p must be valid for the lifetime of the call 157482424Srwatson */ 157579335Srwatsonint 157696886Sjhbp_cansched(struct thread *td, struct proc *p) 157765237Srwatson{ 157872786Srwatson int error; 157965237Srwatson 158096886Sjhb KASSERT(td == curthread, ("%s: td not curthread", __func__)); 158196886Sjhb PROC_LOCK_ASSERT(p, MA_OWNED); 158296886Sjhb if (td->td_proc == p) 158365237Srwatson return (0); 158496886Sjhb if ((error = prison_check(td->td_ucred, p->p_ucred))) 158572786Srwatson return (error); 1586101003Srwatson#ifdef MAC 1587172930Srwatson if ((error = mac_proc_check_sched(td->td_ucred, p))) 1588101003Srwatson return (error); 1589101003Srwatson#endif 159096886Sjhb if ((error = cr_seeotheruids(td->td_ucred, p->p_ucred))) 159192923Srwatson return (error); 1592122869Srwatson if ((error = cr_seeothergids(td->td_ucred, p->p_ucred))) 1593122869Srwatson return (error); 1594164032Srwatson if (td->td_ucred->cr_ruid != p->p_ucred->cr_ruid && 1595164032Srwatson td->td_ucred->cr_uid != p->p_ucred->cr_ruid) { 1596170587Srwatson error = priv_check(td, PRIV_SCHED_DIFFCRED); 1597164032Srwatson if (error) 1598164032Srwatson return (error); 1599164032Srwatson } 1600164032Srwatson return (0); 160165237Srwatson} 160265237Srwatson 160382424Srwatson/* 160487280Srwatson * The 'unprivileged_proc_debug' flag may be used to disable a variety of 160587280Srwatson * unprivileged inter-process debugging services, including some procfs 160687280Srwatson * functionality, ptrace(), and ktrace(). In the past, inter-process 160787280Srwatson * debugging has been involved in a variety of security problems, and sites 160887280Srwatson * not requiring the service might choose to disable it when hardening 160987280Srwatson * systems. 161082424Srwatson * 161182424Srwatson * XXX: Should modifying and reading this variable require locking? 161287218Srwatson * XXX: data declarations should be together near the beginning of the file. 161382424Srwatson */ 161487144Srwatsonstatic int unprivileged_proc_debug = 1; 161589414SarrSYSCTL_INT(_security_bsd, OID_AUTO, unprivileged_proc_debug, CTLFLAG_RW, 161687218Srwatson &unprivileged_proc_debug, 0, 161780735Srwatson "Unprivileged processes may use process debugging facilities"); 161880735Srwatson 1619210226Strasz/*- 162096886Sjhb * Determine whether td may debug p. 162182466Srwatson * Returns: 0 for permitted, an errno value otherwise 162296886Sjhb * Locks: Sufficient locks to protect various components of td and p 162396886Sjhb * must be held. td must be curthread, and a lock must 162496886Sjhb * be held for p. 162596886Sjhb * References: td and p must be valid for the lifetime of the call 162682424Srwatson */ 162779335Srwatsonint 162896886Sjhbp_candebug(struct thread *td, struct proc *p) 162965237Srwatson{ 163087218Srwatson int credentialchanged, error, grpsubset, i, uidsubset; 163165237Srwatson 163296886Sjhb KASSERT(td == curthread, ("%s: td not curthread", __func__)); 163396886Sjhb PROC_LOCK_ASSERT(p, MA_OWNED); 163487144Srwatson if (!unprivileged_proc_debug) { 1635170587Srwatson error = priv_check(td, PRIV_DEBUG_UNPRIV); 163684727Srwatson if (error) 163784727Srwatson return (error); 163884727Srwatson } 163996886Sjhb if (td->td_proc == p) 164084636Sdes return (0); 164196886Sjhb if ((error = prison_check(td->td_ucred, p->p_ucred))) 164272786Srwatson return (error); 1643101003Srwatson#ifdef MAC 1644172930Srwatson if ((error = mac_proc_check_debug(td->td_ucred, p))) 1645101003Srwatson return (error); 1646101003Srwatson#endif 164796886Sjhb if ((error = cr_seeotheruids(td->td_ucred, p->p_ucred))) 164892923Srwatson return (error); 1649122869Srwatson if ((error = cr_seeothergids(td->td_ucred, p->p_ucred))) 1650122869Srwatson return (error); 165165237Srwatson 165282466Srwatson /* 165396886Sjhb * Is p's group set a subset of td's effective group set? This 165496886Sjhb * includes p's egid, group access list, rgid, and svgid. 165582466Srwatson */ 165685895Srwatson grpsubset = 1; 165796886Sjhb for (i = 0; i < p->p_ucred->cr_ngroups; i++) { 165896886Sjhb if (!groupmember(p->p_ucred->cr_groups[i], td->td_ucred)) { 165985895Srwatson grpsubset = 0; 166085895Srwatson break; 166185895Srwatson } 166285895Srwatson } 166385895Srwatson grpsubset = grpsubset && 166496886Sjhb groupmember(p->p_ucred->cr_rgid, td->td_ucred) && 166596886Sjhb groupmember(p->p_ucred->cr_svgid, td->td_ucred); 166685895Srwatson 166785895Srwatson /* 166896886Sjhb * Are the uids present in p's credential equal to td's 166996886Sjhb * effective uid? This includes p's euid, svuid, and ruid. 167085895Srwatson */ 167196886Sjhb uidsubset = (td->td_ucred->cr_uid == p->p_ucred->cr_uid && 167296886Sjhb td->td_ucred->cr_uid == p->p_ucred->cr_svuid && 167396886Sjhb td->td_ucred->cr_uid == p->p_ucred->cr_ruid); 167485895Srwatson 167585895Srwatson /* 167685895Srwatson * Has the credential of the process changed since the last exec()? 167785895Srwatson */ 167896886Sjhb credentialchanged = (p->p_flag & P_SUGID); 167985895Srwatson 168085895Srwatson /* 168196886Sjhb * If p's gids aren't a subset, or the uids aren't a subset, 168285895Srwatson * or the credential has changed, require appropriate privilege 1683164032Srwatson * for td to debug p. 168485895Srwatson */ 1685164032Srwatson if (!grpsubset || !uidsubset) { 1686170587Srwatson error = priv_check(td, PRIV_DEBUG_DIFFCRED); 168784727Srwatson if (error) 168865237Srwatson return (error); 168982466Srwatson } 169065237Srwatson 1691164032Srwatson if (credentialchanged) { 1692170587Srwatson error = priv_check(td, PRIV_DEBUG_SUGID); 1693164032Srwatson if (error) 1694164032Srwatson return (error); 1695164032Srwatson } 1696164032Srwatson 169787218Srwatson /* Can't trace init when securelevel > 0. */ 169896886Sjhb if (p == initproc) { 169996886Sjhb error = securelevel_gt(td->td_ucred, 0); 170083639Srwatson if (error) 170183639Srwatson return (error); 170283639Srwatson } 170365237Srwatson 170485880Srwatson /* 170585880Srwatson * Can't trace a process that's currently exec'ing. 1706164032Srwatson * 170785880Srwatson * XXX: Note, this is not a security policy decision, it's a 170885880Srwatson * basic correctness/functionality decision. Therefore, this check 170985880Srwatson * should be moved to the caller's of p_candebug(). 171085880Srwatson */ 171196886Sjhb if ((p->p_flag & P_INEXEC) != 0) 1712185983Skib return (EBUSY); 171387466Srwatson 171465237Srwatson return (0); 171565237Srwatson} 171665237Srwatson 1717210226Strasz/*- 171892976Srwatson * Determine whether the subject represented by cred can "see" a socket. 171992976Srwatson * Returns: 0 for permitted, ENOENT otherwise. 172092976Srwatson */ 172192976Srwatsonint 172292976Srwatsoncr_canseesocket(struct ucred *cred, struct socket *so) 172392976Srwatson{ 172492976Srwatson int error; 172592976Srwatson 172692976Srwatson error = prison_check(cred, so->so_cred); 172792976Srwatson if (error) 172892976Srwatson return (ENOENT); 1729101003Srwatson#ifdef MAC 1730172930Srwatson error = mac_socket_check_visible(cred, so); 1731101003Srwatson if (error) 1732101003Srwatson return (error); 1733101003Srwatson#endif 173492976Srwatson if (cr_seeotheruids(cred, so->so_cred)) 173592976Srwatson return (ENOENT); 1736122869Srwatson if (cr_seeothergids(cred, so->so_cred)) 1737122869Srwatson return (ENOENT); 173892976Srwatson 173992976Srwatson return (0); 174092976Srwatson} 174192976Srwatson 1742183982Sbz#if defined(INET) || defined(INET6) 1743210226Strasz/*- 1744183982Sbz * Determine whether the subject represented by cred can "see" a socket. 1745183982Sbz * Returns: 0 for permitted, ENOENT otherwise. 1746183982Sbz */ 1747183982Sbzint 1748183982Sbzcr_canseeinpcb(struct ucred *cred, struct inpcb *inp) 1749183982Sbz{ 1750183982Sbz int error; 1751183982Sbz 1752183982Sbz error = prison_check(cred, inp->inp_cred); 1753183982Sbz if (error) 1754183982Sbz return (ENOENT); 1755183982Sbz#ifdef MAC 1756183982Sbz INP_LOCK_ASSERT(inp); 1757183982Sbz error = mac_inpcb_check_visible(cred, inp); 1758183982Sbz if (error) 1759183982Sbz return (error); 1760183982Sbz#endif 1761183982Sbz if (cr_seeotheruids(cred, inp->inp_cred)) 1762183982Sbz return (ENOENT); 1763183982Sbz if (cr_seeothergids(cred, inp->inp_cred)) 1764183982Sbz return (ENOENT); 1765183982Sbz 1766183982Sbz return (0); 1767183982Sbz} 1768183982Sbz#endif 1769183982Sbz 1770210226Strasz/*- 1771145234Srwatson * Determine whether td can wait for the exit of p. 1772145234Srwatson * Returns: 0 for permitted, an errno value otherwise 1773145234Srwatson * Locks: Sufficient locks to protect various components of td and p 1774145234Srwatson * must be held. td must be curthread, and a lock must 1775145234Srwatson * be held for p. 1776145234Srwatson * References: td and p must be valid for the lifetime of the call 1777145234Srwatson 1778145234Srwatson */ 1779145234Srwatsonint 1780145234Srwatsonp_canwait(struct thread *td, struct proc *p) 1781145234Srwatson{ 1782145234Srwatson int error; 1783145234Srwatson 1784145234Srwatson KASSERT(td == curthread, ("%s: td not curthread", __func__)); 1785145234Srwatson PROC_LOCK_ASSERT(p, MA_OWNED); 1786195741Sjamie if ((error = prison_check(td->td_ucred, p->p_ucred))) 1787145234Srwatson return (error); 1788145234Srwatson#ifdef MAC 1789172930Srwatson if ((error = mac_proc_check_wait(td->td_ucred, p))) 1790145234Srwatson return (error); 1791145234Srwatson#endif 1792145234Srwatson#if 0 1793145234Srwatson /* XXXMAC: This could have odd effects on some shells. */ 1794145234Srwatson if ((error = cr_seeotheruids(td->td_ucred, p->p_ucred))) 1795145234Srwatson return (error); 1796145234Srwatson#endif 1797145234Srwatson 1798145234Srwatson return (0); 1799145234Srwatson} 1800145234Srwatson 180153518Sphk/* 18021541Srgrimes * Allocate a zeroed cred structure. 18031541Srgrimes */ 18041541Srgrimesstruct ucred * 180593580Sjhbcrget(void) 18061541Srgrimes{ 18071541Srgrimes register struct ucred *cr; 18081541Srgrimes 1809184205Sdes cr = malloc(sizeof(*cr), M_CRED, M_WAITOK | M_ZERO); 1810150634Sjhb refcount_init(&cr->cr_ref, 1); 1811170407Srwatson#ifdef AUDIT 1812170407Srwatson audit_cred_init(cr); 1813170407Srwatson#endif 1814101001Srwatson#ifdef MAC 1815172930Srwatson mac_cred_init(cr); 1816101001Srwatson#endif 1817194498Sbrooks crextend(cr, XU_NGROUPS); 18181541Srgrimes return (cr); 18191541Srgrimes} 18201541Srgrimes 18211541Srgrimes/* 182282466Srwatson * Claim another reference to a ucred structure. 182369401Salfred */ 182484827Sjhbstruct ucred * 182593580Sjhbcrhold(struct ucred *cr) 182669401Salfred{ 182769401Salfred 1828150634Sjhb refcount_acquire(&cr->cr_ref); 182984827Sjhb return (cr); 183069401Salfred} 183169401Salfred 183269401Salfred/* 1833167211Srwatson * Free a cred structure. Throws away space when ref count gets to 0. 18341541Srgrimes */ 18351549Srgrimesvoid 183693580Sjhbcrfree(struct ucred *cr) 18371541Srgrimes{ 183869239Salfred 183975632Salfred KASSERT(cr->cr_ref > 0, ("bad ucred refcount: %d", cr->cr_ref)); 1840150634Sjhb KASSERT(cr->cr_ref != 0xdeadc0de, ("dangling reference to ucred")); 1841150634Sjhb if (refcount_release(&cr->cr_ref)) { 184265495Struckman /* 184365495Struckman * Some callers of crget(), such as nfs_statfs(), 184465495Struckman * allocate a temporary credential, but don't 184565495Struckman * allocate a uidinfo structure. 184665495Struckman */ 184765495Struckman if (cr->cr_uidinfo != NULL) 184865495Struckman uifree(cr->cr_uidinfo); 184977277Srwatson if (cr->cr_ruidinfo != NULL) 185077277Srwatson uifree(cr->cr_ruidinfo); 185172786Srwatson /* 185272786Srwatson * Free a prison, if any. 185372786Srwatson */ 1854192895Sjamie if (cr->cr_prison != NULL) 185572786Srwatson prison_free(cr->cr_prison); 1856219304Strasz if (cr->cr_loginclass != NULL) 1857219304Strasz loginclass_free(cr->cr_loginclass); 1858170407Srwatson#ifdef AUDIT 1859170407Srwatson audit_cred_destroy(cr); 1860170407Srwatson#endif 1861101001Srwatson#ifdef MAC 1862172930Srwatson mac_cred_destroy(cr); 1863101001Srwatson#endif 1864194498Sbrooks free(cr->cr_groups, M_CRED); 1865184205Sdes free(cr, M_CRED); 186690756Sdillon } 18671541Srgrimes} 18681541Srgrimes 18691541Srgrimes/* 187084827Sjhb * Check to see if this ucred is shared. 18711541Srgrimes */ 187284827Sjhbint 187393580Sjhbcrshared(struct ucred *cr) 18741541Srgrimes{ 18751541Srgrimes 1876150634Sjhb return (cr->cr_ref > 1); 18771541Srgrimes} 18781541Srgrimes 18791541Srgrimes/* 188084827Sjhb * Copy a ucred's contents from a template. Does not block. 188184827Sjhb */ 188284827Sjhbvoid 188393580Sjhbcrcopy(struct ucred *dest, struct ucred *src) 188484827Sjhb{ 188584827Sjhb 188684827Sjhb KASSERT(crshared(dest) == 0, ("crcopy of shared ucred")); 188784827Sjhb bcopy(&src->cr_startcopy, &dest->cr_startcopy, 188887218Srwatson (unsigned)((caddr_t)&src->cr_endcopy - 188984827Sjhb (caddr_t)&src->cr_startcopy)); 1890194498Sbrooks crsetgroups(dest, src->cr_ngroups, src->cr_groups); 189184827Sjhb uihold(dest->cr_uidinfo); 189284827Sjhb uihold(dest->cr_ruidinfo); 1893192895Sjamie prison_hold(dest->cr_prison); 1894219304Strasz loginclass_hold(dest->cr_loginclass); 1895170407Srwatson#ifdef AUDIT 1896170407Srwatson audit_cred_copy(src, dest); 1897170407Srwatson#endif 1898101001Srwatson#ifdef MAC 1899172930Srwatson mac_cred_copy(src, dest); 1900101001Srwatson#endif 190184827Sjhb} 190284827Sjhb 190384827Sjhb/* 19041541Srgrimes * Dup cred struct to a new held one. 19051541Srgrimes */ 19061541Srgrimesstruct ucred * 190793580Sjhbcrdup(struct ucred *cr) 19081541Srgrimes{ 19091541Srgrimes struct ucred *newcr; 19101541Srgrimes 191184827Sjhb newcr = crget(); 191284827Sjhb crcopy(newcr, cr); 19131541Srgrimes return (newcr); 19141541Srgrimes} 19151541Srgrimes 19161541Srgrimes/* 191791354Sdd * Fill in a struct xucred based on a struct ucred. 191891354Sdd */ 191991354Sddvoid 192093580Sjhbcru2x(struct ucred *cr, struct xucred *xcr) 192191354Sdd{ 1922194498Sbrooks int ngroups; 192391354Sdd 192491354Sdd bzero(xcr, sizeof(*xcr)); 192591354Sdd xcr->cr_version = XUCRED_VERSION; 192691354Sdd xcr->cr_uid = cr->cr_uid; 1927194498Sbrooks 1928194498Sbrooks ngroups = MIN(cr->cr_ngroups, XU_NGROUPS); 1929194498Sbrooks xcr->cr_ngroups = ngroups; 1930194498Sbrooks bcopy(cr->cr_groups, xcr->cr_groups, 1931194498Sbrooks ngroups * sizeof(*cr->cr_groups)); 193291354Sdd} 193391354Sdd 193491354Sdd/* 1935167211Srwatson * small routine to swap a thread's current ucred for the correct one taken 1936167211Srwatson * from the process. 193790748Sjulian */ 193890748Sjulianvoid 193990748Sjuliancred_update_thread(struct thread *td) 194090748Sjulian{ 194190748Sjulian struct proc *p; 194291405Sjhb struct ucred *cred; 194390748Sjulian 194490748Sjulian p = td->td_proc; 194591405Sjhb cred = td->td_ucred; 194690748Sjulian PROC_LOCK(p); 194790748Sjulian td->td_ucred = crhold(p->p_ucred); 194890748Sjulian PROC_UNLOCK(p); 194991405Sjhb if (cred != NULL) 195091405Sjhb crfree(cred); 195190748Sjulian} 195290748Sjulian 1953194498Sbrooksstruct ucred * 1954194498Sbrookscrcopysafe(struct proc *p, struct ucred *cr) 1955194498Sbrooks{ 1956194498Sbrooks struct ucred *oldcred; 1957194498Sbrooks int groups; 1958194498Sbrooks 1959194498Sbrooks PROC_LOCK_ASSERT(p, MA_OWNED); 1960194498Sbrooks 1961194498Sbrooks oldcred = p->p_ucred; 1962194498Sbrooks while (cr->cr_agroups < oldcred->cr_agroups) { 1963194498Sbrooks groups = oldcred->cr_agroups; 1964194498Sbrooks PROC_UNLOCK(p); 1965194498Sbrooks crextend(cr, groups); 1966194498Sbrooks PROC_LOCK(p); 1967194498Sbrooks oldcred = p->p_ucred; 1968194498Sbrooks } 1969194498Sbrooks crcopy(cr, oldcred); 1970194498Sbrooks 1971194498Sbrooks return (oldcred); 1972194498Sbrooks} 1973194498Sbrooks 197490748Sjulian/* 1975194498Sbrooks * Extend the passed in credential to hold n items. 1976194498Sbrooks */ 1977194498Sbrooksstatic void 1978194498Sbrookscrextend(struct ucred *cr, int n) 1979194498Sbrooks{ 1980194498Sbrooks int cnt; 1981194498Sbrooks 1982194498Sbrooks /* Truncate? */ 1983194498Sbrooks if (n <= cr->cr_agroups) 1984194498Sbrooks return; 1985194498Sbrooks 1986194498Sbrooks /* 1987194498Sbrooks * We extend by 2 each time since we're using a power of two 1988194498Sbrooks * allocator until we need enough groups to fill a page. 1989194498Sbrooks * Once we're allocating multiple pages, only allocate as many 1990194498Sbrooks * as we actually need. The case of processes needing a 1991194498Sbrooks * non-power of two number of pages seems more likely than 1992194498Sbrooks * a real world process that adds thousands of groups one at a 1993194498Sbrooks * time. 1994194498Sbrooks */ 1995194498Sbrooks if ( n < PAGE_SIZE / sizeof(gid_t) ) { 1996194498Sbrooks if (cr->cr_agroups == 0) 1997194498Sbrooks cnt = MINALLOCSIZE / sizeof(gid_t); 1998194498Sbrooks else 1999194498Sbrooks cnt = cr->cr_agroups * 2; 2000194498Sbrooks 2001194498Sbrooks while (cnt < n) 2002194498Sbrooks cnt *= 2; 2003194498Sbrooks } else 2004194498Sbrooks cnt = roundup2(n, PAGE_SIZE / sizeof(gid_t)); 2005194498Sbrooks 2006194498Sbrooks /* Free the old array. */ 2007194498Sbrooks if (cr->cr_groups) 2008194498Sbrooks free(cr->cr_groups, M_CRED); 2009194498Sbrooks 2010194498Sbrooks cr->cr_groups = malloc(cnt * sizeof(gid_t), M_CRED, M_WAITOK | M_ZERO); 2011194498Sbrooks cr->cr_agroups = cnt; 2012194498Sbrooks} 2013194498Sbrooks 2014194498Sbrooks/* 2015194556Sbrooks * Copy groups in to a credential, preserving any necessary invariants. 2016194556Sbrooks * Currently this includes the sorting of all supplemental gids. 2017194556Sbrooks * crextend() must have been called before hand to ensure sufficient 2018194556Sbrooks * space is available. 2019194498Sbrooks */ 2020194498Sbrooksstatic void 2021194498Sbrookscrsetgroups_locked(struct ucred *cr, int ngrp, gid_t *groups) 2022194498Sbrooks{ 2023194556Sbrooks int i; 2024194556Sbrooks int j; 2025194556Sbrooks gid_t g; 2026194498Sbrooks 2027194498Sbrooks KASSERT(cr->cr_agroups >= ngrp, ("cr_ngroups is too small")); 2028194498Sbrooks 2029194498Sbrooks bcopy(groups, cr->cr_groups, ngrp * sizeof(gid_t)); 2030194498Sbrooks cr->cr_ngroups = ngrp; 2031194556Sbrooks 2032194556Sbrooks /* 2033194556Sbrooks * Sort all groups except cr_groups[0] to allow groupmember to 2034194556Sbrooks * perform a binary search. 2035194556Sbrooks * 2036194556Sbrooks * XXX: If large numbers of groups become common this should 2037194556Sbrooks * be replaced with shell sort like linux uses or possibly 2038194556Sbrooks * heap sort. 2039194556Sbrooks */ 2040194556Sbrooks for (i = 2; i < ngrp; i++) { 2041194556Sbrooks g = cr->cr_groups[i]; 2042194556Sbrooks for (j = i-1; j >= 1 && g < cr->cr_groups[j]; j--) 2043194556Sbrooks cr->cr_groups[j + 1] = cr->cr_groups[j]; 2044194556Sbrooks cr->cr_groups[j + 1] = g; 2045194556Sbrooks } 2046194498Sbrooks} 2047194498Sbrooks 2048194498Sbrooks/* 2049194498Sbrooks * Copy groups in to a credential after expanding it if required. 2050202143Sbrooks * Truncate the list to (ngroups_max + 1) if it is too large. 2051194498Sbrooks */ 2052194498Sbrooksvoid 2053194498Sbrookscrsetgroups(struct ucred *cr, int ngrp, gid_t *groups) 2054194498Sbrooks{ 2055194498Sbrooks 2056202143Sbrooks if (ngrp > ngroups_max + 1) 2057202143Sbrooks ngrp = ngroups_max + 1; 2058194498Sbrooks 2059194498Sbrooks crextend(cr, ngrp); 2060194498Sbrooks crsetgroups_locked(cr, ngrp, groups); 2061194498Sbrooks} 2062194498Sbrooks 2063194498Sbrooks/* 20641541Srgrimes * Get login name, if available. 20651541Srgrimes */ 206612221Sbde#ifndef _SYS_SYSPROTO_H_ 20671541Srgrimesstruct getlogin_args { 20681541Srgrimes char *namebuf; 20691541Srgrimes u_int namelen; 20701541Srgrimes}; 207112221Sbde#endif 20721541Srgrimes/* ARGSUSED */ 20731549Srgrimesint 2074225617Skmacysys_getlogin(struct thread *td, struct getlogin_args *uap) 20751541Srgrimes{ 207682749Sdillon int error; 207791140Stanimura char login[MAXLOGNAME]; 207883366Sjulian struct proc *p = td->td_proc; 20791541Srgrimes 208023358Sache if (uap->namelen > MAXLOGNAME) 208123359Sache uap->namelen = MAXLOGNAME; 208291140Stanimura PROC_LOCK(p); 208391140Stanimura SESS_LOCK(p->p_session); 208491140Stanimura bcopy(p->p_session->s_login, login, uap->namelen); 208591140Stanimura SESS_UNLOCK(p->p_session); 208691140Stanimura PROC_UNLOCK(p); 208799009Salfred error = copyout(login, uap->namebuf, uap->namelen); 208882749Sdillon return(error); 20891541Srgrimes} 20901541Srgrimes 20911541Srgrimes/* 20921541Srgrimes * Set login name. 20931541Srgrimes */ 209412221Sbde#ifndef _SYS_SYSPROTO_H_ 20951541Srgrimesstruct setlogin_args { 20961541Srgrimes char *namebuf; 20971541Srgrimes}; 209812221Sbde#endif 20991541Srgrimes/* ARGSUSED */ 21001549Srgrimesint 2101225617Skmacysys_setlogin(struct thread *td, struct setlogin_args *uap) 21021541Srgrimes{ 210383366Sjulian struct proc *p = td->td_proc; 21041541Srgrimes int error; 210523330Sache char logintmp[MAXLOGNAME]; 21061541Srgrimes 2107170587Srwatson error = priv_check(td, PRIV_PROC_SETLOGIN); 210894619Sjhb if (error) 210994619Sjhb return (error); 211099009Salfred error = copyinstr(uap->namebuf, logintmp, sizeof(logintmp), NULL); 211187218Srwatson if (error == ENAMETOOLONG) 21121541Srgrimes error = EINVAL; 211391140Stanimura else if (!error) { 211491140Stanimura PROC_LOCK(p); 211591140Stanimura SESS_LOCK(p->p_session); 211691140Stanimura (void) memcpy(p->p_session->s_login, logintmp, 211723330Sache sizeof(logintmp)); 211891140Stanimura SESS_UNLOCK(p->p_session); 211991140Stanimura PROC_UNLOCK(p); 212091140Stanimura } 21211541Srgrimes return (error); 21221541Srgrimes} 212331891Ssef 212431891Ssefvoid 212593580Sjhbsetsugid(struct proc *p) 212631891Ssef{ 212798403Salfred 212898403Salfred PROC_LOCK_ASSERT(p, MA_OWNED); 212931891Ssef p->p_flag |= P_SUGID; 213055707Ssef if (!(p->p_pfsflags & PF_ISUGID)) 213131891Ssef p->p_stops = 0; 213231891Ssef} 213365495Struckman 2134210226Strasz/*- 213582466Srwatson * Change a process's effective uid. 213677183Srwatson * Side effects: newcred->cr_uid and newcred->cr_uidinfo will be modified. 213777183Srwatson * References: newcred must be an exclusive credential reference for the 213877183Srwatson * duration of the call. 213965495Struckman */ 214065495Struckmanvoid 214198417Salfredchange_euid(struct ucred *newcred, struct uidinfo *euip) 214265495Struckman{ 214365495Struckman 214498417Salfred newcred->cr_uid = euip->ui_uid; 214598417Salfred uihold(euip); 214677183Srwatson uifree(newcred->cr_uidinfo); 214798417Salfred newcred->cr_uidinfo = euip; 214865495Struckman} 214965495Struckman 2150210226Strasz/*- 215182466Srwatson * Change a process's effective gid. 215277183Srwatson * Side effects: newcred->cr_gid will be modified. 215377183Srwatson * References: newcred must be an exclusive credential reference for the 215477183Srwatson * duration of the call. 215565495Struckman */ 215667629Sgallatinvoid 215793580Sjhbchange_egid(struct ucred *newcred, gid_t egid) 215865495Struckman{ 215965495Struckman 216077183Srwatson newcred->cr_groups[0] = egid; 216165495Struckman} 216277183Srwatson 2163210226Strasz/*- 216482466Srwatson * Change a process's real uid. 216577183Srwatson * Side effects: newcred->cr_ruid will be updated, newcred->cr_ruidinfo 216677183Srwatson * will be updated, and the old and new cr_ruidinfo proc 216777183Srwatson * counts will be updated. 216877183Srwatson * References: newcred must be an exclusive credential reference for the 216977183Srwatson * duration of the call. 217077183Srwatson */ 217177183Srwatsonvoid 217298417Salfredchange_ruid(struct ucred *newcred, struct uidinfo *ruip) 217377183Srwatson{ 217477183Srwatson 217577183Srwatson (void)chgproccnt(newcred->cr_ruidinfo, -1, 0); 217698417Salfred newcred->cr_ruid = ruip->ui_uid; 217798417Salfred uihold(ruip); 217877183Srwatson uifree(newcred->cr_ruidinfo); 217998417Salfred newcred->cr_ruidinfo = ruip; 218077183Srwatson (void)chgproccnt(newcred->cr_ruidinfo, 1, 0); 218177183Srwatson} 218277183Srwatson 2183210226Strasz/*- 218482466Srwatson * Change a process's real gid. 218577183Srwatson * Side effects: newcred->cr_rgid will be updated. 218677183Srwatson * References: newcred must be an exclusive credential reference for the 218777183Srwatson * duration of the call. 218877183Srwatson */ 218977183Srwatsonvoid 219093580Sjhbchange_rgid(struct ucred *newcred, gid_t rgid) 219177183Srwatson{ 219277183Srwatson 219377183Srwatson newcred->cr_rgid = rgid; 219477183Srwatson} 219577183Srwatson 2196210226Strasz/*- 219782466Srwatson * Change a process's saved uid. 219877183Srwatson * Side effects: newcred->cr_svuid will be updated. 219977183Srwatson * References: newcred must be an exclusive credential reference for the 220077183Srwatson * duration of the call. 220177183Srwatson */ 220277183Srwatsonvoid 220393580Sjhbchange_svuid(struct ucred *newcred, uid_t svuid) 220477183Srwatson{ 220577183Srwatson 220677183Srwatson newcred->cr_svuid = svuid; 220777183Srwatson} 220877183Srwatson 2209210226Strasz/*- 221082466Srwatson * Change a process's saved gid. 221177183Srwatson * Side effects: newcred->cr_svgid will be updated. 221277183Srwatson * References: newcred must be an exclusive credential reference for the 221377183Srwatson * duration of the call. 221477183Srwatson */ 221577183Srwatsonvoid 221693580Sjhbchange_svgid(struct ucred *newcred, gid_t svgid) 221777183Srwatson{ 221877183Srwatson 221977183Srwatson newcred->cr_svgid = svgid; 222077183Srwatson} 2221