1df8bae1dSRodney W. Grimes /* 2df8bae1dSRodney W. Grimes * Copyright (c) 1982, 1986, 1989, 1990, 1991, 1993 3df8bae1dSRodney W. Grimes * The Regents of the University of California. All rights reserved. 4df8bae1dSRodney W. Grimes * (c) UNIX System Laboratories, Inc. 5df8bae1dSRodney W. Grimes * All or some portions of this file are derived from material licensed 6df8bae1dSRodney W. Grimes * to the University of California by American Telephone and Telegraph 7df8bae1dSRodney W. Grimes * Co. or Unix System Laboratories, Inc. and are reproduced herein with 8df8bae1dSRodney W. Grimes * the permission of UNIX System Laboratories, Inc. 9eb725b4eSRobert Watson * Copyright (c) 2000-2001 Robert N. M. Watson. All rights reserved. 10df8bae1dSRodney W. Grimes * 11df8bae1dSRodney W. Grimes * Redistribution and use in source and binary forms, with or without 12df8bae1dSRodney W. Grimes * modification, are permitted provided that the following conditions 13df8bae1dSRodney W. Grimes * are met: 14df8bae1dSRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 15df8bae1dSRodney W. Grimes * notice, this list of conditions and the following disclaimer. 16df8bae1dSRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 17df8bae1dSRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 18df8bae1dSRodney W. Grimes * documentation and/or other materials provided with the distribution. 19df8bae1dSRodney W. Grimes * 3. All advertising materials mentioning features or use of this software 20df8bae1dSRodney W. Grimes * must display the following acknowledgement: 21df8bae1dSRodney W. Grimes * This product includes software developed by the University of 22df8bae1dSRodney W. Grimes * California, Berkeley and its contributors. 23df8bae1dSRodney W. Grimes * 4. Neither the name of the University nor the names of its contributors 24df8bae1dSRodney W. Grimes * may be used to endorse or promote products derived from this software 25df8bae1dSRodney W. Grimes * without specific prior written permission. 26df8bae1dSRodney W. Grimes * 27df8bae1dSRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 28df8bae1dSRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 29df8bae1dSRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 30df8bae1dSRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 31df8bae1dSRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 32df8bae1dSRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 33df8bae1dSRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 34df8bae1dSRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 35df8bae1dSRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 36df8bae1dSRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 37df8bae1dSRodney W. Grimes * SUCH DAMAGE. 38df8bae1dSRodney W. Grimes * 39df8bae1dSRodney W. Grimes * @(#)kern_prot.c 8.6 (Berkeley) 1/21/94 40c3aac50fSPeter Wemm * $FreeBSD$ 41df8bae1dSRodney W. Grimes */ 42df8bae1dSRodney W. Grimes 43df8bae1dSRodney W. Grimes /* 44df8bae1dSRodney W. Grimes * System calls related to processes and protection 45df8bae1dSRodney W. Grimes */ 46df8bae1dSRodney W. Grimes 475591b823SEivind Eklund #include "opt_compat.h" 485591b823SEivind Eklund 49df8bae1dSRodney W. Grimes #include <sys/param.h> 50df8bae1dSRodney W. Grimes #include <sys/systm.h> 51fb919e4dSMark Murray #include <sys/acct.h> 521c5bb3eaSPeter Wemm #include <sys/kernel.h> 5398f03f90SJake Burkholder #include <sys/lock.h> 54f591779bSSeigo Tanimura #include <sys/malloc.h> 55fb919e4dSMark Murray #include <sys/mutex.h> 565b29d6e9SJohn Baldwin #include <sys/sx.h> 57f591779bSSeigo Tanimura #include <sys/proc.h> 58fb919e4dSMark Murray #include <sys/sysproto.h> 59eb725b4eSRobert Watson #include <sys/jail.h> 60d5f81602SSean Eric Fagan #include <sys/pioctl.h> 61f535380cSDon Lewis #include <sys/resourcevar.h> 6229dc1288SRobert Watson #include <sys/socket.h> 6329dc1288SRobert Watson #include <sys/socketvar.h> 64579f4eb4SRobert Watson #include <sys/sysctl.h> 65df8bae1dSRodney W. Grimes 66a1c995b6SPoul-Henning Kamp static MALLOC_DEFINE(M_CRED, "cred", "credentials"); 67a1c995b6SPoul-Henning Kamp 68d0615c64SAndrew R. Reiter SYSCTL_DECL(_security); 69d0615c64SAndrew R. Reiter SYSCTL_NODE(_security, OID_AUTO, bsd, CTLFLAG_RW, 0, 7048713bdcSRobert Watson "BSD security policy"); 7148713bdcSRobert Watson 72d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 73ad7507e2SSteven Wallace struct getpid_args { 74df8bae1dSRodney W. Grimes int dummy; 75df8bae1dSRodney W. Grimes }; 76d2d3e875SBruce Evans #endif 77835a82eeSMatthew Dillon /* 78835a82eeSMatthew Dillon * MPSAFE 79835a82eeSMatthew Dillon */ 80df8bae1dSRodney W. Grimes /* ARGSUSED */ 8126f9a767SRodney W. Grimes int 824c44ad8eSJohn Baldwin getpid(struct thread *td, struct getpid_args *uap) 83df8bae1dSRodney W. Grimes { 84b40ce416SJulian Elischer struct proc *p = td->td_proc; 85d23f5958SMatthew Dillon int s; 86df8bae1dSRodney W. Grimes 87d23f5958SMatthew Dillon s = mtx_lock_giant(kern_giant_proc); 88b40ce416SJulian Elischer td->td_retval[0] = p->p_pid; 89df8bae1dSRodney W. Grimes #if defined(COMPAT_43) || defined(COMPAT_SUNOS) 90bae3a80bSJohn Baldwin PROC_LOCK(p); 91b40ce416SJulian Elischer td->td_retval[1] = p->p_pptr->p_pid; 92bae3a80bSJohn Baldwin PROC_UNLOCK(p); 93df8bae1dSRodney W. Grimes #endif 94d23f5958SMatthew Dillon mtx_unlock_giant(s); 95df8bae1dSRodney W. Grimes return (0); 96df8bae1dSRodney W. Grimes } 97df8bae1dSRodney W. Grimes 98d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 99ad7507e2SSteven Wallace struct getppid_args { 100ad7507e2SSteven Wallace int dummy; 101ad7507e2SSteven Wallace }; 102d2d3e875SBruce Evans #endif 103835a82eeSMatthew Dillon /* 104835a82eeSMatthew Dillon * MPSAFE 105835a82eeSMatthew Dillon */ 106df8bae1dSRodney W. Grimes /* ARGSUSED */ 10726f9a767SRodney W. Grimes int 1084c44ad8eSJohn Baldwin getppid(struct thread *td, struct getppid_args *uap) 109df8bae1dSRodney W. Grimes { 110b40ce416SJulian Elischer struct proc *p = td->td_proc; 111d23f5958SMatthew Dillon int s; 112df8bae1dSRodney W. Grimes 113d23f5958SMatthew Dillon s = mtx_lock_giant(kern_giant_proc); 114bae3a80bSJohn Baldwin PROC_LOCK(p); 115b40ce416SJulian Elischer td->td_retval[0] = p->p_pptr->p_pid; 116bae3a80bSJohn Baldwin PROC_UNLOCK(p); 117d23f5958SMatthew Dillon mtx_unlock_giant(s); 118df8bae1dSRodney W. Grimes return (0); 119df8bae1dSRodney W. Grimes } 120df8bae1dSRodney W. Grimes 12136e9f877SMatthew Dillon /* 122eb725b4eSRobert Watson * Get process group ID; note that POSIX getpgrp takes no parameter. 12336e9f877SMatthew Dillon */ 124d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 125ad7507e2SSteven Wallace struct getpgrp_args { 126ad7507e2SSteven Wallace int dummy; 127ad7507e2SSteven Wallace }; 128d2d3e875SBruce Evans #endif 129835a82eeSMatthew Dillon /* 130835a82eeSMatthew Dillon * MPSAFE 131835a82eeSMatthew Dillon */ 13226f9a767SRodney W. Grimes int 1334c44ad8eSJohn Baldwin getpgrp(struct thread *td, struct getpgrp_args *uap) 134df8bae1dSRodney W. Grimes { 135b40ce416SJulian Elischer struct proc *p = td->td_proc; 136f591779bSSeigo Tanimura int s; 137df8bae1dSRodney W. Grimes 138f591779bSSeigo Tanimura s = mtx_lock_giant(kern_giant_proc); 139f591779bSSeigo Tanimura PROC_LOCK(p); 140b40ce416SJulian Elischer td->td_retval[0] = p->p_pgrp->pg_id; 141f591779bSSeigo Tanimura PROC_UNLOCK(p); 142f591779bSSeigo Tanimura mtx_unlock_giant(s); 143df8bae1dSRodney W. Grimes return (0); 144df8bae1dSRodney W. Grimes } 145df8bae1dSRodney W. Grimes 1461a5018a0SPeter Wemm /* Get an arbitary pid's process group id */ 1471a5018a0SPeter Wemm #ifndef _SYS_SYSPROTO_H_ 1481a5018a0SPeter Wemm struct getpgid_args { 1491a5018a0SPeter Wemm pid_t pid; 1501a5018a0SPeter Wemm }; 1511a5018a0SPeter Wemm #endif 152835a82eeSMatthew Dillon /* 153835a82eeSMatthew Dillon * MPSAFE 154835a82eeSMatthew Dillon */ 1551a5018a0SPeter Wemm int 1564c44ad8eSJohn Baldwin getpgid(struct thread *td, struct getpgid_args *uap) 1571a5018a0SPeter Wemm { 158b40ce416SJulian Elischer struct proc *p = td->td_proc; 15965de0c7aSDon Lewis struct proc *pt; 160f2ae7368SJohn Baldwin int error; 16165de0c7aSDon Lewis 162f2ae7368SJohn Baldwin mtx_lock(&Giant); 163eb725b4eSRobert Watson error = 0; 164f591779bSSeigo Tanimura if (uap->pid == 0) { 165f591779bSSeigo Tanimura PROC_LOCK(p); 166b40ce416SJulian Elischer td->td_retval[0] = p->p_pgrp->pg_id; 167f591779bSSeigo Tanimura PROC_UNLOCK(p); 168f591779bSSeigo Tanimura } else if ((pt = pfind(uap->pid)) == NULL) 169835a82eeSMatthew Dillon error = ESRCH; 1706a90c862SJohn Baldwin else { 1716a90c862SJohn Baldwin error = p_cansee(p, pt); 1726a90c862SJohn Baldwin if (error == 0) 173b40ce416SJulian Elischer td->td_retval[0] = pt->p_pgrp->pg_id; 17433a9ed9dSJohn Baldwin PROC_UNLOCK(pt); 17533a9ed9dSJohn Baldwin } 176f2ae7368SJohn Baldwin mtx_unlock(&Giant); 177835a82eeSMatthew Dillon return (error); 1781a5018a0SPeter Wemm } 1791a5018a0SPeter Wemm 1801a5018a0SPeter Wemm /* 1811a5018a0SPeter Wemm * Get an arbitary pid's session id. 1821a5018a0SPeter Wemm */ 1831a5018a0SPeter Wemm #ifndef _SYS_SYSPROTO_H_ 1841a5018a0SPeter Wemm struct getsid_args { 1851a5018a0SPeter Wemm pid_t pid; 1861a5018a0SPeter Wemm }; 1871a5018a0SPeter Wemm #endif 188835a82eeSMatthew Dillon /* 189835a82eeSMatthew Dillon * MPSAFE 190835a82eeSMatthew Dillon */ 1911a5018a0SPeter Wemm int 1924c44ad8eSJohn Baldwin getsid(struct thread *td, struct getsid_args *uap) 1931a5018a0SPeter Wemm { 194b40ce416SJulian Elischer struct proc *p = td->td_proc; 19565de0c7aSDon Lewis struct proc *pt; 196eb725b4eSRobert Watson int error; 19765de0c7aSDon Lewis 198f2ae7368SJohn Baldwin mtx_lock(&Giant); 199eb725b4eSRobert Watson error = 0; 200f591779bSSeigo Tanimura if (uap->pid == 0) { 201f591779bSSeigo Tanimura PROC_LOCK(p); 202b40ce416SJulian Elischer td->td_retval[0] = p->p_session->s_sid; 203f591779bSSeigo Tanimura PROC_UNLOCK(p); 204f591779bSSeigo Tanimura } else if ((pt = pfind(uap->pid)) == NULL) 205835a82eeSMatthew Dillon error = ESRCH; 2066a90c862SJohn Baldwin else { 2076a90c862SJohn Baldwin error = p_cansee(p, pt); 2086a90c862SJohn Baldwin if (error == 0) 209b40ce416SJulian Elischer td->td_retval[0] = pt->p_session->s_sid; 21033a9ed9dSJohn Baldwin PROC_UNLOCK(pt); 21133a9ed9dSJohn Baldwin } 212f2ae7368SJohn Baldwin mtx_unlock(&Giant); 213835a82eeSMatthew Dillon return (error); 2141a5018a0SPeter Wemm } 2151a5018a0SPeter Wemm 216d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 217ad7507e2SSteven Wallace struct getuid_args { 218ad7507e2SSteven Wallace int dummy; 219ad7507e2SSteven Wallace }; 220d2d3e875SBruce Evans #endif 221835a82eeSMatthew Dillon /* 222835a82eeSMatthew Dillon * MPSAFE 223835a82eeSMatthew Dillon */ 224df8bae1dSRodney W. Grimes /* ARGSUSED */ 22526f9a767SRodney W. Grimes int 2264c44ad8eSJohn Baldwin getuid(struct thread *td, struct getuid_args *uap) 227df8bae1dSRodney W. Grimes { 228df8bae1dSRodney W. Grimes 229d846883bSJohn Baldwin td->td_retval[0] = td->td_ucred->cr_ruid; 230df8bae1dSRodney W. Grimes #if defined(COMPAT_43) || defined(COMPAT_SUNOS) 231d846883bSJohn Baldwin td->td_retval[1] = td->td_ucred->cr_uid; 232df8bae1dSRodney W. Grimes #endif 233df8bae1dSRodney W. Grimes return (0); 234df8bae1dSRodney W. Grimes } 235df8bae1dSRodney W. Grimes 236d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 237ad7507e2SSteven Wallace struct geteuid_args { 238ad7507e2SSteven Wallace int dummy; 239ad7507e2SSteven Wallace }; 240d2d3e875SBruce Evans #endif 241eb725b4eSRobert Watson /* 242eb725b4eSRobert Watson * MPSAFE 243eb725b4eSRobert Watson */ 244df8bae1dSRodney W. Grimes /* ARGSUSED */ 24526f9a767SRodney W. Grimes int 2464c44ad8eSJohn Baldwin geteuid(struct thread *td, struct geteuid_args *uap) 247df8bae1dSRodney W. Grimes { 248d846883bSJohn Baldwin 249d846883bSJohn Baldwin td->td_retval[0] = td->td_ucred->cr_uid; 250df8bae1dSRodney W. Grimes return (0); 251df8bae1dSRodney W. Grimes } 252df8bae1dSRodney W. Grimes 253d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 254ad7507e2SSteven Wallace struct getgid_args { 255ad7507e2SSteven Wallace int dummy; 256ad7507e2SSteven Wallace }; 257d2d3e875SBruce Evans #endif 258835a82eeSMatthew Dillon /* 259835a82eeSMatthew Dillon * MPSAFE 260835a82eeSMatthew Dillon */ 261df8bae1dSRodney W. Grimes /* ARGSUSED */ 26226f9a767SRodney W. Grimes int 2634c44ad8eSJohn Baldwin getgid(struct thread *td, struct getgid_args *uap) 264df8bae1dSRodney W. Grimes { 265df8bae1dSRodney W. Grimes 266d846883bSJohn Baldwin td->td_retval[0] = td->td_ucred->cr_rgid; 267df8bae1dSRodney W. Grimes #if defined(COMPAT_43) || defined(COMPAT_SUNOS) 268d846883bSJohn Baldwin td->td_retval[1] = td->td_ucred->cr_groups[0]; 269df8bae1dSRodney W. Grimes #endif 270df8bae1dSRodney W. Grimes return (0); 271df8bae1dSRodney W. Grimes } 272df8bae1dSRodney W. Grimes 273df8bae1dSRodney W. Grimes /* 274df8bae1dSRodney W. Grimes * Get effective group ID. The "egid" is groups[0], and could be obtained 275df8bae1dSRodney W. Grimes * via getgroups. This syscall exists because it is somewhat painful to do 276df8bae1dSRodney W. Grimes * correctly in a library function. 277df8bae1dSRodney W. Grimes */ 278d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 279ad7507e2SSteven Wallace struct getegid_args { 280ad7507e2SSteven Wallace int dummy; 281ad7507e2SSteven Wallace }; 282d2d3e875SBruce Evans #endif 283835a82eeSMatthew Dillon /* 284835a82eeSMatthew Dillon * MPSAFE 285835a82eeSMatthew Dillon */ 286df8bae1dSRodney W. Grimes /* ARGSUSED */ 28726f9a767SRodney W. Grimes int 2884c44ad8eSJohn Baldwin getegid(struct thread *td, struct getegid_args *uap) 289df8bae1dSRodney W. Grimes { 290df8bae1dSRodney W. Grimes 291d846883bSJohn Baldwin td->td_retval[0] = td->td_ucred->cr_groups[0]; 292df8bae1dSRodney W. Grimes return (0); 293df8bae1dSRodney W. Grimes } 294df8bae1dSRodney W. Grimes 295d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 296df8bae1dSRodney W. Grimes struct getgroups_args { 297df8bae1dSRodney W. Grimes u_int gidsetsize; 298df8bae1dSRodney W. Grimes gid_t *gidset; 299df8bae1dSRodney W. Grimes }; 300d2d3e875SBruce Evans #endif 301835a82eeSMatthew Dillon /* 302835a82eeSMatthew Dillon * MPSAFE 303835a82eeSMatthew Dillon */ 30426f9a767SRodney W. Grimes int 3054c44ad8eSJohn Baldwin getgroups(struct thread *td, register struct getgroups_args *uap) 306df8bae1dSRodney W. Grimes { 307835a82eeSMatthew Dillon struct ucred *cred; 308b1fc0ec1SRobert Watson u_int ngrp; 309eb725b4eSRobert Watson int error; 310df8bae1dSRodney W. Grimes 311d846883bSJohn Baldwin cred = td->td_ucred; 312df8bae1dSRodney W. Grimes if ((ngrp = uap->gidsetsize) == 0) { 313b40ce416SJulian Elischer td->td_retval[0] = cred->cr_ngroups; 314d846883bSJohn Baldwin return (0); 315df8bae1dSRodney W. Grimes } 316d846883bSJohn Baldwin if (ngrp < cred->cr_ngroups) 317d846883bSJohn Baldwin return (EINVAL); 318b1fc0ec1SRobert Watson ngrp = cred->cr_ngroups; 319d846883bSJohn Baldwin error = copyout((caddr_t)cred->cr_groups, (caddr_t)uap->gidset, 320d846883bSJohn Baldwin ngrp * sizeof(gid_t)); 321d74ac681SMatthew Dillon if (error == 0) 322d846883bSJohn Baldwin td->td_retval[0] = ngrp; 323d74ac681SMatthew Dillon return (error); 324df8bae1dSRodney W. Grimes } 325df8bae1dSRodney W. Grimes 326d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 32782970b81SBruce Evans struct setsid_args { 328ad7507e2SSteven Wallace int dummy; 329ad7507e2SSteven Wallace }; 330d2d3e875SBruce Evans #endif 331835a82eeSMatthew Dillon /* 332835a82eeSMatthew Dillon * MPSAFE 333835a82eeSMatthew Dillon */ 334df8bae1dSRodney W. Grimes /* ARGSUSED */ 33526f9a767SRodney W. Grimes int 3364c44ad8eSJohn Baldwin setsid(register struct thread *td, struct setsid_args *uap) 337df8bae1dSRodney W. Grimes { 338f591779bSSeigo Tanimura struct pgrp *pgrp; 339835a82eeSMatthew Dillon int error; 340b40ce416SJulian Elischer struct proc *p = td->td_proc; 341f591779bSSeigo Tanimura struct pgrp *newpgrp; 342f591779bSSeigo Tanimura struct session *newsess; 343f591779bSSeigo Tanimura 344f591779bSSeigo Tanimura error = 0; 345f591779bSSeigo Tanimura pgrp = NULL; 346df8bae1dSRodney W. Grimes 347835a82eeSMatthew Dillon mtx_lock(&Giant); 348f591779bSSeigo Tanimura 349f591779bSSeigo Tanimura MALLOC(newpgrp, struct pgrp *, sizeof(struct pgrp), M_PGRP, M_WAITOK | M_ZERO); 350f591779bSSeigo Tanimura MALLOC(newsess, struct session *, sizeof(struct session), M_SESSION, M_WAITOK | M_ZERO); 351f591779bSSeigo Tanimura 352c8b1829dSJohn Baldwin sx_xlock(&proctree_lock); 353f591779bSSeigo Tanimura 354f591779bSSeigo Tanimura if (p->p_pgid == p->p_pid || (pgrp = pgfind(p->p_pid)) != NULL) { 355f591779bSSeigo Tanimura if (pgrp != NULL) 356f591779bSSeigo Tanimura PGRP_UNLOCK(pgrp); 357835a82eeSMatthew Dillon error = EPERM; 358f591779bSSeigo Tanimura } else { 359f591779bSSeigo Tanimura (void)enterpgrp(p, p->p_pid, newpgrp, newsess); 360b40ce416SJulian Elischer td->td_retval[0] = p->p_pid; 361c8b1829dSJohn Baldwin newpgrp = NULL; 362c8b1829dSJohn Baldwin newsess = NULL; 363df8bae1dSRodney W. Grimes } 364f591779bSSeigo Tanimura 365c8b1829dSJohn Baldwin sx_xunlock(&proctree_lock); 366f591779bSSeigo Tanimura 367c8b1829dSJohn Baldwin if (newpgrp != NULL) 368f591779bSSeigo Tanimura FREE(newpgrp, M_PGRP); 369c8b1829dSJohn Baldwin if (newsess != NULL) 370f591779bSSeigo Tanimura FREE(newsess, M_SESSION); 371f591779bSSeigo Tanimura 372f591779bSSeigo Tanimura mtx_unlock(&Giant); 373c8b1829dSJohn Baldwin return (error); 374df8bae1dSRodney W. Grimes } 375df8bae1dSRodney W. Grimes 376df8bae1dSRodney W. Grimes /* 377df8bae1dSRodney W. Grimes * set process group (setpgid/old setpgrp) 378df8bae1dSRodney W. Grimes * 379df8bae1dSRodney W. Grimes * caller does setpgid(targpid, targpgid) 380df8bae1dSRodney W. Grimes * 381df8bae1dSRodney W. Grimes * pid must be caller or child of caller (ESRCH) 382df8bae1dSRodney W. Grimes * if a child 383df8bae1dSRodney W. Grimes * pid must be in same session (EPERM) 384df8bae1dSRodney W. Grimes * pid can't have done an exec (EACCES) 385df8bae1dSRodney W. Grimes * if pgid != pid 386df8bae1dSRodney W. Grimes * there must exist some pid in same session having pgid (EPERM) 387df8bae1dSRodney W. Grimes * pid must not be session leader (EPERM) 388df8bae1dSRodney W. Grimes */ 389d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 390df8bae1dSRodney W. Grimes struct setpgid_args { 391df8bae1dSRodney W. Grimes int pid; /* target process id */ 392df8bae1dSRodney W. Grimes int pgid; /* target pgrp id */ 393df8bae1dSRodney W. Grimes }; 394d2d3e875SBruce Evans #endif 395835a82eeSMatthew Dillon /* 396835a82eeSMatthew Dillon * MPSAFE 397835a82eeSMatthew Dillon */ 398df8bae1dSRodney W. Grimes /* ARGSUSED */ 39926f9a767SRodney W. Grimes int 4004c44ad8eSJohn Baldwin setpgid(struct thread *td, register struct setpgid_args *uap) 401df8bae1dSRodney W. Grimes { 402b40ce416SJulian Elischer struct proc *curp = td->td_proc; 403df8bae1dSRodney W. Grimes register struct proc *targp; /* target process */ 404df8bae1dSRodney W. Grimes register struct pgrp *pgrp; /* target pgrp */ 405eb9e5c1dSRobert Watson int error; 406f591779bSSeigo Tanimura struct pgrp *newpgrp; 407df8bae1dSRodney W. Grimes 40878f64bccSBruce Evans if (uap->pgid < 0) 40978f64bccSBruce Evans return (EINVAL); 410f591779bSSeigo Tanimura 411f591779bSSeigo Tanimura error = 0; 412f591779bSSeigo Tanimura 413835a82eeSMatthew Dillon mtx_lock(&Giant); 414f591779bSSeigo Tanimura 415f591779bSSeigo Tanimura MALLOC(newpgrp, struct pgrp *, sizeof(struct pgrp), M_PGRP, M_WAITOK | M_ZERO); 416f591779bSSeigo Tanimura 417c8b1829dSJohn Baldwin sx_xlock(&proctree_lock); 418df8bae1dSRodney W. Grimes if (uap->pid != 0 && uap->pid != curp->p_pid) { 419f591779bSSeigo Tanimura if ((targp = pfind(uap->pid)) == NULL) { 42033a9ed9dSJohn Baldwin if (targp) 42133a9ed9dSJohn Baldwin PROC_UNLOCK(targp); 422835a82eeSMatthew Dillon error = ESRCH; 423c8b1829dSJohn Baldwin goto done; 42433a9ed9dSJohn Baldwin } 425f591779bSSeigo Tanimura if (!inferior(targp)) { 426f591779bSSeigo Tanimura PROC_UNLOCK(targp); 4272f932587SSeigo Tanimura error = ESRCH; 428c8b1829dSJohn Baldwin goto done; 429f591779bSSeigo Tanimura } 430a0f75161SRobert Watson if ((error = p_cansee(curproc, targp))) { 43133a9ed9dSJohn Baldwin PROC_UNLOCK(targp); 432c8b1829dSJohn Baldwin goto done; 43333a9ed9dSJohn Baldwin } 43433a9ed9dSJohn Baldwin if (targp->p_pgrp == NULL || 43533a9ed9dSJohn Baldwin targp->p_session != curp->p_session) { 43633a9ed9dSJohn Baldwin PROC_UNLOCK(targp); 437835a82eeSMatthew Dillon error = EPERM; 438c8b1829dSJohn Baldwin goto done; 43933a9ed9dSJohn Baldwin } 44033a9ed9dSJohn Baldwin if (targp->p_flag & P_EXEC) { 44133a9ed9dSJohn Baldwin PROC_UNLOCK(targp); 442835a82eeSMatthew Dillon error = EACCES; 443c8b1829dSJohn Baldwin goto done; 44433a9ed9dSJohn Baldwin } 44533a9ed9dSJohn Baldwin PROC_UNLOCK(targp); 446f591779bSSeigo Tanimura } else 447f591779bSSeigo Tanimura targp = curp; 448f591779bSSeigo Tanimura if (SESS_LEADER(targp)) { 449835a82eeSMatthew Dillon error = EPERM; 450c8b1829dSJohn Baldwin goto done; 45133a9ed9dSJohn Baldwin } 452eb725b4eSRobert Watson if (uap->pgid == 0) 453df8bae1dSRodney W. Grimes uap->pgid = targp->p_pid; 454f591779bSSeigo Tanimura if (uap->pgid == targp->p_pid) { 455f591779bSSeigo Tanimura if (targp->p_pgid == uap->pgid) 456f591779bSSeigo Tanimura goto done; 457f591779bSSeigo Tanimura error = enterpgrp(targp, uap->pgid, newpgrp, NULL); 458f591779bSSeigo Tanimura if (error == 0) 459f591779bSSeigo Tanimura newpgrp = NULL; 460f591779bSSeigo Tanimura } else { 461f591779bSSeigo Tanimura if ((pgrp = pgfind(uap->pgid)) == NULL || 46233a9ed9dSJohn Baldwin pgrp->pg_session != curp->p_session) { 463f591779bSSeigo Tanimura if (pgrp != NULL) 464f591779bSSeigo Tanimura PGRP_UNLOCK(pgrp); 465835a82eeSMatthew Dillon error = EPERM; 466c8b1829dSJohn Baldwin goto done; 467835a82eeSMatthew Dillon } 468f591779bSSeigo Tanimura if (pgrp == targp->p_pgrp) { 469f591779bSSeigo Tanimura PGRP_UNLOCK(pgrp); 470f591779bSSeigo Tanimura goto done; 47133a9ed9dSJohn Baldwin } 472f591779bSSeigo Tanimura PGRP_UNLOCK(pgrp); 473f591779bSSeigo Tanimura error = enterthispgrp(targp, pgrp); 474f591779bSSeigo Tanimura } 475f591779bSSeigo Tanimura done: 476c8b1829dSJohn Baldwin sx_xunlock(&proctree_lock); 477c8b1829dSJohn Baldwin KASSERT((error == 0) || (newpgrp != NULL), 478c8b1829dSJohn Baldwin ("setpgid failed and newpgrp is NULL")); 479f591779bSSeigo Tanimura if (newpgrp != NULL) 480f591779bSSeigo Tanimura FREE(newpgrp, M_PGRP); 481f591779bSSeigo Tanimura mtx_unlock(&Giant); 482835a82eeSMatthew Dillon return (error); 483df8bae1dSRodney W. Grimes } 484df8bae1dSRodney W. Grimes 485a08f4bf6SPeter Wemm /* 486a08f4bf6SPeter Wemm * Use the clause in B.4.2.2 that allows setuid/setgid to be 4.2/4.3BSD 4872fa72ea7SJeroen Ruigrok van der Werven * compatible. It says that setting the uid/gid to euid/egid is a special 488a08f4bf6SPeter Wemm * case of "appropriate privilege". Once the rules are expanded out, this 489a08f4bf6SPeter Wemm * basically means that setuid(nnn) sets all three id's, in all permitted 490a08f4bf6SPeter Wemm * cases unless _POSIX_SAVED_IDS is enabled. In that case, setuid(getuid()) 491a08f4bf6SPeter Wemm * does not set the saved id - this is dangerous for traditional BSD 492a08f4bf6SPeter Wemm * programs. For this reason, we *really* do not want to set 493a08f4bf6SPeter Wemm * _POSIX_SAVED_IDS and do not want to clear POSIX_APPENDIX_B_4_2_2. 494a08f4bf6SPeter Wemm */ 495a08f4bf6SPeter Wemm #define POSIX_APPENDIX_B_4_2_2 496a08f4bf6SPeter Wemm 497d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 498df8bae1dSRodney W. Grimes struct setuid_args { 499df8bae1dSRodney W. Grimes uid_t uid; 500df8bae1dSRodney W. Grimes }; 501d2d3e875SBruce Evans #endif 502835a82eeSMatthew Dillon /* 503835a82eeSMatthew Dillon * MPSAFE 504835a82eeSMatthew Dillon */ 505df8bae1dSRodney W. Grimes /* ARGSUSED */ 50626f9a767SRodney W. Grimes int 5074c44ad8eSJohn Baldwin setuid(struct thread *td, struct setuid_args *uap) 508df8bae1dSRodney W. Grimes { 509b40ce416SJulian Elischer struct proc *p = td->td_proc; 510b1fc0ec1SRobert Watson struct ucred *newcred, *oldcred; 511b1fc0ec1SRobert Watson uid_t uid; 512eb725b4eSRobert Watson int error; 513df8bae1dSRodney W. Grimes 514835a82eeSMatthew Dillon mtx_lock(&Giant); 51507f3485dSJohn Baldwin uid = uap->uid; 51607f3485dSJohn Baldwin newcred = crget(); 51707f3485dSJohn Baldwin PROC_LOCK(p); 518f605567cSRobert Watson oldcred = p->p_ucred; 5195a92ee3cSRobert Watson 520a08f4bf6SPeter Wemm /* 521a08f4bf6SPeter Wemm * See if we have "permission" by POSIX 1003.1 rules. 522a08f4bf6SPeter Wemm * 523a08f4bf6SPeter Wemm * Note that setuid(geteuid()) is a special case of 524a08f4bf6SPeter Wemm * "appropriate privileges" in appendix B.4.2.2. We need 5252fa72ea7SJeroen Ruigrok van der Werven * to use this clause to be compatible with traditional BSD 526a08f4bf6SPeter Wemm * semantics. Basically, it means that "setuid(xx)" sets all 527a08f4bf6SPeter Wemm * three id's (assuming you have privs). 528a08f4bf6SPeter Wemm * 529a08f4bf6SPeter Wemm * Notes on the logic. We do things in three steps. 530a08f4bf6SPeter Wemm * 1: We determine if the euid is going to change, and do EPERM 531a08f4bf6SPeter Wemm * right away. We unconditionally change the euid later if this 532a08f4bf6SPeter Wemm * test is satisfied, simplifying that part of the logic. 533eb725b4eSRobert Watson * 2: We determine if the real and/or saved uids are going to 534a08f4bf6SPeter Wemm * change. Determined by compile options. 535a08f4bf6SPeter Wemm * 3: Change euid last. (after tests in #2 for "appropriate privs") 536a08f4bf6SPeter Wemm */ 537b1fc0ec1SRobert Watson if (uid != oldcred->cr_ruid && /* allow setuid(getuid()) */ 5383f246666SAndrey A. Chernov #ifdef _POSIX_SAVED_IDS 539b1fc0ec1SRobert Watson uid != oldcred->cr_svuid && /* allow setuid(saved gid) */ 540a08f4bf6SPeter Wemm #endif 541a08f4bf6SPeter Wemm #ifdef POSIX_APPENDIX_B_4_2_2 /* Use BSD-compat clause from B.4.2.2 */ 542b1fc0ec1SRobert Watson uid != oldcred->cr_uid && /* allow setuid(geteuid()) */ 5433f246666SAndrey A. Chernov #endif 54407f3485dSJohn Baldwin (error = suser_cred(oldcred, PRISON_ROOT)) != 0) { 54507f3485dSJohn Baldwin PROC_UNLOCK(p); 54607f3485dSJohn Baldwin crfree(newcred); 54707f3485dSJohn Baldwin mtx_unlock(&Giant); 54807f3485dSJohn Baldwin return (error); 54907f3485dSJohn Baldwin } 550a08f4bf6SPeter Wemm 55107f3485dSJohn Baldwin crcopy(newcred, oldcred); 552a08f4bf6SPeter Wemm #ifdef _POSIX_SAVED_IDS 553df8bae1dSRodney W. Grimes /* 554a08f4bf6SPeter Wemm * Do we have "appropriate privileges" (are we root or uid == euid) 555a08f4bf6SPeter Wemm * If so, we are changing the real uid and/or saved uid. 556df8bae1dSRodney W. Grimes */ 5573f246666SAndrey A. Chernov if ( 558a08f4bf6SPeter Wemm #ifdef POSIX_APPENDIX_B_4_2_2 /* Use the clause from B.4.2.2 */ 559b1fc0ec1SRobert Watson uid == oldcred->cr_uid || 5603f246666SAndrey A. Chernov #endif 56144731cabSJohn Baldwin suser_cred(oldcred, PRISON_ROOT) == 0) /* we are using privs */ 562a08f4bf6SPeter Wemm #endif 563a08f4bf6SPeter Wemm { 564a08f4bf6SPeter Wemm /* 565f535380cSDon Lewis * Set the real uid and transfer proc count to new user. 566a08f4bf6SPeter Wemm */ 567b1fc0ec1SRobert Watson if (uid != oldcred->cr_ruid) { 568b1fc0ec1SRobert Watson change_ruid(newcred, uid); 569f535380cSDon Lewis setsugid(p); 570d3cdb93dSAndrey A. Chernov } 571a08f4bf6SPeter Wemm /* 572a08f4bf6SPeter Wemm * Set saved uid 573a08f4bf6SPeter Wemm * 574a08f4bf6SPeter Wemm * XXX always set saved uid even if not _POSIX_SAVED_IDS, as 575a08f4bf6SPeter Wemm * the security of seteuid() depends on it. B.4.2.2 says it 576a08f4bf6SPeter Wemm * is important that we should do this. 577a08f4bf6SPeter Wemm */ 578b1fc0ec1SRobert Watson if (uid != oldcred->cr_svuid) { 579b1fc0ec1SRobert Watson change_svuid(newcred, uid); 580d5f81602SSean Eric Fagan setsugid(p); 581a08f4bf6SPeter Wemm } 582a08f4bf6SPeter Wemm } 583a08f4bf6SPeter Wemm 584a08f4bf6SPeter Wemm /* 585a08f4bf6SPeter Wemm * In all permitted cases, we are changing the euid. 586a08f4bf6SPeter Wemm * Copy credentials so other references do not see our changes. 587a08f4bf6SPeter Wemm */ 588b1fc0ec1SRobert Watson if (uid != oldcred->cr_uid) { 589b1fc0ec1SRobert Watson change_euid(newcred, uid); 590d5f81602SSean Eric Fagan setsugid(p); 591a08f4bf6SPeter Wemm } 592b1fc0ec1SRobert Watson p->p_ucred = newcred; 59307f3485dSJohn Baldwin PROC_UNLOCK(p); 594b1fc0ec1SRobert Watson crfree(oldcred); 595835a82eeSMatthew Dillon mtx_unlock(&Giant); 59607f3485dSJohn Baldwin return (0); 597df8bae1dSRodney W. Grimes } 598df8bae1dSRodney W. Grimes 599d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 600df8bae1dSRodney W. Grimes struct seteuid_args { 601df8bae1dSRodney W. Grimes uid_t euid; 602df8bae1dSRodney W. Grimes }; 603d2d3e875SBruce Evans #endif 604835a82eeSMatthew Dillon /* 605835a82eeSMatthew Dillon * MPSAFE 606835a82eeSMatthew Dillon */ 607df8bae1dSRodney W. Grimes /* ARGSUSED */ 60826f9a767SRodney W. Grimes int 6094c44ad8eSJohn Baldwin seteuid(struct thread *td, struct seteuid_args *uap) 610df8bae1dSRodney W. Grimes { 611b40ce416SJulian Elischer struct proc *p = td->td_proc; 612b1fc0ec1SRobert Watson struct ucred *newcred, *oldcred; 613b1fc0ec1SRobert Watson uid_t euid; 614eb725b4eSRobert Watson int error; 615df8bae1dSRodney W. Grimes 616df8bae1dSRodney W. Grimes euid = uap->euid; 617835a82eeSMatthew Dillon mtx_lock(&Giant); 61807f3485dSJohn Baldwin newcred = crget(); 61907f3485dSJohn Baldwin PROC_LOCK(p); 620b1fc0ec1SRobert Watson oldcred = p->p_ucred; 621b1fc0ec1SRobert Watson if (euid != oldcred->cr_ruid && /* allow seteuid(getuid()) */ 622b1fc0ec1SRobert Watson euid != oldcred->cr_svuid && /* allow seteuid(saved uid) */ 62307f3485dSJohn Baldwin (error = suser_cred(oldcred, PRISON_ROOT)) != 0) { 62407f3485dSJohn Baldwin PROC_UNLOCK(p); 62507f3485dSJohn Baldwin crfree(newcred); 62607f3485dSJohn Baldwin mtx_unlock(&Giant); 62707f3485dSJohn Baldwin return (error); 62807f3485dSJohn Baldwin } 629df8bae1dSRodney W. Grimes /* 630df8bae1dSRodney W. Grimes * Everything's okay, do it. Copy credentials so other references do 631df8bae1dSRodney W. Grimes * not see our changes. 632df8bae1dSRodney W. Grimes */ 63307f3485dSJohn Baldwin crcopy(newcred, oldcred); 634b1fc0ec1SRobert Watson if (oldcred->cr_uid != euid) { 635b1fc0ec1SRobert Watson change_euid(newcred, euid); 636d5f81602SSean Eric Fagan setsugid(p); 637229a15f0SPeter Wemm } 638b1fc0ec1SRobert Watson p->p_ucred = newcred; 63907f3485dSJohn Baldwin PROC_UNLOCK(p); 640b1fc0ec1SRobert Watson crfree(oldcred); 641835a82eeSMatthew Dillon mtx_unlock(&Giant); 64207f3485dSJohn Baldwin return (0); 643df8bae1dSRodney W. Grimes } 644df8bae1dSRodney W. Grimes 645d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 646df8bae1dSRodney W. Grimes struct setgid_args { 647df8bae1dSRodney W. Grimes gid_t gid; 648df8bae1dSRodney W. Grimes }; 649d2d3e875SBruce Evans #endif 650835a82eeSMatthew Dillon /* 651835a82eeSMatthew Dillon * MPSAFE 652835a82eeSMatthew Dillon */ 653df8bae1dSRodney W. Grimes /* ARGSUSED */ 65426f9a767SRodney W. Grimes int 6554c44ad8eSJohn Baldwin setgid(struct thread *td, struct setgid_args *uap) 656df8bae1dSRodney W. Grimes { 657b40ce416SJulian Elischer struct proc *p = td->td_proc; 658b1fc0ec1SRobert Watson struct ucred *newcred, *oldcred; 659b1fc0ec1SRobert Watson gid_t gid; 660eb725b4eSRobert Watson int error; 661df8bae1dSRodney W. Grimes 662b1fc0ec1SRobert Watson gid = uap->gid; 663835a82eeSMatthew Dillon mtx_lock(&Giant); 66407f3485dSJohn Baldwin newcred = crget(); 66507f3485dSJohn Baldwin PROC_LOCK(p); 666b1fc0ec1SRobert Watson oldcred = p->p_ucred; 6675a92ee3cSRobert Watson 668a08f4bf6SPeter Wemm /* 669a08f4bf6SPeter Wemm * See if we have "permission" by POSIX 1003.1 rules. 670a08f4bf6SPeter Wemm * 671a08f4bf6SPeter Wemm * Note that setgid(getegid()) is a special case of 672a08f4bf6SPeter Wemm * "appropriate privileges" in appendix B.4.2.2. We need 6732fa72ea7SJeroen Ruigrok van der Werven * to use this clause to be compatible with traditional BSD 674a08f4bf6SPeter Wemm * semantics. Basically, it means that "setgid(xx)" sets all 675a08f4bf6SPeter Wemm * three id's (assuming you have privs). 676a08f4bf6SPeter Wemm * 677a08f4bf6SPeter Wemm * For notes on the logic here, see setuid() above. 678a08f4bf6SPeter Wemm */ 679b1fc0ec1SRobert Watson if (gid != oldcred->cr_rgid && /* allow setgid(getgid()) */ 6803f246666SAndrey A. Chernov #ifdef _POSIX_SAVED_IDS 681b1fc0ec1SRobert Watson gid != oldcred->cr_svgid && /* allow setgid(saved gid) */ 682a08f4bf6SPeter Wemm #endif 683a08f4bf6SPeter Wemm #ifdef POSIX_APPENDIX_B_4_2_2 /* Use BSD-compat clause from B.4.2.2 */ 684b1fc0ec1SRobert Watson gid != oldcred->cr_groups[0] && /* allow setgid(getegid()) */ 6853f246666SAndrey A. Chernov #endif 68607f3485dSJohn Baldwin (error = suser_cred(oldcred, PRISON_ROOT)) != 0) { 68707f3485dSJohn Baldwin PROC_UNLOCK(p); 68807f3485dSJohn Baldwin crfree(newcred); 68907f3485dSJohn Baldwin mtx_unlock(&Giant); 69007f3485dSJohn Baldwin return (error); 69107f3485dSJohn Baldwin } 692a08f4bf6SPeter Wemm 69307f3485dSJohn Baldwin crcopy(newcred, oldcred); 694a08f4bf6SPeter Wemm #ifdef _POSIX_SAVED_IDS 695a08f4bf6SPeter Wemm /* 696a08f4bf6SPeter Wemm * Do we have "appropriate privileges" (are we root or gid == egid) 697a08f4bf6SPeter Wemm * If so, we are changing the real uid and saved gid. 698a08f4bf6SPeter Wemm */ 699a08f4bf6SPeter Wemm if ( 700a08f4bf6SPeter Wemm #ifdef POSIX_APPENDIX_B_4_2_2 /* use the clause from B.4.2.2 */ 701b1fc0ec1SRobert Watson gid == oldcred->cr_groups[0] || 702a08f4bf6SPeter Wemm #endif 70344731cabSJohn Baldwin suser_cred(oldcred, PRISON_ROOT) == 0) /* we are using privs */ 704a08f4bf6SPeter Wemm #endif 705a08f4bf6SPeter Wemm { 706a08f4bf6SPeter Wemm /* 707a08f4bf6SPeter Wemm * Set real gid 708a08f4bf6SPeter Wemm */ 709b1fc0ec1SRobert Watson if (oldcred->cr_rgid != gid) { 710b1fc0ec1SRobert Watson change_rgid(newcred, gid); 711d5f81602SSean Eric Fagan setsugid(p); 712a08f4bf6SPeter Wemm } 713a08f4bf6SPeter Wemm /* 714a08f4bf6SPeter Wemm * Set saved gid 715a08f4bf6SPeter Wemm * 716a08f4bf6SPeter Wemm * XXX always set saved gid even if not _POSIX_SAVED_IDS, as 717a08f4bf6SPeter Wemm * the security of setegid() depends on it. B.4.2.2 says it 718a08f4bf6SPeter Wemm * is important that we should do this. 719a08f4bf6SPeter Wemm */ 720b1fc0ec1SRobert Watson if (oldcred->cr_svgid != gid) { 721b1fc0ec1SRobert Watson change_svgid(newcred, gid); 722d5f81602SSean Eric Fagan setsugid(p); 723a08f4bf6SPeter Wemm } 724a08f4bf6SPeter Wemm } 725a08f4bf6SPeter Wemm /* 726a08f4bf6SPeter Wemm * In all cases permitted cases, we are changing the egid. 727a08f4bf6SPeter Wemm * Copy credentials so other references do not see our changes. 728a08f4bf6SPeter Wemm */ 729b1fc0ec1SRobert Watson if (oldcred->cr_groups[0] != gid) { 730b1fc0ec1SRobert Watson change_egid(newcred, gid); 731d5f81602SSean Eric Fagan setsugid(p); 732a08f4bf6SPeter Wemm } 733b1fc0ec1SRobert Watson p->p_ucred = newcred; 73407f3485dSJohn Baldwin PROC_UNLOCK(p); 735b1fc0ec1SRobert Watson crfree(oldcred); 736835a82eeSMatthew Dillon mtx_unlock(&Giant); 73707f3485dSJohn Baldwin return (0); 738df8bae1dSRodney W. Grimes } 739df8bae1dSRodney W. Grimes 740d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 741df8bae1dSRodney W. Grimes struct setegid_args { 742df8bae1dSRodney W. Grimes gid_t egid; 743df8bae1dSRodney W. Grimes }; 744d2d3e875SBruce Evans #endif 745835a82eeSMatthew Dillon /* 746835a82eeSMatthew Dillon * MPSAFE 747835a82eeSMatthew Dillon */ 748df8bae1dSRodney W. Grimes /* ARGSUSED */ 74926f9a767SRodney W. Grimes int 7504c44ad8eSJohn Baldwin setegid(struct thread *td, struct setegid_args *uap) 751df8bae1dSRodney W. Grimes { 752b40ce416SJulian Elischer struct proc *p = td->td_proc; 753b1fc0ec1SRobert Watson struct ucred *newcred, *oldcred; 754b1fc0ec1SRobert Watson gid_t egid; 755eb725b4eSRobert Watson int error; 756df8bae1dSRodney W. Grimes 757df8bae1dSRodney W. Grimes egid = uap->egid; 758835a82eeSMatthew Dillon mtx_lock(&Giant); 75907f3485dSJohn Baldwin newcred = crget(); 76007f3485dSJohn Baldwin PROC_LOCK(p); 761b1fc0ec1SRobert Watson oldcred = p->p_ucred; 762b1fc0ec1SRobert Watson if (egid != oldcred->cr_rgid && /* allow setegid(getgid()) */ 763b1fc0ec1SRobert Watson egid != oldcred->cr_svgid && /* allow setegid(saved gid) */ 76407f3485dSJohn Baldwin (error = suser_cred(oldcred, PRISON_ROOT)) != 0) { 76507f3485dSJohn Baldwin PROC_UNLOCK(p); 76607f3485dSJohn Baldwin crfree(newcred); 76707f3485dSJohn Baldwin mtx_unlock(&Giant); 76807f3485dSJohn Baldwin return (error); 76907f3485dSJohn Baldwin } 77007f3485dSJohn Baldwin crcopy(newcred, oldcred); 771b1fc0ec1SRobert Watson if (oldcred->cr_groups[0] != egid) { 772b1fc0ec1SRobert Watson change_egid(newcred, egid); 773d5f81602SSean Eric Fagan setsugid(p); 774229a15f0SPeter Wemm } 775b1fc0ec1SRobert Watson p->p_ucred = newcred; 77607f3485dSJohn Baldwin PROC_UNLOCK(p); 777b1fc0ec1SRobert Watson crfree(oldcred); 778835a82eeSMatthew Dillon mtx_unlock(&Giant); 77907f3485dSJohn Baldwin return (0); 780df8bae1dSRodney W. Grimes } 781df8bae1dSRodney W. Grimes 782d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 783df8bae1dSRodney W. Grimes struct setgroups_args { 784df8bae1dSRodney W. Grimes u_int gidsetsize; 785df8bae1dSRodney W. Grimes gid_t *gidset; 786df8bae1dSRodney W. Grimes }; 787d2d3e875SBruce Evans #endif 788835a82eeSMatthew Dillon /* 789835a82eeSMatthew Dillon * MPSAFE 790835a82eeSMatthew Dillon */ 791df8bae1dSRodney W. Grimes /* ARGSUSED */ 79226f9a767SRodney W. Grimes int 7934c44ad8eSJohn Baldwin setgroups(struct thread *td, struct setgroups_args *uap) 794df8bae1dSRodney W. Grimes { 795b40ce416SJulian Elischer struct proc *p = td->td_proc; 79607f3485dSJohn Baldwin struct ucred *newcred, *tempcred, *oldcred; 797b1fc0ec1SRobert Watson u_int ngrp; 798df8bae1dSRodney W. Grimes int error; 799df8bae1dSRodney W. Grimes 8003956a170SDavid Greenman ngrp = uap->gidsetsize; 80107f3485dSJohn Baldwin if (ngrp > NGROUPS) 80207f3485dSJohn Baldwin return (EINVAL); 8034f5a4612SRobert Watson mtx_lock(&Giant); 80407f3485dSJohn Baldwin tempcred = crget(); 80507f3485dSJohn Baldwin error = copyin((caddr_t)uap->gidset, (caddr_t)tempcred->cr_groups, 80607f3485dSJohn Baldwin ngrp * sizeof(gid_t)); 80707f3485dSJohn Baldwin if (error != 0) { 80807f3485dSJohn Baldwin crfree(tempcred); 80907f3485dSJohn Baldwin mtx_unlock(&Giant); 81007f3485dSJohn Baldwin return (error); 811835a82eeSMatthew Dillon } 81207f3485dSJohn Baldwin newcred = crget(); 81307f3485dSJohn Baldwin PROC_LOCK(p); 81407f3485dSJohn Baldwin oldcred = p->p_ucred; 81507f3485dSJohn Baldwin error = suser_cred(oldcred, PRISON_ROOT); 81607f3485dSJohn Baldwin if (error) { 81707f3485dSJohn Baldwin PROC_UNLOCK(p); 81807f3485dSJohn Baldwin crfree(newcred); 81907f3485dSJohn Baldwin crfree(tempcred); 82007f3485dSJohn Baldwin mtx_unlock(&Giant); 82107f3485dSJohn Baldwin return (error); 82207f3485dSJohn Baldwin } 82307f3485dSJohn Baldwin 8248a5d815aSPeter Wemm /* 8258a5d815aSPeter Wemm * XXX A little bit lazy here. We could test if anything has 8268a5d815aSPeter Wemm * changed before crcopy() and setting P_SUGID. 8278a5d815aSPeter Wemm */ 82807f3485dSJohn Baldwin crcopy(newcred, oldcred); 8298a5d815aSPeter Wemm if (ngrp < 1) { 8308a5d815aSPeter Wemm /* 8318a5d815aSPeter Wemm * setgroups(0, NULL) is a legitimate way of clearing the 8328a5d815aSPeter Wemm * groups vector on non-BSD systems (which generally do not 8338a5d815aSPeter Wemm * have the egid in the groups[0]). We risk security holes 8348a5d815aSPeter Wemm * when running non-BSD software if we do not do the same. 8358a5d815aSPeter Wemm */ 836b1fc0ec1SRobert Watson newcred->cr_ngroups = 1; 8378a5d815aSPeter Wemm } else { 83807f3485dSJohn Baldwin bcopy(tempcred->cr_groups, newcred->cr_groups, 83907f3485dSJohn Baldwin ngrp * sizeof(gid_t)); 840b1fc0ec1SRobert Watson newcred->cr_ngroups = ngrp; 8418a5d815aSPeter Wemm } 842d5f81602SSean Eric Fagan setsugid(p); 843b1fc0ec1SRobert Watson p->p_ucred = newcred; 84407f3485dSJohn Baldwin PROC_UNLOCK(p); 84507f3485dSJohn Baldwin crfree(tempcred); 846b1fc0ec1SRobert Watson crfree(oldcred); 847835a82eeSMatthew Dillon mtx_unlock(&Giant); 84807f3485dSJohn Baldwin return (0); 849df8bae1dSRodney W. Grimes } 850df8bae1dSRodney W. Grimes 851d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 852df8bae1dSRodney W. Grimes struct setreuid_args { 85300999cd6SAndrey A. Chernov uid_t ruid; 85400999cd6SAndrey A. Chernov uid_t euid; 855df8bae1dSRodney W. Grimes }; 856d2d3e875SBruce Evans #endif 857835a82eeSMatthew Dillon /* 858835a82eeSMatthew Dillon * MPSAFE 859835a82eeSMatthew Dillon */ 860df8bae1dSRodney W. Grimes /* ARGSUSED */ 86126f9a767SRodney W. Grimes int 8624c44ad8eSJohn Baldwin setreuid(register struct thread *td, struct setreuid_args *uap) 863df8bae1dSRodney W. Grimes { 864b40ce416SJulian Elischer struct proc *p = td->td_proc; 865b1fc0ec1SRobert Watson struct ucred *newcred, *oldcred; 866eb725b4eSRobert Watson uid_t euid, ruid; 867eb725b4eSRobert Watson int error; 868df8bae1dSRodney W. Grimes 86900999cd6SAndrey A. Chernov euid = uap->euid; 870eb725b4eSRobert Watson ruid = uap->ruid; 871835a82eeSMatthew Dillon mtx_lock(&Giant); 87207f3485dSJohn Baldwin newcred = crget(); 87307f3485dSJohn Baldwin PROC_LOCK(p); 874b1fc0ec1SRobert Watson oldcred = p->p_ucred; 875b1fc0ec1SRobert Watson if (((ruid != (uid_t)-1 && ruid != oldcred->cr_ruid && 876b1fc0ec1SRobert Watson ruid != oldcred->cr_svuid) || 877b1fc0ec1SRobert Watson (euid != (uid_t)-1 && euid != oldcred->cr_uid && 878b1fc0ec1SRobert Watson euid != oldcred->cr_ruid && euid != oldcred->cr_svuid)) && 87907f3485dSJohn Baldwin (error = suser_cred(oldcred, PRISON_ROOT)) != 0) { 88007f3485dSJohn Baldwin PROC_UNLOCK(p); 88107f3485dSJohn Baldwin crfree(newcred); 88207f3485dSJohn Baldwin mtx_unlock(&Giant); 88307f3485dSJohn Baldwin return (error); 88407f3485dSJohn Baldwin } 88507f3485dSJohn Baldwin crcopy(newcred, oldcred); 886b1fc0ec1SRobert Watson if (euid != (uid_t)-1 && oldcred->cr_uid != euid) { 887b1fc0ec1SRobert Watson change_euid(newcred, euid); 888d5f81602SSean Eric Fagan setsugid(p); 889a89a5370SPeter Wemm } 890b1fc0ec1SRobert Watson if (ruid != (uid_t)-1 && oldcred->cr_ruid != ruid) { 891b1fc0ec1SRobert Watson change_ruid(newcred, ruid); 892d5f81602SSean Eric Fagan setsugid(p); 89300999cd6SAndrey A. Chernov } 894b1fc0ec1SRobert Watson if ((ruid != (uid_t)-1 || newcred->cr_uid != newcred->cr_ruid) && 895b1fc0ec1SRobert Watson newcred->cr_svuid != newcred->cr_uid) { 896b1fc0ec1SRobert Watson change_svuid(newcred, newcred->cr_uid); 897d5f81602SSean Eric Fagan setsugid(p); 898a89a5370SPeter Wemm } 899b1fc0ec1SRobert Watson p->p_ucred = newcred; 90007f3485dSJohn Baldwin PROC_UNLOCK(p); 901b1fc0ec1SRobert Watson crfree(oldcred); 902835a82eeSMatthew Dillon mtx_unlock(&Giant); 90307f3485dSJohn Baldwin return (0); 904df8bae1dSRodney W. Grimes } 905df8bae1dSRodney W. Grimes 906d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 907df8bae1dSRodney W. Grimes struct setregid_args { 90800999cd6SAndrey A. Chernov gid_t rgid; 90900999cd6SAndrey A. Chernov gid_t egid; 910df8bae1dSRodney W. Grimes }; 911d2d3e875SBruce Evans #endif 912835a82eeSMatthew Dillon /* 913835a82eeSMatthew Dillon * MPSAFE 914835a82eeSMatthew Dillon */ 915df8bae1dSRodney W. Grimes /* ARGSUSED */ 91626f9a767SRodney W. Grimes int 9174c44ad8eSJohn Baldwin setregid(register struct thread *td, struct setregid_args *uap) 918df8bae1dSRodney W. Grimes { 919b40ce416SJulian Elischer struct proc *p = td->td_proc; 920b1fc0ec1SRobert Watson struct ucred *newcred, *oldcred; 921eb725b4eSRobert Watson gid_t egid, rgid; 922eb725b4eSRobert Watson int error; 923df8bae1dSRodney W. Grimes 92400999cd6SAndrey A. Chernov egid = uap->egid; 925eb725b4eSRobert Watson rgid = uap->rgid; 926835a82eeSMatthew Dillon mtx_lock(&Giant); 92707f3485dSJohn Baldwin newcred = crget(); 92807f3485dSJohn Baldwin PROC_LOCK(p); 929b1fc0ec1SRobert Watson oldcred = p->p_ucred; 930b1fc0ec1SRobert Watson if (((rgid != (gid_t)-1 && rgid != oldcred->cr_rgid && 931b1fc0ec1SRobert Watson rgid != oldcred->cr_svgid) || 932b1fc0ec1SRobert Watson (egid != (gid_t)-1 && egid != oldcred->cr_groups[0] && 933b1fc0ec1SRobert Watson egid != oldcred->cr_rgid && egid != oldcred->cr_svgid)) && 93407f3485dSJohn Baldwin (error = suser_cred(oldcred, PRISON_ROOT)) != 0) { 93507f3485dSJohn Baldwin PROC_UNLOCK(p); 93607f3485dSJohn Baldwin crfree(newcred); 93707f3485dSJohn Baldwin mtx_unlock(&Giant); 93807f3485dSJohn Baldwin return (error); 93907f3485dSJohn Baldwin } 94007f3485dSJohn Baldwin 94107f3485dSJohn Baldwin crcopy(newcred, oldcred); 942b1fc0ec1SRobert Watson if (egid != (gid_t)-1 && oldcred->cr_groups[0] != egid) { 943b1fc0ec1SRobert Watson change_egid(newcred, egid); 944d5f81602SSean Eric Fagan setsugid(p); 945a89a5370SPeter Wemm } 946b1fc0ec1SRobert Watson if (rgid != (gid_t)-1 && oldcred->cr_rgid != rgid) { 947b1fc0ec1SRobert Watson change_rgid(newcred, rgid); 948d5f81602SSean Eric Fagan setsugid(p); 949a89a5370SPeter Wemm } 950b1fc0ec1SRobert Watson if ((rgid != (gid_t)-1 || newcred->cr_groups[0] != newcred->cr_rgid) && 951b1fc0ec1SRobert Watson newcred->cr_svgid != newcred->cr_groups[0]) { 952b1fc0ec1SRobert Watson change_svgid(newcred, newcred->cr_groups[0]); 953d5f81602SSean Eric Fagan setsugid(p); 954a89a5370SPeter Wemm } 9554589be70SRuslan Ermilov p->p_ucred = newcred; 95607f3485dSJohn Baldwin PROC_UNLOCK(p); 9574589be70SRuslan Ermilov crfree(oldcred); 958835a82eeSMatthew Dillon mtx_unlock(&Giant); 95907f3485dSJohn Baldwin return (0); 960df8bae1dSRodney W. Grimes } 961df8bae1dSRodney W. Grimes 9628ccd6334SPeter Wemm /* 9638ccd6334SPeter Wemm * setresuid(ruid, euid, suid) is like setreuid except control over the 9648ccd6334SPeter Wemm * saved uid is explicit. 9658ccd6334SPeter Wemm */ 9668ccd6334SPeter Wemm 9678ccd6334SPeter Wemm #ifndef _SYS_SYSPROTO_H_ 9688ccd6334SPeter Wemm struct setresuid_args { 9698ccd6334SPeter Wemm uid_t ruid; 9708ccd6334SPeter Wemm uid_t euid; 9718ccd6334SPeter Wemm uid_t suid; 9728ccd6334SPeter Wemm }; 9738ccd6334SPeter Wemm #endif 974835a82eeSMatthew Dillon /* 975835a82eeSMatthew Dillon * MPSAFE 976835a82eeSMatthew Dillon */ 9778ccd6334SPeter Wemm /* ARGSUSED */ 9788ccd6334SPeter Wemm int 9794c44ad8eSJohn Baldwin setresuid(register struct thread *td, struct setresuid_args *uap) 9808ccd6334SPeter Wemm { 981b40ce416SJulian Elischer struct proc *p = td->td_proc; 982b1fc0ec1SRobert Watson struct ucred *newcred, *oldcred; 983eb725b4eSRobert Watson uid_t euid, ruid, suid; 9848ccd6334SPeter Wemm int error; 9858ccd6334SPeter Wemm 9868ccd6334SPeter Wemm euid = uap->euid; 987eb725b4eSRobert Watson ruid = uap->ruid; 9888ccd6334SPeter Wemm suid = uap->suid; 989835a82eeSMatthew Dillon mtx_lock(&Giant); 99007f3485dSJohn Baldwin newcred = crget(); 99107f3485dSJohn Baldwin PROC_LOCK(p); 992b1fc0ec1SRobert Watson oldcred = p->p_ucred; 993b1fc0ec1SRobert Watson if (((ruid != (uid_t)-1 && ruid != oldcred->cr_ruid && 994b1fc0ec1SRobert Watson ruid != oldcred->cr_svuid && 995b1fc0ec1SRobert Watson ruid != oldcred->cr_uid) || 996b1fc0ec1SRobert Watson (euid != (uid_t)-1 && euid != oldcred->cr_ruid && 997b1fc0ec1SRobert Watson euid != oldcred->cr_svuid && 998b1fc0ec1SRobert Watson euid != oldcred->cr_uid) || 999b1fc0ec1SRobert Watson (suid != (uid_t)-1 && suid != oldcred->cr_ruid && 1000b1fc0ec1SRobert Watson suid != oldcred->cr_svuid && 1001b1fc0ec1SRobert Watson suid != oldcred->cr_uid)) && 100207f3485dSJohn Baldwin (error = suser_cred(oldcred, PRISON_ROOT)) != 0) { 100307f3485dSJohn Baldwin PROC_UNLOCK(p); 100407f3485dSJohn Baldwin crfree(newcred); 100507f3485dSJohn Baldwin mtx_unlock(&Giant); 100607f3485dSJohn Baldwin return (error); 100707f3485dSJohn Baldwin } 100807f3485dSJohn Baldwin 100907f3485dSJohn Baldwin crcopy(newcred, oldcred); 1010b1fc0ec1SRobert Watson if (euid != (uid_t)-1 && oldcred->cr_uid != euid) { 1011b1fc0ec1SRobert Watson change_euid(newcred, euid); 10128ccd6334SPeter Wemm setsugid(p); 10138ccd6334SPeter Wemm } 1014b1fc0ec1SRobert Watson if (ruid != (uid_t)-1 && oldcred->cr_ruid != ruid) { 1015b1fc0ec1SRobert Watson change_ruid(newcred, ruid); 10168ccd6334SPeter Wemm setsugid(p); 10178ccd6334SPeter Wemm } 1018b1fc0ec1SRobert Watson if (suid != (uid_t)-1 && oldcred->cr_svuid != suid) { 1019b1fc0ec1SRobert Watson change_svuid(newcred, suid); 10208ccd6334SPeter Wemm setsugid(p); 10218ccd6334SPeter Wemm } 1022b1fc0ec1SRobert Watson p->p_ucred = newcred; 102307f3485dSJohn Baldwin PROC_UNLOCK(p); 1024b1fc0ec1SRobert Watson crfree(oldcred); 1025835a82eeSMatthew Dillon mtx_unlock(&Giant); 102607f3485dSJohn Baldwin return (0); 10278ccd6334SPeter Wemm } 10288ccd6334SPeter Wemm 10298ccd6334SPeter Wemm /* 10308ccd6334SPeter Wemm * setresgid(rgid, egid, sgid) is like setregid except control over the 10318ccd6334SPeter Wemm * saved gid is explicit. 10328ccd6334SPeter Wemm */ 10338ccd6334SPeter Wemm 10348ccd6334SPeter Wemm #ifndef _SYS_SYSPROTO_H_ 10358ccd6334SPeter Wemm struct setresgid_args { 10368ccd6334SPeter Wemm gid_t rgid; 10378ccd6334SPeter Wemm gid_t egid; 10388ccd6334SPeter Wemm gid_t sgid; 10398ccd6334SPeter Wemm }; 10408ccd6334SPeter Wemm #endif 1041835a82eeSMatthew Dillon /* 1042835a82eeSMatthew Dillon * MPSAFE 1043835a82eeSMatthew Dillon */ 10448ccd6334SPeter Wemm /* ARGSUSED */ 10458ccd6334SPeter Wemm int 10464c44ad8eSJohn Baldwin setresgid(register struct thread *td, struct setresgid_args *uap) 10478ccd6334SPeter Wemm { 1048b40ce416SJulian Elischer struct proc *p = td->td_proc; 1049b1fc0ec1SRobert Watson struct ucred *newcred, *oldcred; 1050eb725b4eSRobert Watson gid_t egid, rgid, sgid; 10518ccd6334SPeter Wemm int error; 10528ccd6334SPeter Wemm 10538ccd6334SPeter Wemm egid = uap->egid; 1054eb725b4eSRobert Watson rgid = uap->rgid; 10558ccd6334SPeter Wemm sgid = uap->sgid; 1056835a82eeSMatthew Dillon mtx_lock(&Giant); 105707f3485dSJohn Baldwin newcred = crget(); 105807f3485dSJohn Baldwin PROC_LOCK(p); 1059b1fc0ec1SRobert Watson oldcred = p->p_ucred; 1060b1fc0ec1SRobert Watson if (((rgid != (gid_t)-1 && rgid != oldcred->cr_rgid && 1061b1fc0ec1SRobert Watson rgid != oldcred->cr_svgid && 1062b1fc0ec1SRobert Watson rgid != oldcred->cr_groups[0]) || 1063b1fc0ec1SRobert Watson (egid != (gid_t)-1 && egid != oldcred->cr_rgid && 1064b1fc0ec1SRobert Watson egid != oldcred->cr_svgid && 1065b1fc0ec1SRobert Watson egid != oldcred->cr_groups[0]) || 1066b1fc0ec1SRobert Watson (sgid != (gid_t)-1 && sgid != oldcred->cr_rgid && 1067b1fc0ec1SRobert Watson sgid != oldcred->cr_svgid && 1068b1fc0ec1SRobert Watson sgid != oldcred->cr_groups[0])) && 106907f3485dSJohn Baldwin (error = suser_cred(oldcred, PRISON_ROOT)) != 0) { 107007f3485dSJohn Baldwin PROC_UNLOCK(p); 107107f3485dSJohn Baldwin crfree(newcred); 107207f3485dSJohn Baldwin mtx_unlock(&Giant); 107307f3485dSJohn Baldwin return (error); 107407f3485dSJohn Baldwin } 107507f3485dSJohn Baldwin 107607f3485dSJohn Baldwin crcopy(newcred, oldcred); 1077b1fc0ec1SRobert Watson if (egid != (gid_t)-1 && oldcred->cr_groups[0] != egid) { 1078b1fc0ec1SRobert Watson change_egid(newcred, egid); 10798ccd6334SPeter Wemm setsugid(p); 10808ccd6334SPeter Wemm } 1081b1fc0ec1SRobert Watson if (rgid != (gid_t)-1 && oldcred->cr_rgid != rgid) { 1082b1fc0ec1SRobert Watson change_rgid(newcred, rgid); 10838ccd6334SPeter Wemm setsugid(p); 10848ccd6334SPeter Wemm } 1085b1fc0ec1SRobert Watson if (sgid != (gid_t)-1 && oldcred->cr_svgid != sgid) { 1086b1fc0ec1SRobert Watson change_svgid(newcred, sgid); 10878ccd6334SPeter Wemm setsugid(p); 10888ccd6334SPeter Wemm } 1089b1fc0ec1SRobert Watson p->p_ucred = newcred; 109007f3485dSJohn Baldwin PROC_UNLOCK(p); 1091b1fc0ec1SRobert Watson crfree(oldcred); 1092835a82eeSMatthew Dillon mtx_unlock(&Giant); 109307f3485dSJohn Baldwin return (0); 10948ccd6334SPeter Wemm } 10958ccd6334SPeter Wemm 10968ccd6334SPeter Wemm #ifndef _SYS_SYSPROTO_H_ 10978ccd6334SPeter Wemm struct getresuid_args { 10988ccd6334SPeter Wemm uid_t *ruid; 10998ccd6334SPeter Wemm uid_t *euid; 11008ccd6334SPeter Wemm uid_t *suid; 11018ccd6334SPeter Wemm }; 11028ccd6334SPeter Wemm #endif 1103835a82eeSMatthew Dillon /* 1104835a82eeSMatthew Dillon * MPSAFE 1105835a82eeSMatthew Dillon */ 11068ccd6334SPeter Wemm /* ARGSUSED */ 11078ccd6334SPeter Wemm int 11084c44ad8eSJohn Baldwin getresuid(register struct thread *td, struct getresuid_args *uap) 11098ccd6334SPeter Wemm { 1110835a82eeSMatthew Dillon struct ucred *cred; 11118ccd6334SPeter Wemm int error1 = 0, error2 = 0, error3 = 0; 11128ccd6334SPeter Wemm 1113d74ac681SMatthew Dillon cred = td->td_ucred; 11148ccd6334SPeter Wemm if (uap->ruid) 1115b1fc0ec1SRobert Watson error1 = copyout((caddr_t)&cred->cr_ruid, 1116b1fc0ec1SRobert Watson (caddr_t)uap->ruid, sizeof(cred->cr_ruid)); 11178ccd6334SPeter Wemm if (uap->euid) 1118b1fc0ec1SRobert Watson error2 = copyout((caddr_t)&cred->cr_uid, 1119b1fc0ec1SRobert Watson (caddr_t)uap->euid, sizeof(cred->cr_uid)); 11208ccd6334SPeter Wemm if (uap->suid) 1121b1fc0ec1SRobert Watson error3 = copyout((caddr_t)&cred->cr_svuid, 1122b1fc0ec1SRobert Watson (caddr_t)uap->suid, sizeof(cred->cr_svuid)); 1123eb725b4eSRobert Watson return (error1 ? error1 : error2 ? error2 : error3); 11248ccd6334SPeter Wemm } 11258ccd6334SPeter Wemm 11268ccd6334SPeter Wemm #ifndef _SYS_SYSPROTO_H_ 11278ccd6334SPeter Wemm struct getresgid_args { 11288ccd6334SPeter Wemm gid_t *rgid; 11298ccd6334SPeter Wemm gid_t *egid; 11308ccd6334SPeter Wemm gid_t *sgid; 11318ccd6334SPeter Wemm }; 11328ccd6334SPeter Wemm #endif 1133835a82eeSMatthew Dillon /* 1134835a82eeSMatthew Dillon * MPSAFE 1135835a82eeSMatthew Dillon */ 11368ccd6334SPeter Wemm /* ARGSUSED */ 11378ccd6334SPeter Wemm int 11384c44ad8eSJohn Baldwin getresgid(register struct thread *td, struct getresgid_args *uap) 11398ccd6334SPeter Wemm { 1140835a82eeSMatthew Dillon struct ucred *cred; 11418ccd6334SPeter Wemm int error1 = 0, error2 = 0, error3 = 0; 11428ccd6334SPeter Wemm 1143d74ac681SMatthew Dillon cred = td->td_ucred; 11448ccd6334SPeter Wemm if (uap->rgid) 1145b1fc0ec1SRobert Watson error1 = copyout((caddr_t)&cred->cr_rgid, 1146b1fc0ec1SRobert Watson (caddr_t)uap->rgid, sizeof(cred->cr_rgid)); 11478ccd6334SPeter Wemm if (uap->egid) 1148b1fc0ec1SRobert Watson error2 = copyout((caddr_t)&cred->cr_groups[0], 1149b1fc0ec1SRobert Watson (caddr_t)uap->egid, sizeof(cred->cr_groups[0])); 11508ccd6334SPeter Wemm if (uap->sgid) 1151b1fc0ec1SRobert Watson error3 = copyout((caddr_t)&cred->cr_svgid, 1152b1fc0ec1SRobert Watson (caddr_t)uap->sgid, sizeof(cred->cr_svgid)); 1153eb725b4eSRobert Watson return (error1 ? error1 : error2 ? error2 : error3); 11548ccd6334SPeter Wemm } 11558ccd6334SPeter Wemm 1156b67cbc65SPeter Wemm #ifndef _SYS_SYSPROTO_H_ 1157b67cbc65SPeter Wemm struct issetugid_args { 1158b67cbc65SPeter Wemm int dummy; 1159b67cbc65SPeter Wemm }; 1160b67cbc65SPeter Wemm #endif 1161eb725b4eSRobert Watson /* 1162eb725b4eSRobert Watson * NOT MPSAFE? 1163eb725b4eSRobert Watson */ 1164b67cbc65SPeter Wemm /* ARGSUSED */ 1165b67cbc65SPeter Wemm int 11664c44ad8eSJohn Baldwin issetugid(register struct thread *td, struct issetugid_args *uap) 1167b67cbc65SPeter Wemm { 1168b40ce416SJulian Elischer struct proc *p = td->td_proc; 1169b40ce416SJulian Elischer 1170b67cbc65SPeter Wemm /* 1171b67cbc65SPeter Wemm * Note: OpenBSD sets a P_SUGIDEXEC flag set at execve() time, 1172b67cbc65SPeter Wemm * we use P_SUGID because we consider changing the owners as 1173b67cbc65SPeter Wemm * "tainting" as well. 1174b67cbc65SPeter Wemm * This is significant for procs that start as root and "become" 1175b67cbc65SPeter Wemm * a user without an exec - programs cannot know *everything* 1176b67cbc65SPeter Wemm * that libc *might* have put in their data segment. 1177b67cbc65SPeter Wemm */ 1178f591779bSSeigo Tanimura PROC_LOCK(p); 1179b40ce416SJulian Elischer td->td_retval[0] = (p->p_flag & P_SUGID) ? 1 : 0; 1180f591779bSSeigo Tanimura PROC_UNLOCK(p); 1181b67cbc65SPeter Wemm return (0); 1182b67cbc65SPeter Wemm } 1183b67cbc65SPeter Wemm 1184835a82eeSMatthew Dillon /* 1185835a82eeSMatthew Dillon * MPSAFE 1186835a82eeSMatthew Dillon */ 1187130d0157SRobert Watson int 11884c44ad8eSJohn Baldwin __setugid(struct thread *td, struct __setugid_args *uap) 1189130d0157SRobert Watson { 1190130d0157SRobert Watson #ifdef REGRESSION 119107f3485dSJohn Baldwin struct proc *p; 1192835a82eeSMatthew Dillon 119307f3485dSJohn Baldwin p = td->td_proc; 1194130d0157SRobert Watson switch (uap->flag) { 1195130d0157SRobert Watson case 0: 119607f3485dSJohn Baldwin mtx_lock(&Giant); 119707f3485dSJohn Baldwin PROC_LOCK(p); 119807f3485dSJohn Baldwin p->p_flag &= ~P_SUGID; 119907f3485dSJohn Baldwin PROC_UNLOCK(p); 1200835a82eeSMatthew Dillon mtx_unlock(&Giant); 120107f3485dSJohn Baldwin return (0); 120207f3485dSJohn Baldwin case 1: 120307f3485dSJohn Baldwin mtx_lock(&Giant); 120407f3485dSJohn Baldwin PROC_LOCK(p); 120507f3485dSJohn Baldwin p->p_flag |= P_SUGID; 120607f3485dSJohn Baldwin PROC_UNLOCK(p); 120707f3485dSJohn Baldwin mtx_unlock(&Giant); 120807f3485dSJohn Baldwin return (0); 120907f3485dSJohn Baldwin default: 121007f3485dSJohn Baldwin return (EINVAL); 121107f3485dSJohn Baldwin } 1212130d0157SRobert Watson #else /* !REGRESSION */ 1213eb725b4eSRobert Watson 1214130d0157SRobert Watson return (ENOSYS); 1215eb725b4eSRobert Watson #endif /* REGRESSION */ 1216130d0157SRobert Watson } 1217130d0157SRobert Watson 1218df8bae1dSRodney W. Grimes /* 1219df8bae1dSRodney W. Grimes * Check if gid is a member of the group set. 1220d74ac681SMatthew Dillon * 1221d74ac681SMatthew Dillon * MPSAFE (cred must be held) 1222df8bae1dSRodney W. Grimes */ 122326f9a767SRodney W. Grimes int 12244c44ad8eSJohn Baldwin groupmember(gid_t gid, struct ucred *cred) 1225df8bae1dSRodney W. Grimes { 1226df8bae1dSRodney W. Grimes register gid_t *gp; 1227df8bae1dSRodney W. Grimes gid_t *egp; 1228df8bae1dSRodney W. Grimes 1229df8bae1dSRodney W. Grimes egp = &(cred->cr_groups[cred->cr_ngroups]); 1230df8bae1dSRodney W. Grimes for (gp = cred->cr_groups; gp < egp; gp++) 1231df8bae1dSRodney W. Grimes if (*gp == gid) 1232df8bae1dSRodney W. Grimes return (1); 1233df8bae1dSRodney W. Grimes return (0); 1234df8bae1dSRodney W. Grimes } 1235df8bae1dSRodney W. Grimes 12363b243b72SRobert Watson /* 1237d0615c64SAndrew R. Reiter * `suser_enabled' (which can be set by the security.suser_enabled 12387fd6a959SRobert Watson * sysctl) determines whether the system 'super-user' policy is in effect. 12397fd6a959SRobert Watson * If it is nonzero, an effective uid of 0 connotes special privilege, 12407fd6a959SRobert Watson * overriding many mandatory and discretionary protections. If it is zero, 12417fd6a959SRobert Watson * uid 0 is offered no special privilege in the kernel security policy. 12427fd6a959SRobert Watson * Setting it to zero may seriously impact the functionality of many 12437fd6a959SRobert Watson * existing userland programs, and should not be done without careful 12447fd6a959SRobert Watson * consideration of the consequences. 12453b243b72SRobert Watson */ 124693f4fd1cSRobert Watson int suser_enabled = 1; 1247d0615c64SAndrew R. Reiter SYSCTL_INT(_security_bsd, OID_AUTO, suser_enabled, CTLFLAG_RW, 124893f4fd1cSRobert Watson &suser_enabled, 0, "processes with uid 0 have privilege"); 1249d0615c64SAndrew R. Reiter TUNABLE_INT("security.bsd.suser_enabled", &suser_enabled); 1250579f4eb4SRobert Watson 1251df8bae1dSRodney W. Grimes /* 12527fd6a959SRobert Watson * Test whether the specified credentials imply "super-user" privilege. 125344731cabSJohn Baldwin * Return 0 or EPERM. The flag argument is currently used only to 125444731cabSJohn Baldwin * specify jail interaction. 1255df8bae1dSRodney W. Grimes */ 125626f9a767SRodney W. Grimes int 125744731cabSJohn Baldwin suser_cred(struct ucred *cred, int flag) 1258f711d546SPoul-Henning Kamp { 1259eb725b4eSRobert Watson 126093f4fd1cSRobert Watson if (!suser_enabled) 126103095547SRobert Watson return (EPERM); 126275c13541SPoul-Henning Kamp if (cred->cr_uid != 0) 126375c13541SPoul-Henning Kamp return (EPERM); 126491421ba2SRobert Watson if (jailed(cred) && !(flag & PRISON_ROOT)) 126575c13541SPoul-Henning Kamp return (EPERM); 126675c13541SPoul-Henning Kamp return (0); 126775c13541SPoul-Henning Kamp } 1268df8bae1dSRodney W. Grimes 12693ca719f1SRobert Watson /* 127044731cabSJohn Baldwin * Shortcut to hide contents of struct td and struct proc from the 127144731cabSJohn Baldwin * caller, promoting binary compatibility. 127244731cabSJohn Baldwin */ 127344731cabSJohn Baldwin int 127444731cabSJohn Baldwin suser(struct thread *td) 127544731cabSJohn Baldwin { 127644731cabSJohn Baldwin 127744731cabSJohn Baldwin return (suser_cred(td->td_ucred, 0)); 127844731cabSJohn Baldwin } 127944731cabSJohn Baldwin 128044731cabSJohn Baldwin /* 1281eb725b4eSRobert Watson * Test the active securelevel against a given level. securelevel_gt() 1282eb725b4eSRobert Watson * implements (securelevel > level). securelevel_ge() implements 1283eb725b4eSRobert Watson * (securelevel >= level). Note that the logic is inverted -- these 1284eb725b4eSRobert Watson * functions return EPERM on "success" and 0 on "failure". 12853ca719f1SRobert Watson * 1286d74ac681SMatthew Dillon * MPSAFE 12873ca719f1SRobert Watson */ 12883ca719f1SRobert Watson int 12893ca719f1SRobert Watson securelevel_gt(struct ucred *cr, int level) 12903ca719f1SRobert Watson { 1291eb725b4eSRobert Watson int active_securelevel; 12923ca719f1SRobert Watson 1293eb725b4eSRobert Watson active_securelevel = securelevel; 129470499328SJohn Baldwin KASSERT(cr != NULL, ("securelevel_gt: null cr")); 129501137630SRobert Watson if (cr->cr_prison != NULL) { 129601137630SRobert Watson mtx_lock(&cr->cr_prison->pr_mtx); 1297eb725b4eSRobert Watson active_securelevel = imax(cr->cr_prison->pr_securelevel, 1298eb725b4eSRobert Watson active_securelevel); 129901137630SRobert Watson mtx_unlock(&cr->cr_prison->pr_mtx); 130001137630SRobert Watson } 1301eb725b4eSRobert Watson return (active_securelevel > level ? EPERM : 0); 13023ca719f1SRobert Watson } 13033ca719f1SRobert Watson 13043ca719f1SRobert Watson int 13053ca719f1SRobert Watson securelevel_ge(struct ucred *cr, int level) 13063ca719f1SRobert Watson { 1307eb725b4eSRobert Watson int active_securelevel; 13083ca719f1SRobert Watson 1309eb725b4eSRobert Watson active_securelevel = securelevel; 131070499328SJohn Baldwin KASSERT(cr != NULL, ("securelevel_ge: null cr")); 131101137630SRobert Watson if (cr->cr_prison != NULL) { 131201137630SRobert Watson mtx_lock(&cr->cr_prison->pr_mtx); 1313eb725b4eSRobert Watson active_securelevel = imax(cr->cr_prison->pr_securelevel, 1314eb725b4eSRobert Watson active_securelevel); 131501137630SRobert Watson mtx_unlock(&cr->cr_prison->pr_mtx); 131601137630SRobert Watson } 1317eb725b4eSRobert Watson return (active_securelevel >= level ? EPERM : 0); 13183ca719f1SRobert Watson } 13193ca719f1SRobert Watson 13208a7d8cc6SRobert Watson /* 1321e409590dSRobert Watson * 'see_other_uids' determines whether or not visibility of processes 1322eb725b4eSRobert Watson * and sockets with credentials holding different real uids is possible 132348713bdcSRobert Watson * using a variety of system MIBs. 1324eb725b4eSRobert Watson * XXX: data declarations should be together near the beginning of the file. 13258a7d8cc6SRobert Watson */ 1326e409590dSRobert Watson static int see_other_uids = 1; 1327d0615c64SAndrew R. Reiter SYSCTL_INT(_security_bsd, OID_AUTO, see_other_uids, CTLFLAG_RW, 1328eb725b4eSRobert Watson &see_other_uids, 0, 13298a7d8cc6SRobert Watson "Unprivileged processes may see subjects/objects with different real uid"); 13308a7d8cc6SRobert Watson 13317fd6a959SRobert Watson /*- 13321b350b45SRobert Watson * Determine if u1 "can see" the subject specified by u2, according to the 13331b350b45SRobert Watson * 'see_other_uids' policy. 13341b350b45SRobert Watson * Returns: 0 for permitted, ESRCH otherwise 13351b350b45SRobert Watson * Locks: none 13361b350b45SRobert Watson * References: *u1 and *u2 must not change during the call 13371b350b45SRobert Watson * u1 may equal u2, in which case only one reference is required 13381b350b45SRobert Watson */ 13391b350b45SRobert Watson static int 13401b350b45SRobert Watson cr_seeotheruids(struct ucred *u1, struct ucred *u2) 13411b350b45SRobert Watson { 13421b350b45SRobert Watson 13431b350b45SRobert Watson if (!see_other_uids && u1->cr_ruid != u2->cr_ruid) { 134444731cabSJohn Baldwin if (suser_cred(u1, PRISON_ROOT) != 0) 13451b350b45SRobert Watson return (ESRCH); 13461b350b45SRobert Watson } 13471b350b45SRobert Watson return (0); 13481b350b45SRobert Watson } 13491b350b45SRobert Watson 13501b350b45SRobert Watson /*- 13517fd6a959SRobert Watson * Determine if u1 "can see" the subject specified by u2. 1352ed639720SRobert Watson * Returns: 0 for permitted, an errno value otherwise 1353ed639720SRobert Watson * Locks: none 1354eb725b4eSRobert Watson * References: *u1 and *u2 must not change during the call 1355ed639720SRobert Watson * u1 may equal u2, in which case only one reference is required 1356ed639720SRobert Watson */ 1357ed639720SRobert Watson int 135894088977SRobert Watson cr_cansee(struct ucred *u1, struct ucred *u2) 1359a9e0361bSPoul-Henning Kamp { 136091421ba2SRobert Watson int error; 1361a9e0361bSPoul-Henning Kamp 1362ed639720SRobert Watson if ((error = prison_check(u1, u2))) 136391421ba2SRobert Watson return (error); 13641b350b45SRobert Watson if ((error = cr_seeotheruids(u1, u2))) 13651b350b45SRobert Watson return (error); 1366387d2c03SRobert Watson return (0); 1367387d2c03SRobert Watson } 1368387d2c03SRobert Watson 13697fd6a959SRobert Watson /*- 13707fd6a959SRobert Watson * Determine if p1 "can see" the subject specified by p2. 13713b243b72SRobert Watson * Returns: 0 for permitted, an errno value otherwise 13727fd6a959SRobert Watson * Locks: Sufficient locks to protect p1->p_ucred and p2->p_ucred must 13733b243b72SRobert Watson * be held. Normally, p1 will be curproc, and a lock must be held 13743b243b72SRobert Watson * for p2. 13753b243b72SRobert Watson * References: p1 and p2 must be valid for the lifetime of the call 13763b243b72SRobert Watson */ 1377a0f75161SRobert Watson int 1378a0f75161SRobert Watson p_cansee(struct proc *p1, struct proc *p2) 1379ed639720SRobert Watson { 1380ed639720SRobert Watson 138194088977SRobert Watson /* Wrap cr_cansee() for all functionality. */ 138294088977SRobert Watson return (cr_cansee(p1->p_ucred, p2->p_ucred)); 1383ed639720SRobert Watson } 1384ed639720SRobert Watson 13857fd6a959SRobert Watson /*- 1386c83f8015SRobert Watson * Determine whether cred may deliver the specified signal to proc. 1387c83f8015SRobert Watson * Returns: 0 for permitted, an errno value otherwise. 1388c83f8015SRobert Watson * Locks: A lock must be held for proc. 1389c83f8015SRobert Watson * References: cred and proc must be valid for the lifetime of the call. 13904c5eb9c3SRobert Watson */ 13914c5eb9c3SRobert Watson int 1392c83f8015SRobert Watson cr_cansignal(struct ucred *cred, struct proc *proc, int signum) 1393387d2c03SRobert Watson { 139491421ba2SRobert Watson int error; 1395387d2c03SRobert Watson 13964c5eb9c3SRobert Watson /* 1397c83f8015SRobert Watson * Jail semantics limit the scope of signalling to proc in the 1398c83f8015SRobert Watson * same jail as cred, if cred is in jail. 13994c5eb9c3SRobert Watson */ 1400c83f8015SRobert Watson error = prison_check(cred, proc->p_ucred); 1401c83f8015SRobert Watson if (error) 140291421ba2SRobert Watson return (error); 14031b350b45SRobert Watson error = cr_seeotheruids(cred, proc->p_ucred); 14041b350b45SRobert Watson if (error) 14051b350b45SRobert Watson return (error); 1406387d2c03SRobert Watson 1407387d2c03SRobert Watson /* 14083b243b72SRobert Watson * UNIX signal semantics depend on the status of the P_SUGID 14093b243b72SRobert Watson * bit on the target process. If the bit is set, then additional 14103b243b72SRobert Watson * restrictions are placed on the set of available signals. 14114c5eb9c3SRobert Watson */ 1412c83f8015SRobert Watson if (proc->p_flag & P_SUGID) { 14134c5eb9c3SRobert Watson switch (signum) { 14144c5eb9c3SRobert Watson case 0: 14154c5eb9c3SRobert Watson case SIGKILL: 14164c5eb9c3SRobert Watson case SIGINT: 14174c5eb9c3SRobert Watson case SIGTERM: 14184c5eb9c3SRobert Watson case SIGSTOP: 14194c5eb9c3SRobert Watson case SIGTTIN: 14204c5eb9c3SRobert Watson case SIGTTOU: 14214c5eb9c3SRobert Watson case SIGTSTP: 14224c5eb9c3SRobert Watson case SIGHUP: 14234c5eb9c3SRobert Watson case SIGUSR1: 14244c5eb9c3SRobert Watson case SIGUSR2: 14257fd6a959SRobert Watson /* 14267fd6a959SRobert Watson * Generally, permit job and terminal control 14277fd6a959SRobert Watson * signals. 14287fd6a959SRobert Watson */ 14294c5eb9c3SRobert Watson break; 14304c5eb9c3SRobert Watson default: 1431c83f8015SRobert Watson /* Not permitted without privilege. */ 143244731cabSJohn Baldwin error = suser_cred(cred, PRISON_ROOT); 14334c5eb9c3SRobert Watson if (error) 14344c5eb9c3SRobert Watson return (error); 14354c5eb9c3SRobert Watson } 1436e9e7ff5bSRobert Watson } 1437e9e7ff5bSRobert Watson 14384c5eb9c3SRobert Watson /* 14393b243b72SRobert Watson * Generally, the target credential's ruid or svuid must match the 1440e9e7ff5bSRobert Watson * subject credential's ruid or euid. 14414c5eb9c3SRobert Watson */ 1442c83f8015SRobert Watson if (cred->cr_ruid != proc->p_ucred->cr_ruid && 1443c83f8015SRobert Watson cred->cr_ruid != proc->p_ucred->cr_svuid && 1444c83f8015SRobert Watson cred->cr_uid != proc->p_ucred->cr_ruid && 1445c83f8015SRobert Watson cred->cr_uid != proc->p_ucred->cr_svuid) { 1446c83f8015SRobert Watson /* Not permitted without privilege. */ 144744731cabSJohn Baldwin error = suser_cred(cred, PRISON_ROOT); 14484c5eb9c3SRobert Watson if (error) 14494c5eb9c3SRobert Watson return (error); 14504c5eb9c3SRobert Watson } 1451387d2c03SRobert Watson 1452387d2c03SRobert Watson return (0); 1453387d2c03SRobert Watson } 1454a9e0361bSPoul-Henning Kamp 1455c83f8015SRobert Watson 1456c83f8015SRobert Watson /*- 1457c83f8015SRobert Watson * Determine whether p1 may deliver the specified signal to p2. 1458c83f8015SRobert Watson * Returns: 0 for permitted, an errno value otherwise 1459c83f8015SRobert Watson * Locks: Sufficient locks to protect various components of p1 and p2 1460c83f8015SRobert Watson * must be held. Normally, p1 will be curproc, and a lock must 1461c83f8015SRobert Watson * be held for p2. 1462c83f8015SRobert Watson * References: p1 and p2 must be valid for the lifetime of the call 1463c83f8015SRobert Watson */ 1464c83f8015SRobert Watson int 1465c83f8015SRobert Watson p_cansignal(struct proc *p1, struct proc *p2, int signum) 1466c83f8015SRobert Watson { 1467c83f8015SRobert Watson 1468c83f8015SRobert Watson if (p1 == p2) 1469c83f8015SRobert Watson return (0); 1470c83f8015SRobert Watson 1471c83f8015SRobert Watson /* 1472c83f8015SRobert Watson * UNIX signalling semantics require that processes in the same 1473c83f8015SRobert Watson * session always be able to deliver SIGCONT to one another, 1474c83f8015SRobert Watson * overriding the remaining protections. 1475c83f8015SRobert Watson */ 1476c83f8015SRobert Watson if (signum == SIGCONT && p1->p_session == p2->p_session) 1477c83f8015SRobert Watson return (0); 1478c83f8015SRobert Watson 1479c83f8015SRobert Watson return (cr_cansignal(p1->p_ucred, p2, signum)); 1480c83f8015SRobert Watson } 1481c83f8015SRobert Watson 14827fd6a959SRobert Watson /*- 1483eb725b4eSRobert Watson * Determine whether p1 may reschedule p2. 14847fd6a959SRobert Watson * Returns: 0 for permitted, an errno value otherwise 14853b243b72SRobert Watson * Locks: Sufficient locks to protect various components of p1 and p2 14863b243b72SRobert Watson * must be held. Normally, p1 will be curproc, and a lock must 14877fd6a959SRobert Watson * be held for p2. 14883b243b72SRobert Watson * References: p1 and p2 must be valid for the lifetime of the call 14893b243b72SRobert Watson */ 1490a0f75161SRobert Watson int 1491a0f75161SRobert Watson p_cansched(struct proc *p1, struct proc *p2) 1492387d2c03SRobert Watson { 149391421ba2SRobert Watson int error; 1494387d2c03SRobert Watson 1495387d2c03SRobert Watson if (p1 == p2) 1496387d2c03SRobert Watson return (0); 149791421ba2SRobert Watson if ((error = prison_check(p1->p_ucred, p2->p_ucred))) 149891421ba2SRobert Watson return (error); 14991b350b45SRobert Watson if ((error = cr_seeotheruids(p1->p_ucred, p2->p_ucred))) 15001b350b45SRobert Watson return (error); 1501b1fc0ec1SRobert Watson if (p1->p_ucred->cr_ruid == p2->p_ucred->cr_ruid) 1502387d2c03SRobert Watson return (0); 1503b1fc0ec1SRobert Watson if (p1->p_ucred->cr_uid == p2->p_ucred->cr_ruid) 1504387d2c03SRobert Watson return (0); 150544731cabSJohn Baldwin if (suser_cred(p1->p_ucred, PRISON_ROOT) == 0) 1506387d2c03SRobert Watson return (0); 1507387d2c03SRobert Watson 1508387d2c03SRobert Watson #ifdef CAPABILITIES 15094df571b1SRobert Watson if (!cap_check(NULL, p1, CAP_SYS_NICE, PRISON_ROOT)) 1510387d2c03SRobert Watson return (0); 1511387d2c03SRobert Watson #endif 1512387d2c03SRobert Watson 1513387d2c03SRobert Watson return (EPERM); 1514387d2c03SRobert Watson } 1515387d2c03SRobert Watson 15163b243b72SRobert Watson /* 15175d476e73SRobert Watson * The 'unprivileged_proc_debug' flag may be used to disable a variety of 15185d476e73SRobert Watson * unprivileged inter-process debugging services, including some procfs 15195d476e73SRobert Watson * functionality, ptrace(), and ktrace(). In the past, inter-process 15205d476e73SRobert Watson * debugging has been involved in a variety of security problems, and sites 15215d476e73SRobert Watson * not requiring the service might choose to disable it when hardening 15225d476e73SRobert Watson * systems. 15233b243b72SRobert Watson * 15243b243b72SRobert Watson * XXX: Should modifying and reading this variable require locking? 1525eb725b4eSRobert Watson * XXX: data declarations should be together near the beginning of the file. 15263b243b72SRobert Watson */ 1527e409590dSRobert Watson static int unprivileged_proc_debug = 1; 1528d0615c64SAndrew R. Reiter SYSCTL_INT(_security_bsd, OID_AUTO, unprivileged_proc_debug, CTLFLAG_RW, 1529eb725b4eSRobert Watson &unprivileged_proc_debug, 0, 15300ef5652eSRobert Watson "Unprivileged processes may use process debugging facilities"); 15310ef5652eSRobert Watson 15327fd6a959SRobert Watson /*- 15337fd6a959SRobert Watson * Determine whether p1 may debug p2. 15347fd6a959SRobert Watson * Returns: 0 for permitted, an errno value otherwise 15357fd6a959SRobert Watson * Locks: Sufficient locks to protect various components of p1 and p2 15367fd6a959SRobert Watson * must be held. Normally, p1 will be curproc, and a lock must 15377fd6a959SRobert Watson * be held for p2. 15383b243b72SRobert Watson * References: p1 and p2 must be valid for the lifetime of the call 15393b243b72SRobert Watson */ 1540a0f75161SRobert Watson int 1541a0f75161SRobert Watson p_candebug(struct proc *p1, struct proc *p2) 1542387d2c03SRobert Watson { 1543eb725b4eSRobert Watson int credentialchanged, error, grpsubset, i, uidsubset; 1544387d2c03SRobert Watson 1545e409590dSRobert Watson if (!unprivileged_proc_debug) { 154644731cabSJohn Baldwin error = suser_cred(p1->p_ucred, PRISON_ROOT); 154732d18604SRobert Watson if (error) 154832d18604SRobert Watson return (error); 154932d18604SRobert Watson } 155023fad5b6SDag-Erling Smørgrav if (p1 == p2) 155123fad5b6SDag-Erling Smørgrav return (0); 155291421ba2SRobert Watson if ((error = prison_check(p1->p_ucred, p2->p_ucred))) 155391421ba2SRobert Watson return (error); 15541b350b45SRobert Watson if ((error = cr_seeotheruids(p1->p_ucred, p2->p_ucred))) 15551b350b45SRobert Watson return (error); 1556387d2c03SRobert Watson 15577fd6a959SRobert Watson /* 1558db42a33dSRobert Watson * Is p2's group set a subset of p1's effective group set? This 1559db42a33dSRobert Watson * includes p2's egid, group access list, rgid, and svgid. 15607fd6a959SRobert Watson */ 1561db42a33dSRobert Watson grpsubset = 1; 1562db42a33dSRobert Watson for (i = 0; i < p2->p_ucred->cr_ngroups; i++) { 1563db42a33dSRobert Watson if (!groupmember(p2->p_ucred->cr_groups[i], p1->p_ucred)) { 1564db42a33dSRobert Watson grpsubset = 0; 1565db42a33dSRobert Watson break; 1566db42a33dSRobert Watson } 1567db42a33dSRobert Watson } 1568db42a33dSRobert Watson grpsubset = grpsubset && 1569db42a33dSRobert Watson groupmember(p2->p_ucred->cr_rgid, p1->p_ucred) && 1570db42a33dSRobert Watson groupmember(p2->p_ucred->cr_svgid, p1->p_ucred); 1571db42a33dSRobert Watson 1572db42a33dSRobert Watson /* 1573db42a33dSRobert Watson * Are the uids present in p2's credential equal to p1's 1574db42a33dSRobert Watson * effective uid? This includes p2's euid, svuid, and ruid. 1575db42a33dSRobert Watson */ 1576db42a33dSRobert Watson uidsubset = (p1->p_ucred->cr_uid == p2->p_ucred->cr_uid && 1577db42a33dSRobert Watson p1->p_ucred->cr_uid == p2->p_ucred->cr_svuid && 1578db42a33dSRobert Watson p1->p_ucred->cr_uid == p2->p_ucred->cr_ruid); 1579db42a33dSRobert Watson 1580db42a33dSRobert Watson /* 1581db42a33dSRobert Watson * Has the credential of the process changed since the last exec()? 1582db42a33dSRobert Watson */ 1583db42a33dSRobert Watson credentialchanged = (p2->p_flag & P_SUGID); 1584db42a33dSRobert Watson 1585db42a33dSRobert Watson /* 1586db42a33dSRobert Watson * If p2's gids aren't a subset, or the uids aren't a subset, 1587db42a33dSRobert Watson * or the credential has changed, require appropriate privilege 1588db42a33dSRobert Watson * for p1 to debug p2. For POSIX.1e capabilities, this will 1589db42a33dSRobert Watson * require CAP_SYS_PTRACE. 1590db42a33dSRobert Watson */ 1591db42a33dSRobert Watson if (!grpsubset || !uidsubset || credentialchanged) { 159244731cabSJohn Baldwin error = suser_cred(p1->p_ucred, PRISON_ROOT); 159332d18604SRobert Watson if (error) 1594387d2c03SRobert Watson return (error); 15957fd6a959SRobert Watson } 1596387d2c03SRobert Watson 1597eb725b4eSRobert Watson /* Can't trace init when securelevel > 0. */ 1598eb725b4eSRobert Watson if (p2 == initproc) { 15993ca719f1SRobert Watson error = securelevel_gt(p1->p_ucred, 0); 16003ca719f1SRobert Watson if (error) 16013ca719f1SRobert Watson return (error); 16023ca719f1SRobert Watson } 1603387d2c03SRobert Watson 16045fab7614SRobert Watson /* 16055fab7614SRobert Watson * Can't trace a process that's currently exec'ing. 16065fab7614SRobert Watson * XXX: Note, this is not a security policy decision, it's a 16075fab7614SRobert Watson * basic correctness/functionality decision. Therefore, this check 16085fab7614SRobert Watson * should be moved to the caller's of p_candebug(). 16095fab7614SRobert Watson */ 16109ca45e81SDag-Erling Smørgrav if ((p2->p_flag & P_INEXEC) != 0) 16119ca45e81SDag-Erling Smørgrav return (EAGAIN); 16129ca45e81SDag-Erling Smørgrav 1613387d2c03SRobert Watson return (0); 1614387d2c03SRobert Watson } 1615387d2c03SRobert Watson 161629dc1288SRobert Watson /*- 161729dc1288SRobert Watson * Determine whether the subject represented by cred can "see" a socket. 161829dc1288SRobert Watson * Returns: 0 for permitted, ENOENT otherwise. 161929dc1288SRobert Watson */ 162029dc1288SRobert Watson int 162129dc1288SRobert Watson cr_canseesocket(struct ucred *cred, struct socket *so) 162229dc1288SRobert Watson { 162329dc1288SRobert Watson int error; 162429dc1288SRobert Watson 162529dc1288SRobert Watson error = prison_check(cred, so->so_cred); 162629dc1288SRobert Watson if (error) 162729dc1288SRobert Watson return (ENOENT); 162829dc1288SRobert Watson if (cr_seeotheruids(cred, so->so_cred)) 162929dc1288SRobert Watson return (ENOENT); 163029dc1288SRobert Watson #ifdef MAC 163129dc1288SRobert Watson /* XXX: error = mac_cred_check_seesocket() here. */ 163229dc1288SRobert Watson #endif 163329dc1288SRobert Watson 163429dc1288SRobert Watson return (0); 163529dc1288SRobert Watson } 163629dc1288SRobert Watson 1637a9e0361bSPoul-Henning Kamp /* 1638df8bae1dSRodney W. Grimes * Allocate a zeroed cred structure. 1639df8bae1dSRodney W. Grimes */ 1640df8bae1dSRodney W. Grimes struct ucred * 16414c44ad8eSJohn Baldwin crget(void) 1642df8bae1dSRodney W. Grimes { 1643df8bae1dSRodney W. Grimes register struct ucred *cr; 1644df8bae1dSRodney W. Grimes 16451e5d626aSAlfred Perlstein MALLOC(cr, struct ucred *, sizeof(*cr), M_CRED, M_WAITOK | M_ZERO); 1646df8bae1dSRodney W. Grimes cr->cr_ref = 1; 1647e1bca29fSMatthew Dillon cr->cr_mtxp = mtx_pool_find(cr); 1648df8bae1dSRodney W. Grimes return (cr); 1649df8bae1dSRodney W. Grimes } 1650df8bae1dSRodney W. Grimes 1651df8bae1dSRodney W. Grimes /* 16527fd6a959SRobert Watson * Claim another reference to a ucred structure. 16535c3f70d7SAlfred Perlstein */ 1654bd78ceceSJohn Baldwin struct ucred * 16554c44ad8eSJohn Baldwin crhold(struct ucred *cr) 16565c3f70d7SAlfred Perlstein { 16575c3f70d7SAlfred Perlstein 1658e1bca29fSMatthew Dillon mtx_lock(cr->cr_mtxp); 16595c3f70d7SAlfred Perlstein cr->cr_ref++; 1660e1bca29fSMatthew Dillon mtx_unlock(cr->cr_mtxp); 1661bd78ceceSJohn Baldwin return (cr); 16625c3f70d7SAlfred Perlstein } 16635c3f70d7SAlfred Perlstein 16645c3f70d7SAlfred Perlstein /* 1665df8bae1dSRodney W. Grimes * Free a cred structure. 1666df8bae1dSRodney W. Grimes * Throws away space when ref count gets to 0. 1667df8bae1dSRodney W. Grimes */ 166826f9a767SRodney W. Grimes void 16694c44ad8eSJohn Baldwin crfree(struct ucred *cr) 1670df8bae1dSRodney W. Grimes { 1671e1bca29fSMatthew Dillon struct mtx *mtxp = cr->cr_mtxp; 16721e5d626aSAlfred Perlstein 1673e1bca29fSMatthew Dillon mtx_lock(mtxp); 1674e04670b7SAlfred Perlstein KASSERT(cr->cr_ref > 0, ("bad ucred refcount: %d", cr->cr_ref)); 1675f535380cSDon Lewis if (--cr->cr_ref == 0) { 1676f535380cSDon Lewis /* 1677f535380cSDon Lewis * Some callers of crget(), such as nfs_statfs(), 1678f535380cSDon Lewis * allocate a temporary credential, but don't 1679f535380cSDon Lewis * allocate a uidinfo structure. 1680f535380cSDon Lewis */ 1681e1bca29fSMatthew Dillon mtx_unlock(mtxp); 1682c1a513c9SJohn Baldwin mtx_lock(&Giant); 1683f535380cSDon Lewis if (cr->cr_uidinfo != NULL) 1684f535380cSDon Lewis uifree(cr->cr_uidinfo); 1685823c224eSRobert Watson if (cr->cr_ruidinfo != NULL) 1686823c224eSRobert Watson uifree(cr->cr_ruidinfo); 168791421ba2SRobert Watson /* 168891421ba2SRobert Watson * Free a prison, if any. 168991421ba2SRobert Watson */ 169091421ba2SRobert Watson if (jailed(cr)) 169191421ba2SRobert Watson prison_free(cr->cr_prison); 1692df8bae1dSRodney W. Grimes FREE((caddr_t)cr, M_CRED); 1693c1a513c9SJohn Baldwin mtx_unlock(&Giant); 1694e1bca29fSMatthew Dillon } else { 1695e1bca29fSMatthew Dillon mtx_unlock(mtxp); 1696e1bca29fSMatthew Dillon } 1697df8bae1dSRodney W. Grimes } 1698df8bae1dSRodney W. Grimes 1699df8bae1dSRodney W. Grimes /* 1700bd78ceceSJohn Baldwin * Check to see if this ucred is shared. 1701df8bae1dSRodney W. Grimes */ 1702bd78ceceSJohn Baldwin int 17034c44ad8eSJohn Baldwin crshared(struct ucred *cr) 1704df8bae1dSRodney W. Grimes { 1705bd78ceceSJohn Baldwin int shared; 1706df8bae1dSRodney W. Grimes 1707e1bca29fSMatthew Dillon mtx_lock(cr->cr_mtxp); 1708bd78ceceSJohn Baldwin shared = (cr->cr_ref > 1); 1709e1bca29fSMatthew Dillon mtx_unlock(cr->cr_mtxp); 1710bd78ceceSJohn Baldwin return (shared); 17111e5d626aSAlfred Perlstein } 1712bd78ceceSJohn Baldwin 1713bd78ceceSJohn Baldwin /* 1714bd78ceceSJohn Baldwin * Copy a ucred's contents from a template. Does not block. 1715bd78ceceSJohn Baldwin */ 1716bd78ceceSJohn Baldwin void 17174c44ad8eSJohn Baldwin crcopy(struct ucred *dest, struct ucred *src) 1718bd78ceceSJohn Baldwin { 1719bd78ceceSJohn Baldwin 1720bd78ceceSJohn Baldwin KASSERT(crshared(dest) == 0, ("crcopy of shared ucred")); 1721bd78ceceSJohn Baldwin bcopy(&src->cr_startcopy, &dest->cr_startcopy, 1722bd78ceceSJohn Baldwin (unsigned)((caddr_t)&src->cr_endcopy - 1723bd78ceceSJohn Baldwin (caddr_t)&src->cr_startcopy)); 1724bd78ceceSJohn Baldwin uihold(dest->cr_uidinfo); 1725bd78ceceSJohn Baldwin uihold(dest->cr_ruidinfo); 1726bd78ceceSJohn Baldwin if (jailed(dest)) 1727bd78ceceSJohn Baldwin prison_hold(dest->cr_prison); 1728df8bae1dSRodney W. Grimes } 1729df8bae1dSRodney W. Grimes 1730df8bae1dSRodney W. Grimes /* 1731df8bae1dSRodney W. Grimes * Dup cred struct to a new held one. 1732df8bae1dSRodney W. Grimes */ 1733df8bae1dSRodney W. Grimes struct ucred * 17344c44ad8eSJohn Baldwin crdup(struct ucred *cr) 1735df8bae1dSRodney W. Grimes { 1736df8bae1dSRodney W. Grimes struct ucred *newcr; 1737df8bae1dSRodney W. Grimes 1738bd78ceceSJohn Baldwin newcr = crget(); 1739bd78ceceSJohn Baldwin crcopy(newcr, cr); 1740df8bae1dSRodney W. Grimes return (newcr); 1741df8bae1dSRodney W. Grimes } 1742df8bae1dSRodney W. Grimes 1743c1a513c9SJohn Baldwin #ifdef DIAGNOSTIC 1744c1a513c9SJohn Baldwin void 1745c1a513c9SJohn Baldwin cred_free_thread(struct thread *td) 1746c1a513c9SJohn Baldwin { 1747c1a513c9SJohn Baldwin struct ucred *cred; 1748c1a513c9SJohn Baldwin 1749c1a513c9SJohn Baldwin cred = td->td_ucred; 1750c1a513c9SJohn Baldwin td->td_ucred = NULL; 1751c1a513c9SJohn Baldwin if (cred != NULL) 1752c1a513c9SJohn Baldwin crfree(cred); 1753c1a513c9SJohn Baldwin } 1754c1a513c9SJohn Baldwin #endif 1755c1a513c9SJohn Baldwin 1756df8bae1dSRodney W. Grimes /* 175776183f34SDima Dorfman * Fill in a struct xucred based on a struct ucred. 175876183f34SDima Dorfman */ 175976183f34SDima Dorfman void 17604c44ad8eSJohn Baldwin cru2x(struct ucred *cr, struct xucred *xcr) 176176183f34SDima Dorfman { 176276183f34SDima Dorfman 176376183f34SDima Dorfman bzero(xcr, sizeof(*xcr)); 176476183f34SDima Dorfman xcr->cr_version = XUCRED_VERSION; 176576183f34SDima Dorfman xcr->cr_uid = cr->cr_uid; 176676183f34SDima Dorfman xcr->cr_ngroups = cr->cr_ngroups; 176776183f34SDima Dorfman bcopy(cr->cr_groups, xcr->cr_groups, sizeof(cr->cr_groups)); 176876183f34SDima Dorfman } 176976183f34SDima Dorfman 177076183f34SDima Dorfman /* 17712eb927e2SJulian Elischer * small routine to swap a thread's current ucred for the correct one 17722eb927e2SJulian Elischer * taken from the process. 17732eb927e2SJulian Elischer */ 17742eb927e2SJulian Elischer void 17752eb927e2SJulian Elischer cred_update_thread(struct thread *td) 17762eb927e2SJulian Elischer { 17772eb927e2SJulian Elischer struct proc *p; 177865e3406dSJohn Baldwin struct ucred *cred; 17792eb927e2SJulian Elischer 17802eb927e2SJulian Elischer p = td->td_proc; 178165e3406dSJohn Baldwin cred = td->td_ucred; 17822eb927e2SJulian Elischer mtx_lock(&Giant); 17832eb927e2SJulian Elischer PROC_LOCK(p); 17842eb927e2SJulian Elischer td->td_ucred = crhold(p->p_ucred); 17852eb927e2SJulian Elischer PROC_UNLOCK(p); 178665e3406dSJohn Baldwin if (cred != NULL) 178765e3406dSJohn Baldwin crfree(cred); 178865e3406dSJohn Baldwin mtx_unlock(&Giant); 17892eb927e2SJulian Elischer } 17902eb927e2SJulian Elischer 17912eb927e2SJulian Elischer /* 1792df8bae1dSRodney W. Grimes * Get login name, if available. 1793df8bae1dSRodney W. Grimes */ 1794d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 1795df8bae1dSRodney W. Grimes struct getlogin_args { 1796df8bae1dSRodney W. Grimes char *namebuf; 1797df8bae1dSRodney W. Grimes u_int namelen; 1798df8bae1dSRodney W. Grimes }; 1799d2d3e875SBruce Evans #endif 1800835a82eeSMatthew Dillon /* 1801835a82eeSMatthew Dillon * MPSAFE 1802835a82eeSMatthew Dillon */ 1803df8bae1dSRodney W. Grimes /* ARGSUSED */ 180426f9a767SRodney W. Grimes int 18054c44ad8eSJohn Baldwin getlogin(struct thread *td, struct getlogin_args *uap) 1806df8bae1dSRodney W. Grimes { 1807835a82eeSMatthew Dillon int error; 1808f591779bSSeigo Tanimura char login[MAXLOGNAME]; 1809b40ce416SJulian Elischer struct proc *p = td->td_proc; 1810df8bae1dSRodney W. Grimes 1811835a82eeSMatthew Dillon mtx_lock(&Giant); 181230cf3ac4SAndrey A. Chernov if (uap->namelen > MAXLOGNAME) 181353490b76SAndrey A. Chernov uap->namelen = MAXLOGNAME; 1814f591779bSSeigo Tanimura PROC_LOCK(p); 1815f591779bSSeigo Tanimura SESS_LOCK(p->p_session); 1816f591779bSSeigo Tanimura bcopy(p->p_session->s_login, login, uap->namelen); 1817f591779bSSeigo Tanimura SESS_UNLOCK(p->p_session); 1818f591779bSSeigo Tanimura PROC_UNLOCK(p); 1819f591779bSSeigo Tanimura error = copyout((caddr_t) login, (caddr_t) uap->namebuf, uap->namelen); 1820835a82eeSMatthew Dillon mtx_unlock(&Giant); 1821835a82eeSMatthew Dillon return(error); 1822df8bae1dSRodney W. Grimes } 1823df8bae1dSRodney W. Grimes 1824df8bae1dSRodney W. Grimes /* 1825df8bae1dSRodney W. Grimes * Set login name. 1826df8bae1dSRodney W. Grimes */ 1827d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 1828df8bae1dSRodney W. Grimes struct setlogin_args { 1829df8bae1dSRodney W. Grimes char *namebuf; 1830df8bae1dSRodney W. Grimes }; 1831d2d3e875SBruce Evans #endif 1832835a82eeSMatthew Dillon /* 1833835a82eeSMatthew Dillon * MPSAFE 1834835a82eeSMatthew Dillon */ 1835df8bae1dSRodney W. Grimes /* ARGSUSED */ 183626f9a767SRodney W. Grimes int 18374c44ad8eSJohn Baldwin setlogin(struct thread *td, struct setlogin_args *uap) 1838df8bae1dSRodney W. Grimes { 1839b40ce416SJulian Elischer struct proc *p = td->td_proc; 1840df8bae1dSRodney W. Grimes int error; 1841964ca0caSAndrey A. Chernov char logintmp[MAXLOGNAME]; 1842df8bae1dSRodney W. Grimes 184307f3485dSJohn Baldwin error = suser_cred(td->td_ucred, PRISON_ROOT); 184407f3485dSJohn Baldwin if (error) 184507f3485dSJohn Baldwin return (error); 1846184989c2SDavid Nugent error = copyinstr((caddr_t) uap->namebuf, (caddr_t) logintmp, 184710d4743fSDoug Rabson sizeof(logintmp), (size_t *)0); 1848eb725b4eSRobert Watson if (error == ENAMETOOLONG) 1849df8bae1dSRodney W. Grimes error = EINVAL; 1850f591779bSSeigo Tanimura else if (!error) { 1851f591779bSSeigo Tanimura PROC_LOCK(p); 1852f591779bSSeigo Tanimura SESS_LOCK(p->p_session); 1853f591779bSSeigo Tanimura (void) memcpy(p->p_session->s_login, logintmp, 1854964ca0caSAndrey A. Chernov sizeof(logintmp)); 1855f591779bSSeigo Tanimura SESS_UNLOCK(p->p_session); 1856f591779bSSeigo Tanimura PROC_UNLOCK(p); 1857f591779bSSeigo Tanimura } 1858df8bae1dSRodney W. Grimes return (error); 1859df8bae1dSRodney W. Grimes } 1860d5f81602SSean Eric Fagan 1861d5f81602SSean Eric Fagan void 18624c44ad8eSJohn Baldwin setsugid(struct proc *p) 1863d5f81602SSean Eric Fagan { 1864d5f81602SSean Eric Fagan p->p_flag |= P_SUGID; 186589361835SSean Eric Fagan if (!(p->p_pfsflags & PF_ISUGID)) 1866d5f81602SSean Eric Fagan p->p_stops = 0; 1867d5f81602SSean Eric Fagan } 1868f535380cSDon Lewis 18697fd6a959SRobert Watson /*- 18707fd6a959SRobert Watson * Change a process's effective uid. 1871b1fc0ec1SRobert Watson * Side effects: newcred->cr_uid and newcred->cr_uidinfo will be modified. 1872b1fc0ec1SRobert Watson * References: newcred must be an exclusive credential reference for the 1873b1fc0ec1SRobert Watson * duration of the call. 1874f535380cSDon Lewis */ 1875f535380cSDon Lewis void 18764c44ad8eSJohn Baldwin change_euid(struct ucred *newcred, uid_t euid) 1877f535380cSDon Lewis { 1878f535380cSDon Lewis 1879b1fc0ec1SRobert Watson newcred->cr_uid = euid; 1880b1fc0ec1SRobert Watson uifree(newcred->cr_uidinfo); 1881b1fc0ec1SRobert Watson newcred->cr_uidinfo = uifind(euid); 1882f535380cSDon Lewis } 1883f535380cSDon Lewis 18847fd6a959SRobert Watson /*- 18857fd6a959SRobert Watson * Change a process's effective gid. 1886b1fc0ec1SRobert Watson * Side effects: newcred->cr_gid will be modified. 1887b1fc0ec1SRobert Watson * References: newcred must be an exclusive credential reference for the 1888b1fc0ec1SRobert Watson * duration of the call. 1889f535380cSDon Lewis */ 1890810bfc8eSAndrew Gallatin void 18914c44ad8eSJohn Baldwin change_egid(struct ucred *newcred, gid_t egid) 1892b1fc0ec1SRobert Watson { 1893b1fc0ec1SRobert Watson 1894b1fc0ec1SRobert Watson newcred->cr_groups[0] = egid; 1895b1fc0ec1SRobert Watson } 1896b1fc0ec1SRobert Watson 18977fd6a959SRobert Watson /*- 18987fd6a959SRobert Watson * Change a process's real uid. 1899b1fc0ec1SRobert Watson * Side effects: newcred->cr_ruid will be updated, newcred->cr_ruidinfo 1900b1fc0ec1SRobert Watson * will be updated, and the old and new cr_ruidinfo proc 1901b1fc0ec1SRobert Watson * counts will be updated. 1902b1fc0ec1SRobert Watson * References: newcred must be an exclusive credential reference for the 1903b1fc0ec1SRobert Watson * duration of the call. 1904b1fc0ec1SRobert Watson */ 1905b1fc0ec1SRobert Watson void 19064c44ad8eSJohn Baldwin change_ruid(struct ucred *newcred, uid_t ruid) 1907f535380cSDon Lewis { 1908f535380cSDon Lewis 1909b1fc0ec1SRobert Watson (void)chgproccnt(newcred->cr_ruidinfo, -1, 0); 1910b1fc0ec1SRobert Watson newcred->cr_ruid = ruid; 1911b1fc0ec1SRobert Watson uifree(newcred->cr_ruidinfo); 1912b1fc0ec1SRobert Watson newcred->cr_ruidinfo = uifind(ruid); 1913b1fc0ec1SRobert Watson (void)chgproccnt(newcred->cr_ruidinfo, 1, 0); 1914b1fc0ec1SRobert Watson } 1915b1fc0ec1SRobert Watson 19167fd6a959SRobert Watson /*- 19177fd6a959SRobert Watson * Change a process's real gid. 1918b1fc0ec1SRobert Watson * Side effects: newcred->cr_rgid will be updated. 1919b1fc0ec1SRobert Watson * References: newcred must be an exclusive credential reference for the 1920b1fc0ec1SRobert Watson * duration of the call. 1921b1fc0ec1SRobert Watson */ 1922b1fc0ec1SRobert Watson void 19234c44ad8eSJohn Baldwin change_rgid(struct ucred *newcred, gid_t rgid) 1924b1fc0ec1SRobert Watson { 1925b1fc0ec1SRobert Watson 1926b1fc0ec1SRobert Watson newcred->cr_rgid = rgid; 1927b1fc0ec1SRobert Watson } 1928b1fc0ec1SRobert Watson 19297fd6a959SRobert Watson /*- 19307fd6a959SRobert Watson * Change a process's saved uid. 1931b1fc0ec1SRobert Watson * Side effects: newcred->cr_svuid will be updated. 1932b1fc0ec1SRobert Watson * References: newcred must be an exclusive credential reference for the 1933b1fc0ec1SRobert Watson * duration of the call. 1934b1fc0ec1SRobert Watson */ 1935b1fc0ec1SRobert Watson void 19364c44ad8eSJohn Baldwin change_svuid(struct ucred *newcred, uid_t svuid) 1937b1fc0ec1SRobert Watson { 1938b1fc0ec1SRobert Watson 1939b1fc0ec1SRobert Watson newcred->cr_svuid = svuid; 1940b1fc0ec1SRobert Watson } 1941b1fc0ec1SRobert Watson 19427fd6a959SRobert Watson /*- 19437fd6a959SRobert Watson * Change a process's saved gid. 1944b1fc0ec1SRobert Watson * Side effects: newcred->cr_svgid will be updated. 1945b1fc0ec1SRobert Watson * References: newcred must be an exclusive credential reference for the 1946b1fc0ec1SRobert Watson * duration of the call. 1947b1fc0ec1SRobert Watson */ 1948b1fc0ec1SRobert Watson void 19494c44ad8eSJohn Baldwin change_svgid(struct ucred *newcred, gid_t svgid) 1950b1fc0ec1SRobert Watson { 1951b1fc0ec1SRobert Watson 1952b1fc0ec1SRobert Watson newcred->cr_svgid = svgid; 1953f535380cSDon Lewis } 1954