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 352f591779bSSeigo Tanimura PGRPSESS_XLOCK(); 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 goto fail; 359f591779bSSeigo Tanimura } else { 360f591779bSSeigo Tanimura (void)enterpgrp(p, p->p_pid, newpgrp, newsess); 361b40ce416SJulian Elischer td->td_retval[0] = p->p_pid; 362835a82eeSMatthew Dillon error = 0; 363df8bae1dSRodney W. Grimes } 364f591779bSSeigo Tanimura PGRPSESS_XUNLOCK(); 365835a82eeSMatthew Dillon mtx_unlock(&Giant); 366f591779bSSeigo Tanimura return (0); 367f591779bSSeigo Tanimura 368f591779bSSeigo Tanimura fail: 369f591779bSSeigo Tanimura PGRPSESS_XUNLOCK(); 370f591779bSSeigo Tanimura 371f591779bSSeigo Tanimura FREE(newpgrp, M_PGRP); 372f591779bSSeigo Tanimura FREE(newsess, M_SESSION); 373f591779bSSeigo Tanimura 374f591779bSSeigo Tanimura mtx_unlock(&Giant); 375f591779bSSeigo Tanimura return (0); 376df8bae1dSRodney W. Grimes } 377df8bae1dSRodney W. Grimes 378df8bae1dSRodney W. Grimes /* 379df8bae1dSRodney W. Grimes * set process group (setpgid/old setpgrp) 380df8bae1dSRodney W. Grimes * 381df8bae1dSRodney W. Grimes * caller does setpgid(targpid, targpgid) 382df8bae1dSRodney W. Grimes * 383df8bae1dSRodney W. Grimes * pid must be caller or child of caller (ESRCH) 384df8bae1dSRodney W. Grimes * if a child 385df8bae1dSRodney W. Grimes * pid must be in same session (EPERM) 386df8bae1dSRodney W. Grimes * pid can't have done an exec (EACCES) 387df8bae1dSRodney W. Grimes * if pgid != pid 388df8bae1dSRodney W. Grimes * there must exist some pid in same session having pgid (EPERM) 389df8bae1dSRodney W. Grimes * pid must not be session leader (EPERM) 390df8bae1dSRodney W. Grimes */ 391d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 392df8bae1dSRodney W. Grimes struct setpgid_args { 393df8bae1dSRodney W. Grimes int pid; /* target process id */ 394df8bae1dSRodney W. Grimes int pgid; /* target pgrp id */ 395df8bae1dSRodney W. Grimes }; 396d2d3e875SBruce Evans #endif 397835a82eeSMatthew Dillon /* 398835a82eeSMatthew Dillon * MPSAFE 399835a82eeSMatthew Dillon */ 400df8bae1dSRodney W. Grimes /* ARGSUSED */ 40126f9a767SRodney W. Grimes int 4024c44ad8eSJohn Baldwin setpgid(struct thread *td, register struct setpgid_args *uap) 403df8bae1dSRodney W. Grimes { 404b40ce416SJulian Elischer struct proc *curp = td->td_proc; 405df8bae1dSRodney W. Grimes register struct proc *targp; /* target process */ 406df8bae1dSRodney W. Grimes register struct pgrp *pgrp; /* target pgrp */ 407eb9e5c1dSRobert Watson int error; 408f591779bSSeigo Tanimura struct pgrp *newpgrp; 409df8bae1dSRodney W. Grimes 41078f64bccSBruce Evans if (uap->pgid < 0) 41178f64bccSBruce Evans return (EINVAL); 412f591779bSSeigo Tanimura 413f591779bSSeigo Tanimura error = 0; 414f591779bSSeigo Tanimura 415835a82eeSMatthew Dillon mtx_lock(&Giant); 416f591779bSSeigo Tanimura 417f591779bSSeigo Tanimura MALLOC(newpgrp, struct pgrp *, sizeof(struct pgrp), M_PGRP, M_WAITOK | M_ZERO); 418f591779bSSeigo Tanimura 419f591779bSSeigo Tanimura PGRPSESS_XLOCK(); 420f591779bSSeigo Tanimura 421df8bae1dSRodney W. Grimes if (uap->pid != 0 && uap->pid != curp->p_pid) { 422f591779bSSeigo Tanimura sx_slock(&proctree_lock); 423f591779bSSeigo Tanimura if ((targp = pfind(uap->pid)) == NULL) { 42433a9ed9dSJohn Baldwin if (targp) 42533a9ed9dSJohn Baldwin PROC_UNLOCK(targp); 426f591779bSSeigo Tanimura sx_sunlock(&proctree_lock); 427835a82eeSMatthew Dillon error = ESRCH; 428f591779bSSeigo Tanimura goto fail; 42933a9ed9dSJohn Baldwin } 430f591779bSSeigo Tanimura if (!inferior(targp)) { 431f591779bSSeigo Tanimura PROC_UNLOCK(targp); 432f591779bSSeigo Tanimura sx_sunlock(&proctree_lock); 4332f932587SSeigo Tanimura error = ESRCH; 434f591779bSSeigo Tanimura goto fail; 435f591779bSSeigo Tanimura } 436f591779bSSeigo Tanimura sx_sunlock(&proctree_lock); 437a0f75161SRobert Watson if ((error = p_cansee(curproc, targp))) { 43833a9ed9dSJohn Baldwin PROC_UNLOCK(targp); 439f591779bSSeigo Tanimura goto fail; 44033a9ed9dSJohn Baldwin } 44133a9ed9dSJohn Baldwin if (targp->p_pgrp == NULL || 44233a9ed9dSJohn Baldwin targp->p_session != curp->p_session) { 44333a9ed9dSJohn Baldwin PROC_UNLOCK(targp); 444835a82eeSMatthew Dillon error = EPERM; 445f591779bSSeigo Tanimura goto fail; 44633a9ed9dSJohn Baldwin } 44733a9ed9dSJohn Baldwin if (targp->p_flag & P_EXEC) { 44833a9ed9dSJohn Baldwin PROC_UNLOCK(targp); 449835a82eeSMatthew Dillon error = EACCES; 450f591779bSSeigo Tanimura goto fail; 45133a9ed9dSJohn Baldwin } 45233a9ed9dSJohn Baldwin PROC_UNLOCK(targp); 453f591779bSSeigo Tanimura } else 454f591779bSSeigo Tanimura targp = curp; 455f591779bSSeigo Tanimura if (SESS_LEADER(targp)) { 456835a82eeSMatthew Dillon error = EPERM; 457f591779bSSeigo Tanimura goto fail; 45833a9ed9dSJohn Baldwin } 459eb725b4eSRobert Watson if (uap->pgid == 0) 460df8bae1dSRodney W. Grimes uap->pgid = targp->p_pid; 461f591779bSSeigo Tanimura if (uap->pgid == targp->p_pid) { 462f591779bSSeigo Tanimura if (targp->p_pgid == uap->pgid) 463f591779bSSeigo Tanimura goto done; 464f591779bSSeigo Tanimura error = enterpgrp(targp, uap->pgid, newpgrp, NULL); 465f591779bSSeigo Tanimura if (error == 0) 466f591779bSSeigo Tanimura newpgrp = NULL; 467f591779bSSeigo Tanimura } else { 468f591779bSSeigo Tanimura if ((pgrp = pgfind(uap->pgid)) == NULL || 46933a9ed9dSJohn Baldwin pgrp->pg_session != curp->p_session) { 470f591779bSSeigo Tanimura if (pgrp != NULL) 471f591779bSSeigo Tanimura PGRP_UNLOCK(pgrp); 472835a82eeSMatthew Dillon error = EPERM; 473f591779bSSeigo Tanimura goto fail; 474835a82eeSMatthew Dillon } 475f591779bSSeigo Tanimura if (pgrp == targp->p_pgrp) { 476f591779bSSeigo Tanimura PGRP_UNLOCK(pgrp); 477f591779bSSeigo Tanimura goto done; 47833a9ed9dSJohn Baldwin } 479f591779bSSeigo Tanimura PGRP_UNLOCK(pgrp); 480f591779bSSeigo Tanimura error = enterthispgrp(targp, pgrp); 481f591779bSSeigo Tanimura } 482f591779bSSeigo Tanimura done: 483f591779bSSeigo Tanimura PGRPSESS_XUNLOCK(); 484f591779bSSeigo Tanimura if (newpgrp != NULL) 485f591779bSSeigo Tanimura FREE(newpgrp, M_PGRP); 486f591779bSSeigo Tanimura mtx_unlock(&Giant); 487f591779bSSeigo Tanimura return (0); 488f591779bSSeigo Tanimura 489f591779bSSeigo Tanimura fail: 490f591779bSSeigo Tanimura PGRPSESS_XUNLOCK(); 491f591779bSSeigo Tanimura 492f591779bSSeigo Tanimura KASSERT(newpgrp != NULL, ("setpgid failed and newpgrp is null.")); 4932f932587SSeigo Tanimura KASSERT(error != 0, ("setpgid successfully failed?")); 494f591779bSSeigo Tanimura FREE(newpgrp, M_PGRP); 495f591779bSSeigo Tanimura 496835a82eeSMatthew Dillon mtx_unlock(&Giant); 497835a82eeSMatthew Dillon return (error); 498df8bae1dSRodney W. Grimes } 499df8bae1dSRodney W. Grimes 500a08f4bf6SPeter Wemm /* 501a08f4bf6SPeter Wemm * Use the clause in B.4.2.2 that allows setuid/setgid to be 4.2/4.3BSD 5022fa72ea7SJeroen Ruigrok van der Werven * compatible. It says that setting the uid/gid to euid/egid is a special 503a08f4bf6SPeter Wemm * case of "appropriate privilege". Once the rules are expanded out, this 504a08f4bf6SPeter Wemm * basically means that setuid(nnn) sets all three id's, in all permitted 505a08f4bf6SPeter Wemm * cases unless _POSIX_SAVED_IDS is enabled. In that case, setuid(getuid()) 506a08f4bf6SPeter Wemm * does not set the saved id - this is dangerous for traditional BSD 507a08f4bf6SPeter Wemm * programs. For this reason, we *really* do not want to set 508a08f4bf6SPeter Wemm * _POSIX_SAVED_IDS and do not want to clear POSIX_APPENDIX_B_4_2_2. 509a08f4bf6SPeter Wemm */ 510a08f4bf6SPeter Wemm #define POSIX_APPENDIX_B_4_2_2 511a08f4bf6SPeter Wemm 512d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 513df8bae1dSRodney W. Grimes struct setuid_args { 514df8bae1dSRodney W. Grimes uid_t uid; 515df8bae1dSRodney W. Grimes }; 516d2d3e875SBruce Evans #endif 517835a82eeSMatthew Dillon /* 518835a82eeSMatthew Dillon * MPSAFE 519835a82eeSMatthew Dillon */ 520df8bae1dSRodney W. Grimes /* ARGSUSED */ 52126f9a767SRodney W. Grimes int 5224c44ad8eSJohn Baldwin setuid(struct thread *td, struct setuid_args *uap) 523df8bae1dSRodney W. Grimes { 524b40ce416SJulian Elischer struct proc *p = td->td_proc; 525b1fc0ec1SRobert Watson struct ucred *newcred, *oldcred; 526b1fc0ec1SRobert Watson uid_t uid; 527eb725b4eSRobert Watson int error; 528df8bae1dSRodney W. Grimes 529eb725b4eSRobert Watson uid = uap->uid; 530835a82eeSMatthew Dillon mtx_lock(&Giant); 531eb725b4eSRobert Watson error = 0; 532f605567cSRobert Watson oldcred = p->p_ucred; 5335a92ee3cSRobert Watson 534a08f4bf6SPeter Wemm /* 535a08f4bf6SPeter Wemm * See if we have "permission" by POSIX 1003.1 rules. 536a08f4bf6SPeter Wemm * 537a08f4bf6SPeter Wemm * Note that setuid(geteuid()) is a special case of 538a08f4bf6SPeter Wemm * "appropriate privileges" in appendix B.4.2.2. We need 5392fa72ea7SJeroen Ruigrok van der Werven * to use this clause to be compatible with traditional BSD 540a08f4bf6SPeter Wemm * semantics. Basically, it means that "setuid(xx)" sets all 541a08f4bf6SPeter Wemm * three id's (assuming you have privs). 542a08f4bf6SPeter Wemm * 543a08f4bf6SPeter Wemm * Notes on the logic. We do things in three steps. 544a08f4bf6SPeter Wemm * 1: We determine if the euid is going to change, and do EPERM 545a08f4bf6SPeter Wemm * right away. We unconditionally change the euid later if this 546a08f4bf6SPeter Wemm * test is satisfied, simplifying that part of the logic. 547eb725b4eSRobert Watson * 2: We determine if the real and/or saved uids are going to 548a08f4bf6SPeter Wemm * change. Determined by compile options. 549a08f4bf6SPeter Wemm * 3: Change euid last. (after tests in #2 for "appropriate privs") 550a08f4bf6SPeter Wemm */ 551b1fc0ec1SRobert Watson if (uid != oldcred->cr_ruid && /* allow setuid(getuid()) */ 5523f246666SAndrey A. Chernov #ifdef _POSIX_SAVED_IDS 553b1fc0ec1SRobert Watson uid != oldcred->cr_svuid && /* allow setuid(saved gid) */ 554a08f4bf6SPeter Wemm #endif 555a08f4bf6SPeter Wemm #ifdef POSIX_APPENDIX_B_4_2_2 /* Use BSD-compat clause from B.4.2.2 */ 556b1fc0ec1SRobert Watson uid != oldcred->cr_uid && /* allow setuid(geteuid()) */ 5573f246666SAndrey A. Chernov #endif 55844731cabSJohn Baldwin (error = suser_cred(oldcred, PRISON_ROOT)) != 0) 559835a82eeSMatthew Dillon goto done2; 560a08f4bf6SPeter Wemm 561b1fc0ec1SRobert Watson newcred = crdup(oldcred); 562a08f4bf6SPeter Wemm #ifdef _POSIX_SAVED_IDS 563df8bae1dSRodney W. Grimes /* 564a08f4bf6SPeter Wemm * Do we have "appropriate privileges" (are we root or uid == euid) 565a08f4bf6SPeter Wemm * If so, we are changing the real uid and/or saved uid. 566df8bae1dSRodney W. Grimes */ 5673f246666SAndrey A. Chernov if ( 568a08f4bf6SPeter Wemm #ifdef POSIX_APPENDIX_B_4_2_2 /* Use the clause from B.4.2.2 */ 569b1fc0ec1SRobert Watson uid == oldcred->cr_uid || 5703f246666SAndrey A. Chernov #endif 57144731cabSJohn Baldwin suser_cred(oldcred, PRISON_ROOT) == 0) /* we are using privs */ 572a08f4bf6SPeter Wemm #endif 573a08f4bf6SPeter Wemm { 574a08f4bf6SPeter Wemm /* 575f535380cSDon Lewis * Set the real uid and transfer proc count to new user. 576a08f4bf6SPeter Wemm */ 577b1fc0ec1SRobert Watson if (uid != oldcred->cr_ruid) { 578b1fc0ec1SRobert Watson change_ruid(newcred, uid); 579f535380cSDon Lewis setsugid(p); 580d3cdb93dSAndrey A. Chernov } 581a08f4bf6SPeter Wemm /* 582a08f4bf6SPeter Wemm * Set saved uid 583a08f4bf6SPeter Wemm * 584a08f4bf6SPeter Wemm * XXX always set saved uid even if not _POSIX_SAVED_IDS, as 585a08f4bf6SPeter Wemm * the security of seteuid() depends on it. B.4.2.2 says it 586a08f4bf6SPeter Wemm * is important that we should do this. 587a08f4bf6SPeter Wemm */ 588b1fc0ec1SRobert Watson if (uid != oldcred->cr_svuid) { 589b1fc0ec1SRobert Watson change_svuid(newcred, uid); 590d5f81602SSean Eric Fagan setsugid(p); 591a08f4bf6SPeter Wemm } 592a08f4bf6SPeter Wemm } 593a08f4bf6SPeter Wemm 594a08f4bf6SPeter Wemm /* 595a08f4bf6SPeter Wemm * In all permitted cases, we are changing the euid. 596a08f4bf6SPeter Wemm * Copy credentials so other references do not see our changes. 597a08f4bf6SPeter Wemm */ 598b1fc0ec1SRobert Watson if (uid != oldcred->cr_uid) { 599b1fc0ec1SRobert Watson change_euid(newcred, uid); 600d5f81602SSean Eric Fagan setsugid(p); 601a08f4bf6SPeter Wemm } 602b1fc0ec1SRobert Watson p->p_ucred = newcred; 603b1fc0ec1SRobert Watson crfree(oldcred); 604835a82eeSMatthew Dillon done2: 605835a82eeSMatthew Dillon mtx_unlock(&Giant); 606835a82eeSMatthew Dillon return (error); 607df8bae1dSRodney W. Grimes } 608df8bae1dSRodney W. Grimes 609d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 610df8bae1dSRodney W. Grimes struct seteuid_args { 611df8bae1dSRodney W. Grimes uid_t euid; 612df8bae1dSRodney W. Grimes }; 613d2d3e875SBruce Evans #endif 614835a82eeSMatthew Dillon /* 615835a82eeSMatthew Dillon * MPSAFE 616835a82eeSMatthew Dillon */ 617df8bae1dSRodney W. Grimes /* ARGSUSED */ 61826f9a767SRodney W. Grimes int 6194c44ad8eSJohn Baldwin seteuid(struct thread *td, struct seteuid_args *uap) 620df8bae1dSRodney W. Grimes { 621b40ce416SJulian Elischer struct proc *p = td->td_proc; 622b1fc0ec1SRobert Watson struct ucred *newcred, *oldcred; 623b1fc0ec1SRobert Watson uid_t euid; 624eb725b4eSRobert Watson int error; 625df8bae1dSRodney W. Grimes 626df8bae1dSRodney W. Grimes euid = uap->euid; 627835a82eeSMatthew Dillon mtx_lock(&Giant); 628eb725b4eSRobert Watson error = 0; 629b1fc0ec1SRobert Watson oldcred = p->p_ucred; 630b1fc0ec1SRobert Watson if (euid != oldcred->cr_ruid && /* allow seteuid(getuid()) */ 631b1fc0ec1SRobert Watson euid != oldcred->cr_svuid && /* allow seteuid(saved uid) */ 63244731cabSJohn Baldwin (error = suser_cred(oldcred, PRISON_ROOT)) != 0) 633835a82eeSMatthew Dillon goto done2; 634df8bae1dSRodney W. Grimes /* 635df8bae1dSRodney W. Grimes * Everything's okay, do it. Copy credentials so other references do 636df8bae1dSRodney W. Grimes * not see our changes. 637df8bae1dSRodney W. Grimes */ 638b1fc0ec1SRobert Watson newcred = crdup(oldcred); 639b1fc0ec1SRobert Watson if (oldcred->cr_uid != euid) { 640b1fc0ec1SRobert Watson change_euid(newcred, euid); 641d5f81602SSean Eric Fagan setsugid(p); 642229a15f0SPeter Wemm } 643b1fc0ec1SRobert Watson p->p_ucred = newcred; 644b1fc0ec1SRobert Watson crfree(oldcred); 645835a82eeSMatthew Dillon done2: 646835a82eeSMatthew Dillon mtx_unlock(&Giant); 647835a82eeSMatthew Dillon return (error); 648df8bae1dSRodney W. Grimes } 649df8bae1dSRodney W. Grimes 650d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 651df8bae1dSRodney W. Grimes struct setgid_args { 652df8bae1dSRodney W. Grimes gid_t gid; 653df8bae1dSRodney W. Grimes }; 654d2d3e875SBruce Evans #endif 655835a82eeSMatthew Dillon /* 656835a82eeSMatthew Dillon * MPSAFE 657835a82eeSMatthew Dillon */ 658df8bae1dSRodney W. Grimes /* ARGSUSED */ 65926f9a767SRodney W. Grimes int 6604c44ad8eSJohn Baldwin setgid(struct thread *td, struct setgid_args *uap) 661df8bae1dSRodney W. Grimes { 662b40ce416SJulian Elischer struct proc *p = td->td_proc; 663b1fc0ec1SRobert Watson struct ucred *newcred, *oldcred; 664b1fc0ec1SRobert Watson gid_t gid; 665eb725b4eSRobert Watson int error; 666df8bae1dSRodney W. Grimes 667b1fc0ec1SRobert Watson gid = uap->gid; 668835a82eeSMatthew Dillon mtx_lock(&Giant); 669eb725b4eSRobert Watson error = 0; 670b1fc0ec1SRobert Watson oldcred = p->p_ucred; 6715a92ee3cSRobert Watson 672a08f4bf6SPeter Wemm /* 673a08f4bf6SPeter Wemm * See if we have "permission" by POSIX 1003.1 rules. 674a08f4bf6SPeter Wemm * 675a08f4bf6SPeter Wemm * Note that setgid(getegid()) is a special case of 676a08f4bf6SPeter Wemm * "appropriate privileges" in appendix B.4.2.2. We need 6772fa72ea7SJeroen Ruigrok van der Werven * to use this clause to be compatible with traditional BSD 678a08f4bf6SPeter Wemm * semantics. Basically, it means that "setgid(xx)" sets all 679a08f4bf6SPeter Wemm * three id's (assuming you have privs). 680a08f4bf6SPeter Wemm * 681a08f4bf6SPeter Wemm * For notes on the logic here, see setuid() above. 682a08f4bf6SPeter Wemm */ 683b1fc0ec1SRobert Watson if (gid != oldcred->cr_rgid && /* allow setgid(getgid()) */ 6843f246666SAndrey A. Chernov #ifdef _POSIX_SAVED_IDS 685b1fc0ec1SRobert Watson gid != oldcred->cr_svgid && /* allow setgid(saved gid) */ 686a08f4bf6SPeter Wemm #endif 687a08f4bf6SPeter Wemm #ifdef POSIX_APPENDIX_B_4_2_2 /* Use BSD-compat clause from B.4.2.2 */ 688b1fc0ec1SRobert Watson gid != oldcred->cr_groups[0] && /* allow setgid(getegid()) */ 6893f246666SAndrey A. Chernov #endif 69044731cabSJohn Baldwin (error = suser_cred(oldcred, PRISON_ROOT)) != 0) 691835a82eeSMatthew Dillon goto done2; 692a08f4bf6SPeter Wemm 693b1fc0ec1SRobert Watson newcred = crdup(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; 734b1fc0ec1SRobert Watson crfree(oldcred); 735835a82eeSMatthew Dillon done2: 736835a82eeSMatthew Dillon mtx_unlock(&Giant); 737835a82eeSMatthew Dillon return (error); 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); 759eb725b4eSRobert Watson error = 0; 760b1fc0ec1SRobert Watson oldcred = p->p_ucred; 761b1fc0ec1SRobert Watson if (egid != oldcred->cr_rgid && /* allow setegid(getgid()) */ 762b1fc0ec1SRobert Watson egid != oldcred->cr_svgid && /* allow setegid(saved gid) */ 76344731cabSJohn Baldwin (error = suser_cred(oldcred, PRISON_ROOT)) != 0) 764835a82eeSMatthew Dillon goto done2; 765b1fc0ec1SRobert Watson newcred = crdup(oldcred); 766b1fc0ec1SRobert Watson if (oldcred->cr_groups[0] != egid) { 767b1fc0ec1SRobert Watson change_egid(newcred, egid); 768d5f81602SSean Eric Fagan setsugid(p); 769229a15f0SPeter Wemm } 770b1fc0ec1SRobert Watson p->p_ucred = newcred; 771b1fc0ec1SRobert Watson crfree(oldcred); 772835a82eeSMatthew Dillon done2: 773835a82eeSMatthew Dillon mtx_unlock(&Giant); 774835a82eeSMatthew Dillon return (error); 775df8bae1dSRodney W. Grimes } 776df8bae1dSRodney W. Grimes 777d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 778df8bae1dSRodney W. Grimes struct setgroups_args { 779df8bae1dSRodney W. Grimes u_int gidsetsize; 780df8bae1dSRodney W. Grimes gid_t *gidset; 781df8bae1dSRodney W. Grimes }; 782d2d3e875SBruce Evans #endif 783835a82eeSMatthew Dillon /* 784835a82eeSMatthew Dillon * MPSAFE 785835a82eeSMatthew Dillon */ 786df8bae1dSRodney W. Grimes /* ARGSUSED */ 78726f9a767SRodney W. Grimes int 7884c44ad8eSJohn Baldwin setgroups(struct thread *td, struct setgroups_args *uap) 789df8bae1dSRodney W. Grimes { 790b40ce416SJulian Elischer struct proc *p = td->td_proc; 791b1fc0ec1SRobert Watson struct ucred *newcred, *oldcred; 792b1fc0ec1SRobert Watson u_int ngrp; 793df8bae1dSRodney W. Grimes int error; 794df8bae1dSRodney W. Grimes 7953956a170SDavid Greenman ngrp = uap->gidsetsize; 7964f5a4612SRobert Watson mtx_lock(&Giant); 797b1fc0ec1SRobert Watson oldcred = p->p_ucred; 79844731cabSJohn Baldwin if ((error = suser_cred(oldcred, PRISON_ROOT)) != 0) 799835a82eeSMatthew Dillon goto done2; 800835a82eeSMatthew Dillon if (ngrp > NGROUPS) { 801835a82eeSMatthew Dillon error = EINVAL; 802835a82eeSMatthew Dillon goto done2; 803835a82eeSMatthew Dillon } 8048a5d815aSPeter Wemm /* 8058a5d815aSPeter Wemm * XXX A little bit lazy here. We could test if anything has 8068a5d815aSPeter Wemm * changed before crcopy() and setting P_SUGID. 8078a5d815aSPeter Wemm */ 808b1fc0ec1SRobert Watson newcred = crdup(oldcred); 8098a5d815aSPeter Wemm if (ngrp < 1) { 8108a5d815aSPeter Wemm /* 8118a5d815aSPeter Wemm * setgroups(0, NULL) is a legitimate way of clearing the 8128a5d815aSPeter Wemm * groups vector on non-BSD systems (which generally do not 8138a5d815aSPeter Wemm * have the egid in the groups[0]). We risk security holes 8148a5d815aSPeter Wemm * when running non-BSD software if we do not do the same. 8158a5d815aSPeter Wemm */ 816b1fc0ec1SRobert Watson newcred->cr_ngroups = 1; 8178a5d815aSPeter Wemm } else { 818bb56ec4aSPoul-Henning Kamp if ((error = copyin((caddr_t)uap->gidset, 819b1fc0ec1SRobert Watson (caddr_t)newcred->cr_groups, ngrp * sizeof(gid_t)))) { 820b1fc0ec1SRobert Watson crfree(newcred); 821835a82eeSMatthew Dillon goto done2; 822b1fc0ec1SRobert Watson } 823b1fc0ec1SRobert Watson newcred->cr_ngroups = ngrp; 8248a5d815aSPeter Wemm } 825d5f81602SSean Eric Fagan setsugid(p); 826b1fc0ec1SRobert Watson p->p_ucred = newcred; 827b1fc0ec1SRobert Watson crfree(oldcred); 828835a82eeSMatthew Dillon done2: 829835a82eeSMatthew Dillon mtx_unlock(&Giant); 830835a82eeSMatthew Dillon return (error); 831df8bae1dSRodney W. Grimes } 832df8bae1dSRodney W. Grimes 833d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 834df8bae1dSRodney W. Grimes struct setreuid_args { 83500999cd6SAndrey A. Chernov uid_t ruid; 83600999cd6SAndrey A. Chernov uid_t euid; 837df8bae1dSRodney W. Grimes }; 838d2d3e875SBruce Evans #endif 839835a82eeSMatthew Dillon /* 840835a82eeSMatthew Dillon * MPSAFE 841835a82eeSMatthew Dillon */ 842df8bae1dSRodney W. Grimes /* ARGSUSED */ 84326f9a767SRodney W. Grimes int 8444c44ad8eSJohn Baldwin setreuid(register struct thread *td, struct setreuid_args *uap) 845df8bae1dSRodney W. Grimes { 846b40ce416SJulian Elischer struct proc *p = td->td_proc; 847b1fc0ec1SRobert Watson struct ucred *newcred, *oldcred; 848eb725b4eSRobert Watson uid_t euid, ruid; 849eb725b4eSRobert Watson int error; 850df8bae1dSRodney W. Grimes 85100999cd6SAndrey A. Chernov euid = uap->euid; 852eb725b4eSRobert Watson ruid = uap->ruid; 853835a82eeSMatthew Dillon mtx_lock(&Giant); 854eb725b4eSRobert Watson error = 0; 855b1fc0ec1SRobert Watson oldcred = p->p_ucred; 856b1fc0ec1SRobert Watson if (((ruid != (uid_t)-1 && ruid != oldcred->cr_ruid && 857b1fc0ec1SRobert Watson ruid != oldcred->cr_svuid) || 858b1fc0ec1SRobert Watson (euid != (uid_t)-1 && euid != oldcred->cr_uid && 859b1fc0ec1SRobert Watson euid != oldcred->cr_ruid && euid != oldcred->cr_svuid)) && 86044731cabSJohn Baldwin (error = suser_cred(oldcred, PRISON_ROOT)) != 0) 861835a82eeSMatthew Dillon goto done2; 862b1fc0ec1SRobert Watson newcred = crdup(oldcred); 863b1fc0ec1SRobert Watson if (euid != (uid_t)-1 && oldcred->cr_uid != euid) { 864b1fc0ec1SRobert Watson change_euid(newcred, euid); 865d5f81602SSean Eric Fagan setsugid(p); 866a89a5370SPeter Wemm } 867b1fc0ec1SRobert Watson if (ruid != (uid_t)-1 && oldcred->cr_ruid != ruid) { 868b1fc0ec1SRobert Watson change_ruid(newcred, ruid); 869d5f81602SSean Eric Fagan setsugid(p); 87000999cd6SAndrey A. Chernov } 871b1fc0ec1SRobert Watson if ((ruid != (uid_t)-1 || newcred->cr_uid != newcred->cr_ruid) && 872b1fc0ec1SRobert Watson newcred->cr_svuid != newcred->cr_uid) { 873b1fc0ec1SRobert Watson change_svuid(newcred, newcred->cr_uid); 874d5f81602SSean Eric Fagan setsugid(p); 875a89a5370SPeter Wemm } 876b1fc0ec1SRobert Watson p->p_ucred = newcred; 877b1fc0ec1SRobert Watson crfree(oldcred); 878835a82eeSMatthew Dillon done2: 879835a82eeSMatthew Dillon mtx_unlock(&Giant); 880835a82eeSMatthew Dillon return (error); 881df8bae1dSRodney W. Grimes } 882df8bae1dSRodney W. Grimes 883d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 884df8bae1dSRodney W. Grimes struct setregid_args { 88500999cd6SAndrey A. Chernov gid_t rgid; 88600999cd6SAndrey A. Chernov gid_t egid; 887df8bae1dSRodney W. Grimes }; 888d2d3e875SBruce Evans #endif 889835a82eeSMatthew Dillon /* 890835a82eeSMatthew Dillon * MPSAFE 891835a82eeSMatthew Dillon */ 892df8bae1dSRodney W. Grimes /* ARGSUSED */ 89326f9a767SRodney W. Grimes int 8944c44ad8eSJohn Baldwin setregid(register struct thread *td, struct setregid_args *uap) 895df8bae1dSRodney W. Grimes { 896b40ce416SJulian Elischer struct proc *p = td->td_proc; 897b1fc0ec1SRobert Watson struct ucred *newcred, *oldcred; 898eb725b4eSRobert Watson gid_t egid, rgid; 899eb725b4eSRobert Watson int error; 900df8bae1dSRodney W. Grimes 90100999cd6SAndrey A. Chernov egid = uap->egid; 902eb725b4eSRobert Watson rgid = uap->rgid; 903835a82eeSMatthew Dillon mtx_lock(&Giant); 904eb725b4eSRobert Watson error = 0; 905b1fc0ec1SRobert Watson oldcred = p->p_ucred; 906b1fc0ec1SRobert Watson if (((rgid != (gid_t)-1 && rgid != oldcred->cr_rgid && 907b1fc0ec1SRobert Watson rgid != oldcred->cr_svgid) || 908b1fc0ec1SRobert Watson (egid != (gid_t)-1 && egid != oldcred->cr_groups[0] && 909b1fc0ec1SRobert Watson egid != oldcred->cr_rgid && egid != oldcred->cr_svgid)) && 91044731cabSJohn Baldwin (error = suser_cred(oldcred, PRISON_ROOT)) != 0) 911835a82eeSMatthew Dillon goto done2; 912b1fc0ec1SRobert Watson newcred = crdup(oldcred); 913b1fc0ec1SRobert Watson if (egid != (gid_t)-1 && oldcred->cr_groups[0] != egid) { 914b1fc0ec1SRobert Watson change_egid(newcred, egid); 915d5f81602SSean Eric Fagan setsugid(p); 916a89a5370SPeter Wemm } 917b1fc0ec1SRobert Watson if (rgid != (gid_t)-1 && oldcred->cr_rgid != rgid) { 918b1fc0ec1SRobert Watson change_rgid(newcred, rgid); 919d5f81602SSean Eric Fagan setsugid(p); 920a89a5370SPeter Wemm } 921b1fc0ec1SRobert Watson if ((rgid != (gid_t)-1 || newcred->cr_groups[0] != newcred->cr_rgid) && 922b1fc0ec1SRobert Watson newcred->cr_svgid != newcred->cr_groups[0]) { 923b1fc0ec1SRobert Watson change_svgid(newcred, newcred->cr_groups[0]); 924d5f81602SSean Eric Fagan setsugid(p); 925a89a5370SPeter Wemm } 9264589be70SRuslan Ermilov p->p_ucred = newcred; 9274589be70SRuslan Ermilov crfree(oldcred); 928835a82eeSMatthew Dillon done2: 929835a82eeSMatthew Dillon mtx_unlock(&Giant); 930835a82eeSMatthew Dillon return (error); 931df8bae1dSRodney W. Grimes } 932df8bae1dSRodney W. Grimes 9338ccd6334SPeter Wemm /* 9348ccd6334SPeter Wemm * setresuid(ruid, euid, suid) is like setreuid except control over the 9358ccd6334SPeter Wemm * saved uid is explicit. 9368ccd6334SPeter Wemm */ 9378ccd6334SPeter Wemm 9388ccd6334SPeter Wemm #ifndef _SYS_SYSPROTO_H_ 9398ccd6334SPeter Wemm struct setresuid_args { 9408ccd6334SPeter Wemm uid_t ruid; 9418ccd6334SPeter Wemm uid_t euid; 9428ccd6334SPeter Wemm uid_t suid; 9438ccd6334SPeter Wemm }; 9448ccd6334SPeter Wemm #endif 945835a82eeSMatthew Dillon /* 946835a82eeSMatthew Dillon * MPSAFE 947835a82eeSMatthew Dillon */ 9488ccd6334SPeter Wemm /* ARGSUSED */ 9498ccd6334SPeter Wemm int 9504c44ad8eSJohn Baldwin setresuid(register struct thread *td, struct setresuid_args *uap) 9518ccd6334SPeter Wemm { 952b40ce416SJulian Elischer struct proc *p = td->td_proc; 953b1fc0ec1SRobert Watson struct ucred *newcred, *oldcred; 954eb725b4eSRobert Watson uid_t euid, ruid, suid; 9558ccd6334SPeter Wemm int error; 9568ccd6334SPeter Wemm 9578ccd6334SPeter Wemm euid = uap->euid; 958eb725b4eSRobert Watson ruid = uap->ruid; 9598ccd6334SPeter Wemm suid = uap->suid; 960835a82eeSMatthew Dillon mtx_lock(&Giant); 961b1fc0ec1SRobert Watson oldcred = p->p_ucred; 962b1fc0ec1SRobert Watson if (((ruid != (uid_t)-1 && ruid != oldcred->cr_ruid && 963b1fc0ec1SRobert Watson ruid != oldcred->cr_svuid && 964b1fc0ec1SRobert Watson ruid != oldcred->cr_uid) || 965b1fc0ec1SRobert Watson (euid != (uid_t)-1 && euid != oldcred->cr_ruid && 966b1fc0ec1SRobert Watson euid != oldcred->cr_svuid && 967b1fc0ec1SRobert Watson euid != oldcred->cr_uid) || 968b1fc0ec1SRobert Watson (suid != (uid_t)-1 && suid != oldcred->cr_ruid && 969b1fc0ec1SRobert Watson suid != oldcred->cr_svuid && 970b1fc0ec1SRobert Watson suid != oldcred->cr_uid)) && 97144731cabSJohn Baldwin (error = suser_cred(oldcred, PRISON_ROOT)) != 0) 972835a82eeSMatthew Dillon goto done2; 973b1fc0ec1SRobert Watson newcred = crdup(oldcred); 974b1fc0ec1SRobert Watson if (euid != (uid_t)-1 && oldcred->cr_uid != euid) { 975b1fc0ec1SRobert Watson change_euid(newcred, euid); 9768ccd6334SPeter Wemm setsugid(p); 9778ccd6334SPeter Wemm } 978b1fc0ec1SRobert Watson if (ruid != (uid_t)-1 && oldcred->cr_ruid != ruid) { 979b1fc0ec1SRobert Watson change_ruid(newcred, ruid); 9808ccd6334SPeter Wemm setsugid(p); 9818ccd6334SPeter Wemm } 982b1fc0ec1SRobert Watson if (suid != (uid_t)-1 && oldcred->cr_svuid != suid) { 983b1fc0ec1SRobert Watson change_svuid(newcred, suid); 9848ccd6334SPeter Wemm setsugid(p); 9858ccd6334SPeter Wemm } 986b1fc0ec1SRobert Watson p->p_ucred = newcred; 987b1fc0ec1SRobert Watson crfree(oldcred); 988835a82eeSMatthew Dillon error = 0; 989835a82eeSMatthew Dillon done2: 990835a82eeSMatthew Dillon mtx_unlock(&Giant); 991835a82eeSMatthew Dillon return (error); 9928ccd6334SPeter Wemm } 9938ccd6334SPeter Wemm 9948ccd6334SPeter Wemm /* 9958ccd6334SPeter Wemm * setresgid(rgid, egid, sgid) is like setregid except control over the 9968ccd6334SPeter Wemm * saved gid is explicit. 9978ccd6334SPeter Wemm */ 9988ccd6334SPeter Wemm 9998ccd6334SPeter Wemm #ifndef _SYS_SYSPROTO_H_ 10008ccd6334SPeter Wemm struct setresgid_args { 10018ccd6334SPeter Wemm gid_t rgid; 10028ccd6334SPeter Wemm gid_t egid; 10038ccd6334SPeter Wemm gid_t sgid; 10048ccd6334SPeter Wemm }; 10058ccd6334SPeter Wemm #endif 1006835a82eeSMatthew Dillon /* 1007835a82eeSMatthew Dillon * MPSAFE 1008835a82eeSMatthew Dillon */ 10098ccd6334SPeter Wemm /* ARGSUSED */ 10108ccd6334SPeter Wemm int 10114c44ad8eSJohn Baldwin setresgid(register struct thread *td, struct setresgid_args *uap) 10128ccd6334SPeter Wemm { 1013b40ce416SJulian Elischer struct proc *p = td->td_proc; 1014b1fc0ec1SRobert Watson struct ucred *newcred, *oldcred; 1015eb725b4eSRobert Watson gid_t egid, rgid, sgid; 10168ccd6334SPeter Wemm int error; 10178ccd6334SPeter Wemm 10188ccd6334SPeter Wemm egid = uap->egid; 1019eb725b4eSRobert Watson rgid = uap->rgid; 10208ccd6334SPeter Wemm sgid = uap->sgid; 1021835a82eeSMatthew Dillon mtx_lock(&Giant); 1022b1fc0ec1SRobert Watson oldcred = p->p_ucred; 1023b1fc0ec1SRobert Watson if (((rgid != (gid_t)-1 && rgid != oldcred->cr_rgid && 1024b1fc0ec1SRobert Watson rgid != oldcred->cr_svgid && 1025b1fc0ec1SRobert Watson rgid != oldcred->cr_groups[0]) || 1026b1fc0ec1SRobert Watson (egid != (gid_t)-1 && egid != oldcred->cr_rgid && 1027b1fc0ec1SRobert Watson egid != oldcred->cr_svgid && 1028b1fc0ec1SRobert Watson egid != oldcred->cr_groups[0]) || 1029b1fc0ec1SRobert Watson (sgid != (gid_t)-1 && sgid != oldcred->cr_rgid && 1030b1fc0ec1SRobert Watson sgid != oldcred->cr_svgid && 1031b1fc0ec1SRobert Watson sgid != oldcred->cr_groups[0])) && 103244731cabSJohn Baldwin (error = suser_cred(oldcred, PRISON_ROOT)) != 0) 1033835a82eeSMatthew Dillon goto done2; 1034b1fc0ec1SRobert Watson newcred = crdup(oldcred); 1035b1fc0ec1SRobert Watson if (egid != (gid_t)-1 && oldcred->cr_groups[0] != egid) { 1036b1fc0ec1SRobert Watson change_egid(newcred, egid); 10378ccd6334SPeter Wemm setsugid(p); 10388ccd6334SPeter Wemm } 1039b1fc0ec1SRobert Watson if (rgid != (gid_t)-1 && oldcred->cr_rgid != rgid) { 1040b1fc0ec1SRobert Watson change_rgid(newcred, rgid); 10418ccd6334SPeter Wemm setsugid(p); 10428ccd6334SPeter Wemm } 1043b1fc0ec1SRobert Watson if (sgid != (gid_t)-1 && oldcred->cr_svgid != sgid) { 1044b1fc0ec1SRobert Watson change_svgid(newcred, sgid); 10458ccd6334SPeter Wemm setsugid(p); 10468ccd6334SPeter Wemm } 1047b1fc0ec1SRobert Watson p->p_ucred = newcred; 1048b1fc0ec1SRobert Watson crfree(oldcred); 1049835a82eeSMatthew Dillon error = 0; 1050835a82eeSMatthew Dillon done2: 1051835a82eeSMatthew Dillon mtx_unlock(&Giant); 1052835a82eeSMatthew Dillon return (error); 10538ccd6334SPeter Wemm } 10548ccd6334SPeter Wemm 10558ccd6334SPeter Wemm #ifndef _SYS_SYSPROTO_H_ 10568ccd6334SPeter Wemm struct getresuid_args { 10578ccd6334SPeter Wemm uid_t *ruid; 10588ccd6334SPeter Wemm uid_t *euid; 10598ccd6334SPeter Wemm uid_t *suid; 10608ccd6334SPeter Wemm }; 10618ccd6334SPeter Wemm #endif 1062835a82eeSMatthew Dillon /* 1063835a82eeSMatthew Dillon * MPSAFE 1064835a82eeSMatthew Dillon */ 10658ccd6334SPeter Wemm /* ARGSUSED */ 10668ccd6334SPeter Wemm int 10674c44ad8eSJohn Baldwin getresuid(register struct thread *td, struct getresuid_args *uap) 10688ccd6334SPeter Wemm { 1069835a82eeSMatthew Dillon struct ucred *cred; 10708ccd6334SPeter Wemm int error1 = 0, error2 = 0, error3 = 0; 10718ccd6334SPeter Wemm 1072d74ac681SMatthew Dillon cred = td->td_ucred; 10738ccd6334SPeter Wemm if (uap->ruid) 1074b1fc0ec1SRobert Watson error1 = copyout((caddr_t)&cred->cr_ruid, 1075b1fc0ec1SRobert Watson (caddr_t)uap->ruid, sizeof(cred->cr_ruid)); 10768ccd6334SPeter Wemm if (uap->euid) 1077b1fc0ec1SRobert Watson error2 = copyout((caddr_t)&cred->cr_uid, 1078b1fc0ec1SRobert Watson (caddr_t)uap->euid, sizeof(cred->cr_uid)); 10798ccd6334SPeter Wemm if (uap->suid) 1080b1fc0ec1SRobert Watson error3 = copyout((caddr_t)&cred->cr_svuid, 1081b1fc0ec1SRobert Watson (caddr_t)uap->suid, sizeof(cred->cr_svuid)); 1082eb725b4eSRobert Watson return (error1 ? error1 : error2 ? error2 : error3); 10838ccd6334SPeter Wemm } 10848ccd6334SPeter Wemm 10858ccd6334SPeter Wemm #ifndef _SYS_SYSPROTO_H_ 10868ccd6334SPeter Wemm struct getresgid_args { 10878ccd6334SPeter Wemm gid_t *rgid; 10888ccd6334SPeter Wemm gid_t *egid; 10898ccd6334SPeter Wemm gid_t *sgid; 10908ccd6334SPeter Wemm }; 10918ccd6334SPeter Wemm #endif 1092835a82eeSMatthew Dillon /* 1093835a82eeSMatthew Dillon * MPSAFE 1094835a82eeSMatthew Dillon */ 10958ccd6334SPeter Wemm /* ARGSUSED */ 10968ccd6334SPeter Wemm int 10974c44ad8eSJohn Baldwin getresgid(register struct thread *td, struct getresgid_args *uap) 10988ccd6334SPeter Wemm { 1099835a82eeSMatthew Dillon struct ucred *cred; 11008ccd6334SPeter Wemm int error1 = 0, error2 = 0, error3 = 0; 11018ccd6334SPeter Wemm 1102d74ac681SMatthew Dillon cred = td->td_ucred; 11038ccd6334SPeter Wemm if (uap->rgid) 1104b1fc0ec1SRobert Watson error1 = copyout((caddr_t)&cred->cr_rgid, 1105b1fc0ec1SRobert Watson (caddr_t)uap->rgid, sizeof(cred->cr_rgid)); 11068ccd6334SPeter Wemm if (uap->egid) 1107b1fc0ec1SRobert Watson error2 = copyout((caddr_t)&cred->cr_groups[0], 1108b1fc0ec1SRobert Watson (caddr_t)uap->egid, sizeof(cred->cr_groups[0])); 11098ccd6334SPeter Wemm if (uap->sgid) 1110b1fc0ec1SRobert Watson error3 = copyout((caddr_t)&cred->cr_svgid, 1111b1fc0ec1SRobert Watson (caddr_t)uap->sgid, sizeof(cred->cr_svgid)); 1112eb725b4eSRobert Watson return (error1 ? error1 : error2 ? error2 : error3); 11138ccd6334SPeter Wemm } 11148ccd6334SPeter Wemm 1115b67cbc65SPeter Wemm #ifndef _SYS_SYSPROTO_H_ 1116b67cbc65SPeter Wemm struct issetugid_args { 1117b67cbc65SPeter Wemm int dummy; 1118b67cbc65SPeter Wemm }; 1119b67cbc65SPeter Wemm #endif 1120eb725b4eSRobert Watson /* 1121eb725b4eSRobert Watson * NOT MPSAFE? 1122eb725b4eSRobert Watson */ 1123b67cbc65SPeter Wemm /* ARGSUSED */ 1124b67cbc65SPeter Wemm int 11254c44ad8eSJohn Baldwin issetugid(register struct thread *td, struct issetugid_args *uap) 1126b67cbc65SPeter Wemm { 1127b40ce416SJulian Elischer struct proc *p = td->td_proc; 1128b40ce416SJulian Elischer 1129b67cbc65SPeter Wemm /* 1130b67cbc65SPeter Wemm * Note: OpenBSD sets a P_SUGIDEXEC flag set at execve() time, 1131b67cbc65SPeter Wemm * we use P_SUGID because we consider changing the owners as 1132b67cbc65SPeter Wemm * "tainting" as well. 1133b67cbc65SPeter Wemm * This is significant for procs that start as root and "become" 1134b67cbc65SPeter Wemm * a user without an exec - programs cannot know *everything* 1135b67cbc65SPeter Wemm * that libc *might* have put in their data segment. 1136b67cbc65SPeter Wemm */ 1137f591779bSSeigo Tanimura PROC_LOCK(p); 1138b40ce416SJulian Elischer td->td_retval[0] = (p->p_flag & P_SUGID) ? 1 : 0; 1139f591779bSSeigo Tanimura PROC_UNLOCK(p); 1140b67cbc65SPeter Wemm return (0); 1141b67cbc65SPeter Wemm } 1142b67cbc65SPeter Wemm 1143835a82eeSMatthew Dillon /* 1144835a82eeSMatthew Dillon * MPSAFE 1145835a82eeSMatthew Dillon */ 1146130d0157SRobert Watson int 11474c44ad8eSJohn Baldwin __setugid(struct thread *td, struct __setugid_args *uap) 1148130d0157SRobert Watson { 1149130d0157SRobert Watson #ifdef REGRESSION 1150eb725b4eSRobert Watson int error; 1151835a82eeSMatthew Dillon 1152835a82eeSMatthew Dillon mtx_lock(&Giant); 1153eb725b4eSRobert Watson error = 0; 1154130d0157SRobert Watson switch (uap->flag) { 1155130d0157SRobert Watson case 0: 1156f591779bSSeigo Tanimura PROC_LOCK(td->td_proc); 1157b40ce416SJulian Elischer td->td_proc->p_flag &= ~P_SUGID; 1158f591779bSSeigo Tanimura PROC_UNLOCK(td->td_proc); 1159835a82eeSMatthew Dillon break; 1160130d0157SRobert Watson case 1: 1161f591779bSSeigo Tanimura PROC_LOCK(td->td_proc); 1162b40ce416SJulian Elischer td->td_proc->p_flag |= P_SUGID; 1163f591779bSSeigo Tanimura PROC_UNLOCK(td->td_proc); 1164835a82eeSMatthew Dillon break; 1165130d0157SRobert Watson default: 1166835a82eeSMatthew Dillon error = EINVAL; 1167835a82eeSMatthew Dillon break; 1168130d0157SRobert Watson } 1169835a82eeSMatthew Dillon mtx_unlock(&Giant); 1170835a82eeSMatthew Dillon return (error); 1171130d0157SRobert Watson #else /* !REGRESSION */ 1172eb725b4eSRobert Watson 1173130d0157SRobert Watson return (ENOSYS); 1174eb725b4eSRobert Watson #endif /* REGRESSION */ 1175130d0157SRobert Watson } 1176130d0157SRobert Watson 1177df8bae1dSRodney W. Grimes /* 1178df8bae1dSRodney W. Grimes * Check if gid is a member of the group set. 1179d74ac681SMatthew Dillon * 1180d74ac681SMatthew Dillon * MPSAFE (cred must be held) 1181df8bae1dSRodney W. Grimes */ 118226f9a767SRodney W. Grimes int 11834c44ad8eSJohn Baldwin groupmember(gid_t gid, struct ucred *cred) 1184df8bae1dSRodney W. Grimes { 1185df8bae1dSRodney W. Grimes register gid_t *gp; 1186df8bae1dSRodney W. Grimes gid_t *egp; 1187df8bae1dSRodney W. Grimes 1188df8bae1dSRodney W. Grimes egp = &(cred->cr_groups[cred->cr_ngroups]); 1189df8bae1dSRodney W. Grimes for (gp = cred->cr_groups; gp < egp; gp++) 1190df8bae1dSRodney W. Grimes if (*gp == gid) 1191df8bae1dSRodney W. Grimes return (1); 1192df8bae1dSRodney W. Grimes return (0); 1193df8bae1dSRodney W. Grimes } 1194df8bae1dSRodney W. Grimes 11953b243b72SRobert Watson /* 1196d0615c64SAndrew R. Reiter * `suser_enabled' (which can be set by the security.suser_enabled 11977fd6a959SRobert Watson * sysctl) determines whether the system 'super-user' policy is in effect. 11987fd6a959SRobert Watson * If it is nonzero, an effective uid of 0 connotes special privilege, 11997fd6a959SRobert Watson * overriding many mandatory and discretionary protections. If it is zero, 12007fd6a959SRobert Watson * uid 0 is offered no special privilege in the kernel security policy. 12017fd6a959SRobert Watson * Setting it to zero may seriously impact the functionality of many 12027fd6a959SRobert Watson * existing userland programs, and should not be done without careful 12037fd6a959SRobert Watson * consideration of the consequences. 12043b243b72SRobert Watson */ 120593f4fd1cSRobert Watson int suser_enabled = 1; 1206d0615c64SAndrew R. Reiter SYSCTL_INT(_security_bsd, OID_AUTO, suser_enabled, CTLFLAG_RW, 120793f4fd1cSRobert Watson &suser_enabled, 0, "processes with uid 0 have privilege"); 1208d0615c64SAndrew R. Reiter TUNABLE_INT("security.bsd.suser_enabled", &suser_enabled); 1209579f4eb4SRobert Watson 1210df8bae1dSRodney W. Grimes /* 12117fd6a959SRobert Watson * Test whether the specified credentials imply "super-user" privilege. 121244731cabSJohn Baldwin * Return 0 or EPERM. The flag argument is currently used only to 121344731cabSJohn Baldwin * specify jail interaction. 1214df8bae1dSRodney W. Grimes */ 121526f9a767SRodney W. Grimes int 121644731cabSJohn Baldwin suser_cred(struct ucred *cred, int flag) 1217f711d546SPoul-Henning Kamp { 1218eb725b4eSRobert Watson 121993f4fd1cSRobert Watson if (!suser_enabled) 122003095547SRobert Watson return (EPERM); 122175c13541SPoul-Henning Kamp if (cred->cr_uid != 0) 122275c13541SPoul-Henning Kamp return (EPERM); 122391421ba2SRobert Watson if (jailed(cred) && !(flag & PRISON_ROOT)) 122475c13541SPoul-Henning Kamp return (EPERM); 122575c13541SPoul-Henning Kamp return (0); 122675c13541SPoul-Henning Kamp } 1227df8bae1dSRodney W. Grimes 12283ca719f1SRobert Watson /* 122944731cabSJohn Baldwin * Shortcut to hide contents of struct td and struct proc from the 123044731cabSJohn Baldwin * caller, promoting binary compatibility. 123144731cabSJohn Baldwin */ 123244731cabSJohn Baldwin int 123344731cabSJohn Baldwin suser(struct thread *td) 123444731cabSJohn Baldwin { 123544731cabSJohn Baldwin 123644731cabSJohn Baldwin return (suser_cred(td->td_ucred, 0)); 123744731cabSJohn Baldwin } 123844731cabSJohn Baldwin 123944731cabSJohn Baldwin /* 1240eb725b4eSRobert Watson * Test the active securelevel against a given level. securelevel_gt() 1241eb725b4eSRobert Watson * implements (securelevel > level). securelevel_ge() implements 1242eb725b4eSRobert Watson * (securelevel >= level). Note that the logic is inverted -- these 1243eb725b4eSRobert Watson * functions return EPERM on "success" and 0 on "failure". 12443ca719f1SRobert Watson * 1245d74ac681SMatthew Dillon * MPSAFE 12463ca719f1SRobert Watson */ 12473ca719f1SRobert Watson int 12483ca719f1SRobert Watson securelevel_gt(struct ucred *cr, int level) 12493ca719f1SRobert Watson { 1250eb725b4eSRobert Watson int active_securelevel; 12513ca719f1SRobert Watson 1252eb725b4eSRobert Watson active_securelevel = securelevel; 125370499328SJohn Baldwin KASSERT(cr != NULL, ("securelevel_gt: null cr")); 125401137630SRobert Watson if (cr->cr_prison != NULL) { 125501137630SRobert Watson mtx_lock(&cr->cr_prison->pr_mtx); 1256eb725b4eSRobert Watson active_securelevel = imax(cr->cr_prison->pr_securelevel, 1257eb725b4eSRobert Watson active_securelevel); 125801137630SRobert Watson mtx_unlock(&cr->cr_prison->pr_mtx); 125901137630SRobert Watson } 1260eb725b4eSRobert Watson return (active_securelevel > level ? EPERM : 0); 12613ca719f1SRobert Watson } 12623ca719f1SRobert Watson 12633ca719f1SRobert Watson int 12643ca719f1SRobert Watson securelevel_ge(struct ucred *cr, int level) 12653ca719f1SRobert Watson { 1266eb725b4eSRobert Watson int active_securelevel; 12673ca719f1SRobert Watson 1268eb725b4eSRobert Watson active_securelevel = securelevel; 126970499328SJohn Baldwin KASSERT(cr != NULL, ("securelevel_ge: null cr")); 127001137630SRobert Watson if (cr->cr_prison != NULL) { 127101137630SRobert Watson mtx_lock(&cr->cr_prison->pr_mtx); 1272eb725b4eSRobert Watson active_securelevel = imax(cr->cr_prison->pr_securelevel, 1273eb725b4eSRobert Watson active_securelevel); 127401137630SRobert Watson mtx_unlock(&cr->cr_prison->pr_mtx); 127501137630SRobert Watson } 1276eb725b4eSRobert Watson return (active_securelevel >= level ? EPERM : 0); 12773ca719f1SRobert Watson } 12783ca719f1SRobert Watson 12798a7d8cc6SRobert Watson /* 1280e409590dSRobert Watson * 'see_other_uids' determines whether or not visibility of processes 1281eb725b4eSRobert Watson * and sockets with credentials holding different real uids is possible 128248713bdcSRobert Watson * using a variety of system MIBs. 1283eb725b4eSRobert Watson * XXX: data declarations should be together near the beginning of the file. 12848a7d8cc6SRobert Watson */ 1285e409590dSRobert Watson static int see_other_uids = 1; 1286d0615c64SAndrew R. Reiter SYSCTL_INT(_security_bsd, OID_AUTO, see_other_uids, CTLFLAG_RW, 1287eb725b4eSRobert Watson &see_other_uids, 0, 12888a7d8cc6SRobert Watson "Unprivileged processes may see subjects/objects with different real uid"); 12898a7d8cc6SRobert Watson 12907fd6a959SRobert Watson /*- 12911b350b45SRobert Watson * Determine if u1 "can see" the subject specified by u2, according to the 12921b350b45SRobert Watson * 'see_other_uids' policy. 12931b350b45SRobert Watson * Returns: 0 for permitted, ESRCH otherwise 12941b350b45SRobert Watson * Locks: none 12951b350b45SRobert Watson * References: *u1 and *u2 must not change during the call 12961b350b45SRobert Watson * u1 may equal u2, in which case only one reference is required 12971b350b45SRobert Watson */ 12981b350b45SRobert Watson static int 12991b350b45SRobert Watson cr_seeotheruids(struct ucred *u1, struct ucred *u2) 13001b350b45SRobert Watson { 13011b350b45SRobert Watson 13021b350b45SRobert Watson if (!see_other_uids && u1->cr_ruid != u2->cr_ruid) { 130344731cabSJohn Baldwin if (suser_cred(u1, PRISON_ROOT) != 0) 13041b350b45SRobert Watson return (ESRCH); 13051b350b45SRobert Watson } 13061b350b45SRobert Watson return (0); 13071b350b45SRobert Watson } 13081b350b45SRobert Watson 13091b350b45SRobert Watson /*- 13107fd6a959SRobert Watson * Determine if u1 "can see" the subject specified by u2. 1311ed639720SRobert Watson * Returns: 0 for permitted, an errno value otherwise 1312ed639720SRobert Watson * Locks: none 1313eb725b4eSRobert Watson * References: *u1 and *u2 must not change during the call 1314ed639720SRobert Watson * u1 may equal u2, in which case only one reference is required 1315ed639720SRobert Watson */ 1316ed639720SRobert Watson int 131794088977SRobert Watson cr_cansee(struct ucred *u1, struct ucred *u2) 1318a9e0361bSPoul-Henning Kamp { 131991421ba2SRobert Watson int error; 1320a9e0361bSPoul-Henning Kamp 1321ed639720SRobert Watson if ((error = prison_check(u1, u2))) 132291421ba2SRobert Watson return (error); 13231b350b45SRobert Watson if ((error = cr_seeotheruids(u1, u2))) 13241b350b45SRobert Watson return (error); 1325387d2c03SRobert Watson return (0); 1326387d2c03SRobert Watson } 1327387d2c03SRobert Watson 13287fd6a959SRobert Watson /*- 13297fd6a959SRobert Watson * Determine if p1 "can see" the subject specified by p2. 13303b243b72SRobert Watson * Returns: 0 for permitted, an errno value otherwise 13317fd6a959SRobert Watson * Locks: Sufficient locks to protect p1->p_ucred and p2->p_ucred must 13323b243b72SRobert Watson * be held. Normally, p1 will be curproc, and a lock must be held 13333b243b72SRobert Watson * for p2. 13343b243b72SRobert Watson * References: p1 and p2 must be valid for the lifetime of the call 13353b243b72SRobert Watson */ 1336a0f75161SRobert Watson int 1337a0f75161SRobert Watson p_cansee(struct proc *p1, struct proc *p2) 1338ed639720SRobert Watson { 1339ed639720SRobert Watson 134094088977SRobert Watson /* Wrap cr_cansee() for all functionality. */ 134194088977SRobert Watson return (cr_cansee(p1->p_ucred, p2->p_ucred)); 1342ed639720SRobert Watson } 1343ed639720SRobert Watson 13447fd6a959SRobert Watson /*- 1345c83f8015SRobert Watson * Determine whether cred may deliver the specified signal to proc. 1346c83f8015SRobert Watson * Returns: 0 for permitted, an errno value otherwise. 1347c83f8015SRobert Watson * Locks: A lock must be held for proc. 1348c83f8015SRobert Watson * References: cred and proc must be valid for the lifetime of the call. 13494c5eb9c3SRobert Watson */ 13504c5eb9c3SRobert Watson int 1351c83f8015SRobert Watson cr_cansignal(struct ucred *cred, struct proc *proc, int signum) 1352387d2c03SRobert Watson { 135391421ba2SRobert Watson int error; 1354387d2c03SRobert Watson 13554c5eb9c3SRobert Watson /* 1356c83f8015SRobert Watson * Jail semantics limit the scope of signalling to proc in the 1357c83f8015SRobert Watson * same jail as cred, if cred is in jail. 13584c5eb9c3SRobert Watson */ 1359c83f8015SRobert Watson error = prison_check(cred, proc->p_ucred); 1360c83f8015SRobert Watson if (error) 136191421ba2SRobert Watson return (error); 13621b350b45SRobert Watson error = cr_seeotheruids(cred, proc->p_ucred); 13631b350b45SRobert Watson if (error) 13641b350b45SRobert Watson return (error); 1365387d2c03SRobert Watson 1366387d2c03SRobert Watson /* 13673b243b72SRobert Watson * UNIX signal semantics depend on the status of the P_SUGID 13683b243b72SRobert Watson * bit on the target process. If the bit is set, then additional 13693b243b72SRobert Watson * restrictions are placed on the set of available signals. 13704c5eb9c3SRobert Watson */ 1371c83f8015SRobert Watson if (proc->p_flag & P_SUGID) { 13724c5eb9c3SRobert Watson switch (signum) { 13734c5eb9c3SRobert Watson case 0: 13744c5eb9c3SRobert Watson case SIGKILL: 13754c5eb9c3SRobert Watson case SIGINT: 13764c5eb9c3SRobert Watson case SIGTERM: 13774c5eb9c3SRobert Watson case SIGSTOP: 13784c5eb9c3SRobert Watson case SIGTTIN: 13794c5eb9c3SRobert Watson case SIGTTOU: 13804c5eb9c3SRobert Watson case SIGTSTP: 13814c5eb9c3SRobert Watson case SIGHUP: 13824c5eb9c3SRobert Watson case SIGUSR1: 13834c5eb9c3SRobert Watson case SIGUSR2: 13847fd6a959SRobert Watson /* 13857fd6a959SRobert Watson * Generally, permit job and terminal control 13867fd6a959SRobert Watson * signals. 13877fd6a959SRobert Watson */ 13884c5eb9c3SRobert Watson break; 13894c5eb9c3SRobert Watson default: 1390c83f8015SRobert Watson /* Not permitted without privilege. */ 139144731cabSJohn Baldwin error = suser_cred(cred, PRISON_ROOT); 13924c5eb9c3SRobert Watson if (error) 13934c5eb9c3SRobert Watson return (error); 13944c5eb9c3SRobert Watson } 1395e9e7ff5bSRobert Watson } 1396e9e7ff5bSRobert Watson 13974c5eb9c3SRobert Watson /* 13983b243b72SRobert Watson * Generally, the target credential's ruid or svuid must match the 1399e9e7ff5bSRobert Watson * subject credential's ruid or euid. 14004c5eb9c3SRobert Watson */ 1401c83f8015SRobert Watson if (cred->cr_ruid != proc->p_ucred->cr_ruid && 1402c83f8015SRobert Watson cred->cr_ruid != proc->p_ucred->cr_svuid && 1403c83f8015SRobert Watson cred->cr_uid != proc->p_ucred->cr_ruid && 1404c83f8015SRobert Watson cred->cr_uid != proc->p_ucred->cr_svuid) { 1405c83f8015SRobert Watson /* Not permitted without privilege. */ 140644731cabSJohn Baldwin error = suser_cred(cred, PRISON_ROOT); 14074c5eb9c3SRobert Watson if (error) 14084c5eb9c3SRobert Watson return (error); 14094c5eb9c3SRobert Watson } 1410387d2c03SRobert Watson 1411387d2c03SRobert Watson return (0); 1412387d2c03SRobert Watson } 1413a9e0361bSPoul-Henning Kamp 1414c83f8015SRobert Watson 1415c83f8015SRobert Watson /*- 1416c83f8015SRobert Watson * Determine whether p1 may deliver the specified signal to p2. 1417c83f8015SRobert Watson * Returns: 0 for permitted, an errno value otherwise 1418c83f8015SRobert Watson * Locks: Sufficient locks to protect various components of p1 and p2 1419c83f8015SRobert Watson * must be held. Normally, p1 will be curproc, and a lock must 1420c83f8015SRobert Watson * be held for p2. 1421c83f8015SRobert Watson * References: p1 and p2 must be valid for the lifetime of the call 1422c83f8015SRobert Watson */ 1423c83f8015SRobert Watson int 1424c83f8015SRobert Watson p_cansignal(struct proc *p1, struct proc *p2, int signum) 1425c83f8015SRobert Watson { 1426c83f8015SRobert Watson 1427c83f8015SRobert Watson if (p1 == p2) 1428c83f8015SRobert Watson return (0); 1429c83f8015SRobert Watson 1430c83f8015SRobert Watson /* 1431c83f8015SRobert Watson * UNIX signalling semantics require that processes in the same 1432c83f8015SRobert Watson * session always be able to deliver SIGCONT to one another, 1433c83f8015SRobert Watson * overriding the remaining protections. 1434c83f8015SRobert Watson */ 1435c83f8015SRobert Watson if (signum == SIGCONT && p1->p_session == p2->p_session) 1436c83f8015SRobert Watson return (0); 1437c83f8015SRobert Watson 1438c83f8015SRobert Watson return (cr_cansignal(p1->p_ucred, p2, signum)); 1439c83f8015SRobert Watson } 1440c83f8015SRobert Watson 14417fd6a959SRobert Watson /*- 1442eb725b4eSRobert Watson * Determine whether p1 may reschedule p2. 14437fd6a959SRobert Watson * Returns: 0 for permitted, an errno value otherwise 14443b243b72SRobert Watson * Locks: Sufficient locks to protect various components of p1 and p2 14453b243b72SRobert Watson * must be held. Normally, p1 will be curproc, and a lock must 14467fd6a959SRobert Watson * be held for p2. 14473b243b72SRobert Watson * References: p1 and p2 must be valid for the lifetime of the call 14483b243b72SRobert Watson */ 1449a0f75161SRobert Watson int 1450a0f75161SRobert Watson p_cansched(struct proc *p1, struct proc *p2) 1451387d2c03SRobert Watson { 145291421ba2SRobert Watson int error; 1453387d2c03SRobert Watson 1454387d2c03SRobert Watson if (p1 == p2) 1455387d2c03SRobert Watson return (0); 145691421ba2SRobert Watson if ((error = prison_check(p1->p_ucred, p2->p_ucred))) 145791421ba2SRobert Watson return (error); 14581b350b45SRobert Watson if ((error = cr_seeotheruids(p1->p_ucred, p2->p_ucred))) 14591b350b45SRobert Watson return (error); 1460b1fc0ec1SRobert Watson if (p1->p_ucred->cr_ruid == p2->p_ucred->cr_ruid) 1461387d2c03SRobert Watson return (0); 1462b1fc0ec1SRobert Watson if (p1->p_ucred->cr_uid == p2->p_ucred->cr_ruid) 1463387d2c03SRobert Watson return (0); 146444731cabSJohn Baldwin if (suser_cred(p1->p_ucred, PRISON_ROOT) == 0) 1465387d2c03SRobert Watson return (0); 1466387d2c03SRobert Watson 1467387d2c03SRobert Watson #ifdef CAPABILITIES 14684df571b1SRobert Watson if (!cap_check(NULL, p1, CAP_SYS_NICE, PRISON_ROOT)) 1469387d2c03SRobert Watson return (0); 1470387d2c03SRobert Watson #endif 1471387d2c03SRobert Watson 1472387d2c03SRobert Watson return (EPERM); 1473387d2c03SRobert Watson } 1474387d2c03SRobert Watson 14753b243b72SRobert Watson /* 14765d476e73SRobert Watson * The 'unprivileged_proc_debug' flag may be used to disable a variety of 14775d476e73SRobert Watson * unprivileged inter-process debugging services, including some procfs 14785d476e73SRobert Watson * functionality, ptrace(), and ktrace(). In the past, inter-process 14795d476e73SRobert Watson * debugging has been involved in a variety of security problems, and sites 14805d476e73SRobert Watson * not requiring the service might choose to disable it when hardening 14815d476e73SRobert Watson * systems. 14823b243b72SRobert Watson * 14833b243b72SRobert Watson * XXX: Should modifying and reading this variable require locking? 1484eb725b4eSRobert Watson * XXX: data declarations should be together near the beginning of the file. 14853b243b72SRobert Watson */ 1486e409590dSRobert Watson static int unprivileged_proc_debug = 1; 1487d0615c64SAndrew R. Reiter SYSCTL_INT(_security_bsd, OID_AUTO, unprivileged_proc_debug, CTLFLAG_RW, 1488eb725b4eSRobert Watson &unprivileged_proc_debug, 0, 14890ef5652eSRobert Watson "Unprivileged processes may use process debugging facilities"); 14900ef5652eSRobert Watson 14917fd6a959SRobert Watson /*- 14927fd6a959SRobert Watson * Determine whether p1 may debug p2. 14937fd6a959SRobert Watson * Returns: 0 for permitted, an errno value otherwise 14947fd6a959SRobert Watson * Locks: Sufficient locks to protect various components of p1 and p2 14957fd6a959SRobert Watson * must be held. Normally, p1 will be curproc, and a lock must 14967fd6a959SRobert Watson * be held for p2. 14973b243b72SRobert Watson * References: p1 and p2 must be valid for the lifetime of the call 14983b243b72SRobert Watson */ 1499a0f75161SRobert Watson int 1500a0f75161SRobert Watson p_candebug(struct proc *p1, struct proc *p2) 1501387d2c03SRobert Watson { 1502eb725b4eSRobert Watson int credentialchanged, error, grpsubset, i, uidsubset; 1503387d2c03SRobert Watson 1504e409590dSRobert Watson if (!unprivileged_proc_debug) { 150544731cabSJohn Baldwin error = suser_cred(p1->p_ucred, PRISON_ROOT); 150632d18604SRobert Watson if (error) 150732d18604SRobert Watson return (error); 150832d18604SRobert Watson } 150923fad5b6SDag-Erling Smørgrav if (p1 == p2) 151023fad5b6SDag-Erling Smørgrav return (0); 151191421ba2SRobert Watson if ((error = prison_check(p1->p_ucred, p2->p_ucred))) 151291421ba2SRobert Watson return (error); 15131b350b45SRobert Watson if ((error = cr_seeotheruids(p1->p_ucred, p2->p_ucred))) 15141b350b45SRobert Watson return (error); 1515387d2c03SRobert Watson 15167fd6a959SRobert Watson /* 1517db42a33dSRobert Watson * Is p2's group set a subset of p1's effective group set? This 1518db42a33dSRobert Watson * includes p2's egid, group access list, rgid, and svgid. 15197fd6a959SRobert Watson */ 1520db42a33dSRobert Watson grpsubset = 1; 1521db42a33dSRobert Watson for (i = 0; i < p2->p_ucred->cr_ngroups; i++) { 1522db42a33dSRobert Watson if (!groupmember(p2->p_ucred->cr_groups[i], p1->p_ucred)) { 1523db42a33dSRobert Watson grpsubset = 0; 1524db42a33dSRobert Watson break; 1525db42a33dSRobert Watson } 1526db42a33dSRobert Watson } 1527db42a33dSRobert Watson grpsubset = grpsubset && 1528db42a33dSRobert Watson groupmember(p2->p_ucred->cr_rgid, p1->p_ucred) && 1529db42a33dSRobert Watson groupmember(p2->p_ucred->cr_svgid, p1->p_ucred); 1530db42a33dSRobert Watson 1531db42a33dSRobert Watson /* 1532db42a33dSRobert Watson * Are the uids present in p2's credential equal to p1's 1533db42a33dSRobert Watson * effective uid? This includes p2's euid, svuid, and ruid. 1534db42a33dSRobert Watson */ 1535db42a33dSRobert Watson uidsubset = (p1->p_ucred->cr_uid == p2->p_ucred->cr_uid && 1536db42a33dSRobert Watson p1->p_ucred->cr_uid == p2->p_ucred->cr_svuid && 1537db42a33dSRobert Watson p1->p_ucred->cr_uid == p2->p_ucred->cr_ruid); 1538db42a33dSRobert Watson 1539db42a33dSRobert Watson /* 1540db42a33dSRobert Watson * Has the credential of the process changed since the last exec()? 1541db42a33dSRobert Watson */ 1542db42a33dSRobert Watson credentialchanged = (p2->p_flag & P_SUGID); 1543db42a33dSRobert Watson 1544db42a33dSRobert Watson /* 1545db42a33dSRobert Watson * If p2's gids aren't a subset, or the uids aren't a subset, 1546db42a33dSRobert Watson * or the credential has changed, require appropriate privilege 1547db42a33dSRobert Watson * for p1 to debug p2. For POSIX.1e capabilities, this will 1548db42a33dSRobert Watson * require CAP_SYS_PTRACE. 1549db42a33dSRobert Watson */ 1550db42a33dSRobert Watson if (!grpsubset || !uidsubset || credentialchanged) { 155144731cabSJohn Baldwin error = suser_cred(p1->p_ucred, PRISON_ROOT); 155232d18604SRobert Watson if (error) 1553387d2c03SRobert Watson return (error); 15547fd6a959SRobert Watson } 1555387d2c03SRobert Watson 1556eb725b4eSRobert Watson /* Can't trace init when securelevel > 0. */ 1557eb725b4eSRobert Watson if (p2 == initproc) { 15583ca719f1SRobert Watson error = securelevel_gt(p1->p_ucred, 0); 15593ca719f1SRobert Watson if (error) 15603ca719f1SRobert Watson return (error); 15613ca719f1SRobert Watson } 1562387d2c03SRobert Watson 15635fab7614SRobert Watson /* 15645fab7614SRobert Watson * Can't trace a process that's currently exec'ing. 15655fab7614SRobert Watson * XXX: Note, this is not a security policy decision, it's a 15665fab7614SRobert Watson * basic correctness/functionality decision. Therefore, this check 15675fab7614SRobert Watson * should be moved to the caller's of p_candebug(). 15685fab7614SRobert Watson */ 15699ca45e81SDag-Erling Smørgrav if ((p2->p_flag & P_INEXEC) != 0) 15709ca45e81SDag-Erling Smørgrav return (EAGAIN); 15719ca45e81SDag-Erling Smørgrav 1572387d2c03SRobert Watson return (0); 1573387d2c03SRobert Watson } 1574387d2c03SRobert Watson 157529dc1288SRobert Watson /*- 157629dc1288SRobert Watson * Determine whether the subject represented by cred can "see" a socket. 157729dc1288SRobert Watson * Returns: 0 for permitted, ENOENT otherwise. 157829dc1288SRobert Watson */ 157929dc1288SRobert Watson int 158029dc1288SRobert Watson cr_canseesocket(struct ucred *cred, struct socket *so) 158129dc1288SRobert Watson { 158229dc1288SRobert Watson int error; 158329dc1288SRobert Watson 158429dc1288SRobert Watson error = prison_check(cred, so->so_cred); 158529dc1288SRobert Watson if (error) 158629dc1288SRobert Watson return (ENOENT); 158729dc1288SRobert Watson if (cr_seeotheruids(cred, so->so_cred)) 158829dc1288SRobert Watson return (ENOENT); 158929dc1288SRobert Watson #ifdef MAC 159029dc1288SRobert Watson /* XXX: error = mac_cred_check_seesocket() here. */ 159129dc1288SRobert Watson #endif 159229dc1288SRobert Watson 159329dc1288SRobert Watson return (0); 159429dc1288SRobert Watson } 159529dc1288SRobert Watson 1596a9e0361bSPoul-Henning Kamp /* 1597df8bae1dSRodney W. Grimes * Allocate a zeroed cred structure. 1598df8bae1dSRodney W. Grimes */ 1599df8bae1dSRodney W. Grimes struct ucred * 16004c44ad8eSJohn Baldwin crget(void) 1601df8bae1dSRodney W. Grimes { 1602df8bae1dSRodney W. Grimes register struct ucred *cr; 1603df8bae1dSRodney W. Grimes 16041e5d626aSAlfred Perlstein MALLOC(cr, struct ucred *, sizeof(*cr), M_CRED, M_WAITOK | M_ZERO); 1605df8bae1dSRodney W. Grimes cr->cr_ref = 1; 1606e1bca29fSMatthew Dillon cr->cr_mtxp = mtx_pool_find(cr); 1607df8bae1dSRodney W. Grimes return (cr); 1608df8bae1dSRodney W. Grimes } 1609df8bae1dSRodney W. Grimes 1610df8bae1dSRodney W. Grimes /* 16117fd6a959SRobert Watson * Claim another reference to a ucred structure. 16125c3f70d7SAlfred Perlstein */ 1613bd78ceceSJohn Baldwin struct ucred * 16144c44ad8eSJohn Baldwin crhold(struct ucred *cr) 16155c3f70d7SAlfred Perlstein { 16165c3f70d7SAlfred Perlstein 1617e1bca29fSMatthew Dillon mtx_lock(cr->cr_mtxp); 16185c3f70d7SAlfred Perlstein cr->cr_ref++; 1619e1bca29fSMatthew Dillon mtx_unlock(cr->cr_mtxp); 1620bd78ceceSJohn Baldwin return (cr); 16215c3f70d7SAlfred Perlstein } 16225c3f70d7SAlfred Perlstein 16235c3f70d7SAlfred Perlstein /* 1624df8bae1dSRodney W. Grimes * Free a cred structure. 1625df8bae1dSRodney W. Grimes * Throws away space when ref count gets to 0. 1626df8bae1dSRodney W. Grimes */ 162726f9a767SRodney W. Grimes void 16284c44ad8eSJohn Baldwin crfree(struct ucred *cr) 1629df8bae1dSRodney W. Grimes { 1630e1bca29fSMatthew Dillon struct mtx *mtxp = cr->cr_mtxp; 16311e5d626aSAlfred Perlstein 1632e1bca29fSMatthew Dillon mtx_lock(mtxp); 1633e04670b7SAlfred Perlstein KASSERT(cr->cr_ref > 0, ("bad ucred refcount: %d", cr->cr_ref)); 1634f535380cSDon Lewis if (--cr->cr_ref == 0) { 1635f535380cSDon Lewis /* 1636f535380cSDon Lewis * Some callers of crget(), such as nfs_statfs(), 1637f535380cSDon Lewis * allocate a temporary credential, but don't 1638f535380cSDon Lewis * allocate a uidinfo structure. 1639f535380cSDon Lewis */ 1640e1bca29fSMatthew Dillon mtx_unlock(mtxp); 1641c1a513c9SJohn Baldwin mtx_lock(&Giant); 1642f535380cSDon Lewis if (cr->cr_uidinfo != NULL) 1643f535380cSDon Lewis uifree(cr->cr_uidinfo); 1644823c224eSRobert Watson if (cr->cr_ruidinfo != NULL) 1645823c224eSRobert Watson uifree(cr->cr_ruidinfo); 164691421ba2SRobert Watson /* 164791421ba2SRobert Watson * Free a prison, if any. 164891421ba2SRobert Watson */ 164991421ba2SRobert Watson if (jailed(cr)) 165091421ba2SRobert Watson prison_free(cr->cr_prison); 1651df8bae1dSRodney W. Grimes FREE((caddr_t)cr, M_CRED); 1652c1a513c9SJohn Baldwin mtx_unlock(&Giant); 1653e1bca29fSMatthew Dillon } else { 1654e1bca29fSMatthew Dillon mtx_unlock(mtxp); 1655e1bca29fSMatthew Dillon } 1656df8bae1dSRodney W. Grimes } 1657df8bae1dSRodney W. Grimes 1658df8bae1dSRodney W. Grimes /* 1659bd78ceceSJohn Baldwin * Check to see if this ucred is shared. 1660df8bae1dSRodney W. Grimes */ 1661bd78ceceSJohn Baldwin int 16624c44ad8eSJohn Baldwin crshared(struct ucred *cr) 1663df8bae1dSRodney W. Grimes { 1664bd78ceceSJohn Baldwin int shared; 1665df8bae1dSRodney W. Grimes 1666e1bca29fSMatthew Dillon mtx_lock(cr->cr_mtxp); 1667bd78ceceSJohn Baldwin shared = (cr->cr_ref > 1); 1668e1bca29fSMatthew Dillon mtx_unlock(cr->cr_mtxp); 1669bd78ceceSJohn Baldwin return (shared); 16701e5d626aSAlfred Perlstein } 1671bd78ceceSJohn Baldwin 1672bd78ceceSJohn Baldwin /* 1673bd78ceceSJohn Baldwin * Copy a ucred's contents from a template. Does not block. 1674bd78ceceSJohn Baldwin */ 1675bd78ceceSJohn Baldwin void 16764c44ad8eSJohn Baldwin crcopy(struct ucred *dest, struct ucred *src) 1677bd78ceceSJohn Baldwin { 1678bd78ceceSJohn Baldwin 1679bd78ceceSJohn Baldwin KASSERT(crshared(dest) == 0, ("crcopy of shared ucred")); 1680bd78ceceSJohn Baldwin bcopy(&src->cr_startcopy, &dest->cr_startcopy, 1681bd78ceceSJohn Baldwin (unsigned)((caddr_t)&src->cr_endcopy - 1682bd78ceceSJohn Baldwin (caddr_t)&src->cr_startcopy)); 1683bd78ceceSJohn Baldwin uihold(dest->cr_uidinfo); 1684bd78ceceSJohn Baldwin uihold(dest->cr_ruidinfo); 1685bd78ceceSJohn Baldwin if (jailed(dest)) 1686bd78ceceSJohn Baldwin prison_hold(dest->cr_prison); 1687df8bae1dSRodney W. Grimes } 1688df8bae1dSRodney W. Grimes 1689df8bae1dSRodney W. Grimes /* 1690df8bae1dSRodney W. Grimes * Dup cred struct to a new held one. 1691df8bae1dSRodney W. Grimes */ 1692df8bae1dSRodney W. Grimes struct ucred * 16934c44ad8eSJohn Baldwin crdup(struct ucred *cr) 1694df8bae1dSRodney W. Grimes { 1695df8bae1dSRodney W. Grimes struct ucred *newcr; 1696df8bae1dSRodney W. Grimes 1697bd78ceceSJohn Baldwin newcr = crget(); 1698bd78ceceSJohn Baldwin crcopy(newcr, cr); 1699df8bae1dSRodney W. Grimes return (newcr); 1700df8bae1dSRodney W. Grimes } 1701df8bae1dSRodney W. Grimes 1702c1a513c9SJohn Baldwin #ifdef DIAGNOSTIC 1703c1a513c9SJohn Baldwin void 1704c1a513c9SJohn Baldwin cred_free_thread(struct thread *td) 1705c1a513c9SJohn Baldwin { 1706c1a513c9SJohn Baldwin struct ucred *cred; 1707c1a513c9SJohn Baldwin 1708c1a513c9SJohn Baldwin cred = td->td_ucred; 1709c1a513c9SJohn Baldwin td->td_ucred = NULL; 1710c1a513c9SJohn Baldwin if (cred != NULL) 1711c1a513c9SJohn Baldwin crfree(cred); 1712c1a513c9SJohn Baldwin } 1713c1a513c9SJohn Baldwin #endif 1714c1a513c9SJohn Baldwin 1715df8bae1dSRodney W. Grimes /* 171676183f34SDima Dorfman * Fill in a struct xucred based on a struct ucred. 171776183f34SDima Dorfman */ 171876183f34SDima Dorfman void 17194c44ad8eSJohn Baldwin cru2x(struct ucred *cr, struct xucred *xcr) 172076183f34SDima Dorfman { 172176183f34SDima Dorfman 172276183f34SDima Dorfman bzero(xcr, sizeof(*xcr)); 172376183f34SDima Dorfman xcr->cr_version = XUCRED_VERSION; 172476183f34SDima Dorfman xcr->cr_uid = cr->cr_uid; 172576183f34SDima Dorfman xcr->cr_ngroups = cr->cr_ngroups; 172676183f34SDima Dorfman bcopy(cr->cr_groups, xcr->cr_groups, sizeof(cr->cr_groups)); 172776183f34SDima Dorfman } 172876183f34SDima Dorfman 172976183f34SDima Dorfman /* 17302eb927e2SJulian Elischer * small routine to swap a thread's current ucred for the correct one 17312eb927e2SJulian Elischer * taken from the process. 17322eb927e2SJulian Elischer */ 17332eb927e2SJulian Elischer void 17342eb927e2SJulian Elischer cred_update_thread(struct thread *td) 17352eb927e2SJulian Elischer { 17362eb927e2SJulian Elischer struct proc *p; 173765e3406dSJohn Baldwin struct ucred *cred; 17382eb927e2SJulian Elischer 17392eb927e2SJulian Elischer p = td->td_proc; 174065e3406dSJohn Baldwin cred = td->td_ucred; 17412eb927e2SJulian Elischer mtx_lock(&Giant); 17422eb927e2SJulian Elischer PROC_LOCK(p); 17432eb927e2SJulian Elischer td->td_ucred = crhold(p->p_ucred); 17442eb927e2SJulian Elischer PROC_UNLOCK(p); 174565e3406dSJohn Baldwin if (cred != NULL) 174665e3406dSJohn Baldwin crfree(cred); 174765e3406dSJohn Baldwin mtx_unlock(&Giant); 17482eb927e2SJulian Elischer } 17492eb927e2SJulian Elischer 17502eb927e2SJulian Elischer /* 1751df8bae1dSRodney W. Grimes * Get login name, if available. 1752df8bae1dSRodney W. Grimes */ 1753d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 1754df8bae1dSRodney W. Grimes struct getlogin_args { 1755df8bae1dSRodney W. Grimes char *namebuf; 1756df8bae1dSRodney W. Grimes u_int namelen; 1757df8bae1dSRodney W. Grimes }; 1758d2d3e875SBruce Evans #endif 1759835a82eeSMatthew Dillon /* 1760835a82eeSMatthew Dillon * MPSAFE 1761835a82eeSMatthew Dillon */ 1762df8bae1dSRodney W. Grimes /* ARGSUSED */ 176326f9a767SRodney W. Grimes int 17644c44ad8eSJohn Baldwin getlogin(struct thread *td, struct getlogin_args *uap) 1765df8bae1dSRodney W. Grimes { 1766835a82eeSMatthew Dillon int error; 1767f591779bSSeigo Tanimura char login[MAXLOGNAME]; 1768b40ce416SJulian Elischer struct proc *p = td->td_proc; 1769df8bae1dSRodney W. Grimes 1770835a82eeSMatthew Dillon mtx_lock(&Giant); 177130cf3ac4SAndrey A. Chernov if (uap->namelen > MAXLOGNAME) 177253490b76SAndrey A. Chernov uap->namelen = MAXLOGNAME; 1773f591779bSSeigo Tanimura PROC_LOCK(p); 1774f591779bSSeigo Tanimura SESS_LOCK(p->p_session); 1775f591779bSSeigo Tanimura bcopy(p->p_session->s_login, login, uap->namelen); 1776f591779bSSeigo Tanimura SESS_UNLOCK(p->p_session); 1777f591779bSSeigo Tanimura PROC_UNLOCK(p); 1778f591779bSSeigo Tanimura error = copyout((caddr_t) login, (caddr_t) uap->namebuf, uap->namelen); 1779835a82eeSMatthew Dillon mtx_unlock(&Giant); 1780835a82eeSMatthew Dillon return(error); 1781df8bae1dSRodney W. Grimes } 1782df8bae1dSRodney W. Grimes 1783df8bae1dSRodney W. Grimes /* 1784df8bae1dSRodney W. Grimes * Set login name. 1785df8bae1dSRodney W. Grimes */ 1786d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 1787df8bae1dSRodney W. Grimes struct setlogin_args { 1788df8bae1dSRodney W. Grimes char *namebuf; 1789df8bae1dSRodney W. Grimes }; 1790d2d3e875SBruce Evans #endif 1791835a82eeSMatthew Dillon /* 1792835a82eeSMatthew Dillon * MPSAFE 1793835a82eeSMatthew Dillon */ 1794df8bae1dSRodney W. Grimes /* ARGSUSED */ 179526f9a767SRodney W. Grimes int 17964c44ad8eSJohn Baldwin setlogin(struct thread *td, struct setlogin_args *uap) 1797df8bae1dSRodney W. Grimes { 1798b40ce416SJulian Elischer struct proc *p = td->td_proc; 1799df8bae1dSRodney W. Grimes int error; 1800964ca0caSAndrey A. Chernov char logintmp[MAXLOGNAME]; 1801df8bae1dSRodney W. Grimes 1802835a82eeSMatthew Dillon mtx_lock(&Giant); 180344731cabSJohn Baldwin if ((error = suser_cred(td->td_ucred, PRISON_ROOT)) != 0) 1804835a82eeSMatthew Dillon goto done2; 1805184989c2SDavid Nugent error = copyinstr((caddr_t) uap->namebuf, (caddr_t) logintmp, 180610d4743fSDoug Rabson sizeof(logintmp), (size_t *)0); 1807eb725b4eSRobert Watson if (error == ENAMETOOLONG) 1808df8bae1dSRodney W. Grimes error = EINVAL; 1809f591779bSSeigo Tanimura else if (!error) { 1810f591779bSSeigo Tanimura PROC_LOCK(p); 1811f591779bSSeigo Tanimura SESS_LOCK(p->p_session); 1812f591779bSSeigo Tanimura (void) memcpy(p->p_session->s_login, logintmp, 1813964ca0caSAndrey A. Chernov sizeof(logintmp)); 1814f591779bSSeigo Tanimura SESS_UNLOCK(p->p_session); 1815f591779bSSeigo Tanimura PROC_UNLOCK(p); 1816f591779bSSeigo Tanimura } 1817835a82eeSMatthew Dillon done2: 1818835a82eeSMatthew Dillon mtx_unlock(&Giant); 1819df8bae1dSRodney W. Grimes return (error); 1820df8bae1dSRodney W. Grimes } 1821d5f81602SSean Eric Fagan 1822d5f81602SSean Eric Fagan void 18234c44ad8eSJohn Baldwin setsugid(struct proc *p) 1824d5f81602SSean Eric Fagan { 1825d5f81602SSean Eric Fagan p->p_flag |= P_SUGID; 182689361835SSean Eric Fagan if (!(p->p_pfsflags & PF_ISUGID)) 1827d5f81602SSean Eric Fagan p->p_stops = 0; 1828d5f81602SSean Eric Fagan } 1829f535380cSDon Lewis 18307fd6a959SRobert Watson /*- 18317fd6a959SRobert Watson * Change a process's effective uid. 1832b1fc0ec1SRobert Watson * Side effects: newcred->cr_uid and newcred->cr_uidinfo will be modified. 1833b1fc0ec1SRobert Watson * References: newcred must be an exclusive credential reference for the 1834b1fc0ec1SRobert Watson * duration of the call. 1835f535380cSDon Lewis */ 1836f535380cSDon Lewis void 18374c44ad8eSJohn Baldwin change_euid(struct ucred *newcred, uid_t euid) 1838f535380cSDon Lewis { 1839f535380cSDon Lewis 1840b1fc0ec1SRobert Watson newcred->cr_uid = euid; 1841b1fc0ec1SRobert Watson uifree(newcred->cr_uidinfo); 1842b1fc0ec1SRobert Watson newcred->cr_uidinfo = uifind(euid); 1843f535380cSDon Lewis } 1844f535380cSDon Lewis 18457fd6a959SRobert Watson /*- 18467fd6a959SRobert Watson * Change a process's effective gid. 1847b1fc0ec1SRobert Watson * Side effects: newcred->cr_gid will be modified. 1848b1fc0ec1SRobert Watson * References: newcred must be an exclusive credential reference for the 1849b1fc0ec1SRobert Watson * duration of the call. 1850f535380cSDon Lewis */ 1851810bfc8eSAndrew Gallatin void 18524c44ad8eSJohn Baldwin change_egid(struct ucred *newcred, gid_t egid) 1853b1fc0ec1SRobert Watson { 1854b1fc0ec1SRobert Watson 1855b1fc0ec1SRobert Watson newcred->cr_groups[0] = egid; 1856b1fc0ec1SRobert Watson } 1857b1fc0ec1SRobert Watson 18587fd6a959SRobert Watson /*- 18597fd6a959SRobert Watson * Change a process's real uid. 1860b1fc0ec1SRobert Watson * Side effects: newcred->cr_ruid will be updated, newcred->cr_ruidinfo 1861b1fc0ec1SRobert Watson * will be updated, and the old and new cr_ruidinfo proc 1862b1fc0ec1SRobert Watson * counts will be updated. 1863b1fc0ec1SRobert Watson * References: newcred must be an exclusive credential reference for the 1864b1fc0ec1SRobert Watson * duration of the call. 1865b1fc0ec1SRobert Watson */ 1866b1fc0ec1SRobert Watson void 18674c44ad8eSJohn Baldwin change_ruid(struct ucred *newcred, uid_t ruid) 1868f535380cSDon Lewis { 1869f535380cSDon Lewis 1870b1fc0ec1SRobert Watson (void)chgproccnt(newcred->cr_ruidinfo, -1, 0); 1871b1fc0ec1SRobert Watson newcred->cr_ruid = ruid; 1872b1fc0ec1SRobert Watson uifree(newcred->cr_ruidinfo); 1873b1fc0ec1SRobert Watson newcred->cr_ruidinfo = uifind(ruid); 1874b1fc0ec1SRobert Watson (void)chgproccnt(newcred->cr_ruidinfo, 1, 0); 1875b1fc0ec1SRobert Watson } 1876b1fc0ec1SRobert Watson 18777fd6a959SRobert Watson /*- 18787fd6a959SRobert Watson * Change a process's real gid. 1879b1fc0ec1SRobert Watson * Side effects: newcred->cr_rgid will be updated. 1880b1fc0ec1SRobert Watson * References: newcred must be an exclusive credential reference for the 1881b1fc0ec1SRobert Watson * duration of the call. 1882b1fc0ec1SRobert Watson */ 1883b1fc0ec1SRobert Watson void 18844c44ad8eSJohn Baldwin change_rgid(struct ucred *newcred, gid_t rgid) 1885b1fc0ec1SRobert Watson { 1886b1fc0ec1SRobert Watson 1887b1fc0ec1SRobert Watson newcred->cr_rgid = rgid; 1888b1fc0ec1SRobert Watson } 1889b1fc0ec1SRobert Watson 18907fd6a959SRobert Watson /*- 18917fd6a959SRobert Watson * Change a process's saved uid. 1892b1fc0ec1SRobert Watson * Side effects: newcred->cr_svuid will be updated. 1893b1fc0ec1SRobert Watson * References: newcred must be an exclusive credential reference for the 1894b1fc0ec1SRobert Watson * duration of the call. 1895b1fc0ec1SRobert Watson */ 1896b1fc0ec1SRobert Watson void 18974c44ad8eSJohn Baldwin change_svuid(struct ucred *newcred, uid_t svuid) 1898b1fc0ec1SRobert Watson { 1899b1fc0ec1SRobert Watson 1900b1fc0ec1SRobert Watson newcred->cr_svuid = svuid; 1901b1fc0ec1SRobert Watson } 1902b1fc0ec1SRobert Watson 19037fd6a959SRobert Watson /*- 19047fd6a959SRobert Watson * Change a process's saved gid. 1905b1fc0ec1SRobert Watson * Side effects: newcred->cr_svgid will be updated. 1906b1fc0ec1SRobert Watson * References: newcred must be an exclusive credential reference for the 1907b1fc0ec1SRobert Watson * duration of the call. 1908b1fc0ec1SRobert Watson */ 1909b1fc0ec1SRobert Watson void 19104c44ad8eSJohn Baldwin change_svgid(struct ucred *newcred, gid_t svgid) 1911b1fc0ec1SRobert Watson { 1912b1fc0ec1SRobert Watson 1913b1fc0ec1SRobert Watson newcred->cr_svgid = svgid; 1914f535380cSDon Lewis } 1915