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" 4840244964SRobert Watson #include "opt_mac.h" 495591b823SEivind Eklund 50df8bae1dSRodney W. Grimes #include <sys/param.h> 51df8bae1dSRodney W. Grimes #include <sys/systm.h> 52fb919e4dSMark Murray #include <sys/acct.h> 531c5bb3eaSPeter Wemm #include <sys/kernel.h> 5498f03f90SJake Burkholder #include <sys/lock.h> 5540244964SRobert Watson #include <sys/mac.h> 56f9d0d524SRobert Watson #include <sys/malloc.h> 57fb919e4dSMark Murray #include <sys/mutex.h> 585b29d6e9SJohn Baldwin #include <sys/sx.h> 59f591779bSSeigo Tanimura #include <sys/proc.h> 60fb919e4dSMark Murray #include <sys/sysproto.h> 61eb725b4eSRobert Watson #include <sys/jail.h> 62d5f81602SSean Eric Fagan #include <sys/pioctl.h> 63f535380cSDon Lewis #include <sys/resourcevar.h> 6429dc1288SRobert Watson #include <sys/socket.h> 6529dc1288SRobert Watson #include <sys/socketvar.h> 66579f4eb4SRobert Watson #include <sys/sysctl.h> 67df8bae1dSRodney W. Grimes 68a1c995b6SPoul-Henning Kamp static MALLOC_DEFINE(M_CRED, "cred", "credentials"); 69a1c995b6SPoul-Henning Kamp 70d0615c64SAndrew R. Reiter SYSCTL_DECL(_security); 71d0615c64SAndrew R. Reiter SYSCTL_NODE(_security, OID_AUTO, bsd, CTLFLAG_RW, 0, 7248713bdcSRobert Watson "BSD security policy"); 7348713bdcSRobert Watson 74d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 75ad7507e2SSteven Wallace struct getpid_args { 76df8bae1dSRodney W. Grimes int dummy; 77df8bae1dSRodney W. Grimes }; 78d2d3e875SBruce Evans #endif 79835a82eeSMatthew Dillon /* 80835a82eeSMatthew Dillon * MPSAFE 81835a82eeSMatthew Dillon */ 82df8bae1dSRodney W. Grimes /* ARGSUSED */ 8326f9a767SRodney W. Grimes int 844c44ad8eSJohn Baldwin getpid(struct thread *td, struct getpid_args *uap) 85df8bae1dSRodney W. Grimes { 86b40ce416SJulian Elischer struct proc *p = td->td_proc; 87d23f5958SMatthew Dillon int s; 88df8bae1dSRodney W. Grimes 89d23f5958SMatthew Dillon s = mtx_lock_giant(kern_giant_proc); 90b40ce416SJulian Elischer td->td_retval[0] = p->p_pid; 91df8bae1dSRodney W. Grimes #if defined(COMPAT_43) || defined(COMPAT_SUNOS) 92bae3a80bSJohn Baldwin PROC_LOCK(p); 93b40ce416SJulian Elischer td->td_retval[1] = p->p_pptr->p_pid; 94bae3a80bSJohn Baldwin PROC_UNLOCK(p); 95df8bae1dSRodney W. Grimes #endif 96d23f5958SMatthew Dillon mtx_unlock_giant(s); 97df8bae1dSRodney W. Grimes return (0); 98df8bae1dSRodney W. Grimes } 99df8bae1dSRodney W. Grimes 100d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 101ad7507e2SSteven Wallace struct getppid_args { 102ad7507e2SSteven Wallace int dummy; 103ad7507e2SSteven Wallace }; 104d2d3e875SBruce Evans #endif 105835a82eeSMatthew Dillon /* 106835a82eeSMatthew Dillon * MPSAFE 107835a82eeSMatthew Dillon */ 108df8bae1dSRodney W. Grimes /* ARGSUSED */ 10926f9a767SRodney W. Grimes int 1104c44ad8eSJohn Baldwin getppid(struct thread *td, struct getppid_args *uap) 111df8bae1dSRodney W. Grimes { 112b40ce416SJulian Elischer struct proc *p = td->td_proc; 113d23f5958SMatthew Dillon int s; 114df8bae1dSRodney W. Grimes 115d23f5958SMatthew Dillon s = mtx_lock_giant(kern_giant_proc); 116bae3a80bSJohn Baldwin PROC_LOCK(p); 117b40ce416SJulian Elischer td->td_retval[0] = p->p_pptr->p_pid; 118bae3a80bSJohn Baldwin PROC_UNLOCK(p); 119d23f5958SMatthew Dillon mtx_unlock_giant(s); 120df8bae1dSRodney W. Grimes return (0); 121df8bae1dSRodney W. Grimes } 122df8bae1dSRodney W. Grimes 12336e9f877SMatthew Dillon /* 124eb725b4eSRobert Watson * Get process group ID; note that POSIX getpgrp takes no parameter. 12536e9f877SMatthew Dillon */ 126d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 127ad7507e2SSteven Wallace struct getpgrp_args { 128ad7507e2SSteven Wallace int dummy; 129ad7507e2SSteven Wallace }; 130d2d3e875SBruce Evans #endif 131835a82eeSMatthew Dillon /* 132835a82eeSMatthew Dillon * MPSAFE 133835a82eeSMatthew Dillon */ 13426f9a767SRodney W. Grimes int 1354c44ad8eSJohn Baldwin getpgrp(struct thread *td, struct getpgrp_args *uap) 136df8bae1dSRodney W. Grimes { 137b40ce416SJulian Elischer struct proc *p = td->td_proc; 138f591779bSSeigo Tanimura int s; 139df8bae1dSRodney W. Grimes 140f591779bSSeigo Tanimura s = mtx_lock_giant(kern_giant_proc); 141f591779bSSeigo Tanimura PROC_LOCK(p); 142b40ce416SJulian Elischer td->td_retval[0] = p->p_pgrp->pg_id; 143f591779bSSeigo Tanimura PROC_UNLOCK(p); 144f591779bSSeigo Tanimura mtx_unlock_giant(s); 145df8bae1dSRodney W. Grimes return (0); 146df8bae1dSRodney W. Grimes } 147df8bae1dSRodney W. Grimes 1481a5018a0SPeter Wemm /* Get an arbitary pid's process group id */ 1491a5018a0SPeter Wemm #ifndef _SYS_SYSPROTO_H_ 1501a5018a0SPeter Wemm struct getpgid_args { 1511a5018a0SPeter Wemm pid_t pid; 1521a5018a0SPeter Wemm }; 1531a5018a0SPeter Wemm #endif 154835a82eeSMatthew Dillon /* 155835a82eeSMatthew Dillon * MPSAFE 156835a82eeSMatthew Dillon */ 1571a5018a0SPeter Wemm int 1584c44ad8eSJohn Baldwin getpgid(struct thread *td, struct getpgid_args *uap) 1591a5018a0SPeter Wemm { 160b40ce416SJulian Elischer struct proc *p = td->td_proc; 16165de0c7aSDon Lewis struct proc *pt; 162f2ae7368SJohn Baldwin int error; 16365de0c7aSDon Lewis 164f2ae7368SJohn Baldwin mtx_lock(&Giant); 165eb725b4eSRobert Watson error = 0; 166f591779bSSeigo Tanimura if (uap->pid == 0) { 167f591779bSSeigo Tanimura PROC_LOCK(p); 168b40ce416SJulian Elischer td->td_retval[0] = p->p_pgrp->pg_id; 169f591779bSSeigo Tanimura PROC_UNLOCK(p); 170f591779bSSeigo Tanimura } else if ((pt = pfind(uap->pid)) == NULL) 171835a82eeSMatthew Dillon error = ESRCH; 1726a90c862SJohn Baldwin else { 173f44d9e24SJohn Baldwin error = p_cansee(td, pt); 1746a90c862SJohn Baldwin if (error == 0) 175b40ce416SJulian Elischer td->td_retval[0] = pt->p_pgrp->pg_id; 17633a9ed9dSJohn Baldwin PROC_UNLOCK(pt); 17733a9ed9dSJohn Baldwin } 178f2ae7368SJohn Baldwin mtx_unlock(&Giant); 179835a82eeSMatthew Dillon return (error); 1801a5018a0SPeter Wemm } 1811a5018a0SPeter Wemm 1821a5018a0SPeter Wemm /* 1831a5018a0SPeter Wemm * Get an arbitary pid's session id. 1841a5018a0SPeter Wemm */ 1851a5018a0SPeter Wemm #ifndef _SYS_SYSPROTO_H_ 1861a5018a0SPeter Wemm struct getsid_args { 1871a5018a0SPeter Wemm pid_t pid; 1881a5018a0SPeter Wemm }; 1891a5018a0SPeter Wemm #endif 190835a82eeSMatthew Dillon /* 191835a82eeSMatthew Dillon * MPSAFE 192835a82eeSMatthew Dillon */ 1931a5018a0SPeter Wemm int 1944c44ad8eSJohn Baldwin getsid(struct thread *td, struct getsid_args *uap) 1951a5018a0SPeter Wemm { 196b40ce416SJulian Elischer struct proc *p = td->td_proc; 19765de0c7aSDon Lewis struct proc *pt; 198eb725b4eSRobert Watson int error; 19965de0c7aSDon Lewis 200f2ae7368SJohn Baldwin mtx_lock(&Giant); 201eb725b4eSRobert Watson error = 0; 202f591779bSSeigo Tanimura if (uap->pid == 0) { 203f591779bSSeigo Tanimura PROC_LOCK(p); 204b40ce416SJulian Elischer td->td_retval[0] = p->p_session->s_sid; 205f591779bSSeigo Tanimura PROC_UNLOCK(p); 206f591779bSSeigo Tanimura } else if ((pt = pfind(uap->pid)) == NULL) 207835a82eeSMatthew Dillon error = ESRCH; 2086a90c862SJohn Baldwin else { 209f44d9e24SJohn Baldwin error = p_cansee(td, pt); 2106a90c862SJohn Baldwin if (error == 0) 211b40ce416SJulian Elischer td->td_retval[0] = pt->p_session->s_sid; 21233a9ed9dSJohn Baldwin PROC_UNLOCK(pt); 21333a9ed9dSJohn Baldwin } 214f2ae7368SJohn Baldwin mtx_unlock(&Giant); 215835a82eeSMatthew Dillon return (error); 2161a5018a0SPeter Wemm } 2171a5018a0SPeter Wemm 218d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 219ad7507e2SSteven Wallace struct getuid_args { 220ad7507e2SSteven Wallace int dummy; 221ad7507e2SSteven Wallace }; 222d2d3e875SBruce Evans #endif 223835a82eeSMatthew Dillon /* 224835a82eeSMatthew Dillon * MPSAFE 225835a82eeSMatthew Dillon */ 226df8bae1dSRodney W. Grimes /* ARGSUSED */ 22726f9a767SRodney W. Grimes int 2284c44ad8eSJohn Baldwin getuid(struct thread *td, struct getuid_args *uap) 229df8bae1dSRodney W. Grimes { 230df8bae1dSRodney W. Grimes 231d846883bSJohn Baldwin td->td_retval[0] = td->td_ucred->cr_ruid; 232df8bae1dSRodney W. Grimes #if defined(COMPAT_43) || defined(COMPAT_SUNOS) 233d846883bSJohn Baldwin td->td_retval[1] = td->td_ucred->cr_uid; 234df8bae1dSRodney W. Grimes #endif 235df8bae1dSRodney W. Grimes return (0); 236df8bae1dSRodney W. Grimes } 237df8bae1dSRodney W. Grimes 238d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 239ad7507e2SSteven Wallace struct geteuid_args { 240ad7507e2SSteven Wallace int dummy; 241ad7507e2SSteven Wallace }; 242d2d3e875SBruce Evans #endif 243eb725b4eSRobert Watson /* 244eb725b4eSRobert Watson * MPSAFE 245eb725b4eSRobert Watson */ 246df8bae1dSRodney W. Grimes /* ARGSUSED */ 24726f9a767SRodney W. Grimes int 2484c44ad8eSJohn Baldwin geteuid(struct thread *td, struct geteuid_args *uap) 249df8bae1dSRodney W. Grimes { 250d846883bSJohn Baldwin 251d846883bSJohn Baldwin td->td_retval[0] = td->td_ucred->cr_uid; 252df8bae1dSRodney W. Grimes return (0); 253df8bae1dSRodney W. Grimes } 254df8bae1dSRodney W. Grimes 255d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 256ad7507e2SSteven Wallace struct getgid_args { 257ad7507e2SSteven Wallace int dummy; 258ad7507e2SSteven Wallace }; 259d2d3e875SBruce Evans #endif 260835a82eeSMatthew Dillon /* 261835a82eeSMatthew Dillon * MPSAFE 262835a82eeSMatthew Dillon */ 263df8bae1dSRodney W. Grimes /* ARGSUSED */ 26426f9a767SRodney W. Grimes int 2654c44ad8eSJohn Baldwin getgid(struct thread *td, struct getgid_args *uap) 266df8bae1dSRodney W. Grimes { 267df8bae1dSRodney W. Grimes 268d846883bSJohn Baldwin td->td_retval[0] = td->td_ucred->cr_rgid; 269df8bae1dSRodney W. Grimes #if defined(COMPAT_43) || defined(COMPAT_SUNOS) 270d846883bSJohn Baldwin td->td_retval[1] = td->td_ucred->cr_groups[0]; 271df8bae1dSRodney W. Grimes #endif 272df8bae1dSRodney W. Grimes return (0); 273df8bae1dSRodney W. Grimes } 274df8bae1dSRodney W. Grimes 275df8bae1dSRodney W. Grimes /* 276df8bae1dSRodney W. Grimes * Get effective group ID. The "egid" is groups[0], and could be obtained 277df8bae1dSRodney W. Grimes * via getgroups. This syscall exists because it is somewhat painful to do 278df8bae1dSRodney W. Grimes * correctly in a library function. 279df8bae1dSRodney W. Grimes */ 280d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 281ad7507e2SSteven Wallace struct getegid_args { 282ad7507e2SSteven Wallace int dummy; 283ad7507e2SSteven Wallace }; 284d2d3e875SBruce Evans #endif 285835a82eeSMatthew Dillon /* 286835a82eeSMatthew Dillon * MPSAFE 287835a82eeSMatthew Dillon */ 288df8bae1dSRodney W. Grimes /* ARGSUSED */ 28926f9a767SRodney W. Grimes int 2904c44ad8eSJohn Baldwin getegid(struct thread *td, struct getegid_args *uap) 291df8bae1dSRodney W. Grimes { 292df8bae1dSRodney W. Grimes 293d846883bSJohn Baldwin td->td_retval[0] = td->td_ucred->cr_groups[0]; 294df8bae1dSRodney W. Grimes return (0); 295df8bae1dSRodney W. Grimes } 296df8bae1dSRodney W. Grimes 297d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 298df8bae1dSRodney W. Grimes struct getgroups_args { 299df8bae1dSRodney W. Grimes u_int gidsetsize; 300df8bae1dSRodney W. Grimes gid_t *gidset; 301df8bae1dSRodney W. Grimes }; 302d2d3e875SBruce Evans #endif 303835a82eeSMatthew Dillon /* 304835a82eeSMatthew Dillon * MPSAFE 305835a82eeSMatthew Dillon */ 30626f9a767SRodney W. Grimes int 3074c44ad8eSJohn Baldwin getgroups(struct thread *td, register struct getgroups_args *uap) 308df8bae1dSRodney W. Grimes { 309835a82eeSMatthew Dillon struct ucred *cred; 310b1fc0ec1SRobert Watson u_int ngrp; 311eb725b4eSRobert Watson int error; 312df8bae1dSRodney W. Grimes 313d846883bSJohn Baldwin cred = td->td_ucred; 314df8bae1dSRodney W. Grimes if ((ngrp = uap->gidsetsize) == 0) { 315b40ce416SJulian Elischer td->td_retval[0] = cred->cr_ngroups; 316d846883bSJohn Baldwin return (0); 317df8bae1dSRodney W. Grimes } 318d846883bSJohn Baldwin if (ngrp < cred->cr_ngroups) 319d846883bSJohn Baldwin return (EINVAL); 320b1fc0ec1SRobert Watson ngrp = cred->cr_ngroups; 3217f05b035SAlfred Perlstein error = copyout(cred->cr_groups, uap->gidset, ngrp * sizeof(gid_t)); 322d74ac681SMatthew Dillon if (error == 0) 323d846883bSJohn Baldwin td->td_retval[0] = ngrp; 324d74ac681SMatthew Dillon return (error); 325df8bae1dSRodney W. Grimes } 326df8bae1dSRodney W. Grimes 327d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 32882970b81SBruce Evans struct setsid_args { 329ad7507e2SSteven Wallace int dummy; 330ad7507e2SSteven Wallace }; 331d2d3e875SBruce Evans #endif 332835a82eeSMatthew Dillon /* 333835a82eeSMatthew Dillon * MPSAFE 334835a82eeSMatthew Dillon */ 335df8bae1dSRodney W. Grimes /* ARGSUSED */ 33626f9a767SRodney W. Grimes int 3374c44ad8eSJohn Baldwin setsid(register struct thread *td, struct setsid_args *uap) 338df8bae1dSRodney W. Grimes { 339f591779bSSeigo Tanimura struct pgrp *pgrp; 340835a82eeSMatthew Dillon int error; 341b40ce416SJulian Elischer struct proc *p = td->td_proc; 342f591779bSSeigo Tanimura struct pgrp *newpgrp; 343f591779bSSeigo Tanimura struct session *newsess; 344f591779bSSeigo Tanimura 345f591779bSSeigo Tanimura error = 0; 346f591779bSSeigo Tanimura pgrp = NULL; 347df8bae1dSRodney W. Grimes 348f591779bSSeigo Tanimura MALLOC(newpgrp, struct pgrp *, sizeof(struct pgrp), M_PGRP, M_WAITOK | M_ZERO); 349f591779bSSeigo Tanimura MALLOC(newsess, struct session *, sizeof(struct session), M_SESSION, M_WAITOK | M_ZERO); 350f591779bSSeigo Tanimura 351c8b1829dSJohn Baldwin sx_xlock(&proctree_lock); 352f591779bSSeigo Tanimura 353f591779bSSeigo Tanimura if (p->p_pgid == p->p_pid || (pgrp = pgfind(p->p_pid)) != NULL) { 354f591779bSSeigo Tanimura if (pgrp != NULL) 355f591779bSSeigo Tanimura PGRP_UNLOCK(pgrp); 356835a82eeSMatthew Dillon error = EPERM; 357f591779bSSeigo Tanimura } else { 358f591779bSSeigo Tanimura (void)enterpgrp(p, p->p_pid, newpgrp, newsess); 359b40ce416SJulian Elischer td->td_retval[0] = p->p_pid; 360c8b1829dSJohn Baldwin newpgrp = NULL; 361c8b1829dSJohn Baldwin newsess = NULL; 362df8bae1dSRodney W. Grimes } 363f591779bSSeigo Tanimura 364c8b1829dSJohn Baldwin sx_xunlock(&proctree_lock); 365f591779bSSeigo Tanimura 366c8b1829dSJohn Baldwin if (newpgrp != NULL) 367f591779bSSeigo Tanimura FREE(newpgrp, M_PGRP); 368c8b1829dSJohn Baldwin if (newsess != NULL) 369f591779bSSeigo Tanimura FREE(newsess, M_SESSION); 3701c2451c2SSeigo Tanimura 371c8b1829dSJohn Baldwin return (error); 372df8bae1dSRodney W. Grimes } 373df8bae1dSRodney W. Grimes 374df8bae1dSRodney W. Grimes /* 375df8bae1dSRodney W. Grimes * set process group (setpgid/old setpgrp) 376df8bae1dSRodney W. Grimes * 377df8bae1dSRodney W. Grimes * caller does setpgid(targpid, targpgid) 378df8bae1dSRodney W. Grimes * 379df8bae1dSRodney W. Grimes * pid must be caller or child of caller (ESRCH) 380df8bae1dSRodney W. Grimes * if a child 381df8bae1dSRodney W. Grimes * pid must be in same session (EPERM) 382df8bae1dSRodney W. Grimes * pid can't have done an exec (EACCES) 383df8bae1dSRodney W. Grimes * if pgid != pid 384df8bae1dSRodney W. Grimes * there must exist some pid in same session having pgid (EPERM) 385df8bae1dSRodney W. Grimes * pid must not be session leader (EPERM) 386df8bae1dSRodney W. Grimes */ 387d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 388df8bae1dSRodney W. Grimes struct setpgid_args { 389df8bae1dSRodney W. Grimes int pid; /* target process id */ 390df8bae1dSRodney W. Grimes int pgid; /* target pgrp id */ 391df8bae1dSRodney W. Grimes }; 392d2d3e875SBruce Evans #endif 393835a82eeSMatthew Dillon /* 394835a82eeSMatthew Dillon * MPSAFE 395835a82eeSMatthew Dillon */ 396df8bae1dSRodney W. Grimes /* ARGSUSED */ 39726f9a767SRodney W. Grimes int 3984c44ad8eSJohn Baldwin setpgid(struct thread *td, register struct setpgid_args *uap) 399df8bae1dSRodney W. Grimes { 400b40ce416SJulian Elischer struct proc *curp = td->td_proc; 401df8bae1dSRodney W. Grimes register struct proc *targp; /* target process */ 402df8bae1dSRodney W. Grimes register struct pgrp *pgrp; /* target pgrp */ 403eb9e5c1dSRobert Watson int error; 404f591779bSSeigo Tanimura struct pgrp *newpgrp; 405df8bae1dSRodney W. Grimes 40678f64bccSBruce Evans if (uap->pgid < 0) 40778f64bccSBruce Evans return (EINVAL); 408f591779bSSeigo Tanimura 409f591779bSSeigo Tanimura error = 0; 410f591779bSSeigo Tanimura 411f591779bSSeigo Tanimura MALLOC(newpgrp, struct pgrp *, sizeof(struct pgrp), M_PGRP, M_WAITOK | M_ZERO); 412f591779bSSeigo Tanimura 413c8b1829dSJohn Baldwin sx_xlock(&proctree_lock); 414df8bae1dSRodney W. Grimes if (uap->pid != 0 && uap->pid != curp->p_pid) { 415f591779bSSeigo Tanimura if ((targp = pfind(uap->pid)) == NULL) { 41633a9ed9dSJohn Baldwin if (targp) 41733a9ed9dSJohn Baldwin PROC_UNLOCK(targp); 418835a82eeSMatthew Dillon error = ESRCH; 419c8b1829dSJohn Baldwin goto done; 42033a9ed9dSJohn Baldwin } 421f591779bSSeigo Tanimura if (!inferior(targp)) { 422f591779bSSeigo Tanimura PROC_UNLOCK(targp); 4232f932587SSeigo Tanimura error = ESRCH; 424c8b1829dSJohn Baldwin goto done; 425f591779bSSeigo Tanimura } 426f44d9e24SJohn Baldwin if ((error = p_cansee(curthread, targp))) { 42733a9ed9dSJohn Baldwin PROC_UNLOCK(targp); 428c8b1829dSJohn Baldwin goto done; 42933a9ed9dSJohn Baldwin } 43033a9ed9dSJohn Baldwin if (targp->p_pgrp == NULL || 43133a9ed9dSJohn Baldwin targp->p_session != curp->p_session) { 43233a9ed9dSJohn Baldwin PROC_UNLOCK(targp); 433835a82eeSMatthew Dillon error = EPERM; 434c8b1829dSJohn Baldwin goto done; 43533a9ed9dSJohn Baldwin } 43633a9ed9dSJohn Baldwin if (targp->p_flag & P_EXEC) { 43733a9ed9dSJohn Baldwin PROC_UNLOCK(targp); 438835a82eeSMatthew Dillon error = EACCES; 439c8b1829dSJohn Baldwin goto done; 44033a9ed9dSJohn Baldwin } 44133a9ed9dSJohn Baldwin PROC_UNLOCK(targp); 442f591779bSSeigo Tanimura } else 443f591779bSSeigo Tanimura targp = curp; 444f591779bSSeigo Tanimura if (SESS_LEADER(targp)) { 445835a82eeSMatthew Dillon error = EPERM; 446c8b1829dSJohn Baldwin goto done; 44733a9ed9dSJohn Baldwin } 448eb725b4eSRobert Watson if (uap->pgid == 0) 449df8bae1dSRodney W. Grimes uap->pgid = targp->p_pid; 450f591779bSSeigo Tanimura if (uap->pgid == targp->p_pid) { 451f591779bSSeigo Tanimura if (targp->p_pgid == uap->pgid) 452f591779bSSeigo Tanimura goto done; 453f591779bSSeigo Tanimura error = enterpgrp(targp, uap->pgid, newpgrp, NULL); 454f591779bSSeigo Tanimura if (error == 0) 455f591779bSSeigo Tanimura newpgrp = NULL; 456f591779bSSeigo Tanimura } else { 457f591779bSSeigo Tanimura if ((pgrp = pgfind(uap->pgid)) == NULL || 45833a9ed9dSJohn Baldwin pgrp->pg_session != curp->p_session) { 459f591779bSSeigo Tanimura if (pgrp != NULL) 460f591779bSSeigo Tanimura PGRP_UNLOCK(pgrp); 461835a82eeSMatthew Dillon error = EPERM; 462c8b1829dSJohn Baldwin goto done; 463835a82eeSMatthew Dillon } 464f591779bSSeigo Tanimura if (pgrp == targp->p_pgrp) { 465f591779bSSeigo Tanimura PGRP_UNLOCK(pgrp); 466f591779bSSeigo Tanimura goto done; 46733a9ed9dSJohn Baldwin } 468f591779bSSeigo Tanimura PGRP_UNLOCK(pgrp); 469f591779bSSeigo Tanimura error = enterthispgrp(targp, pgrp); 470f591779bSSeigo Tanimura } 471f591779bSSeigo Tanimura done: 472c8b1829dSJohn Baldwin sx_xunlock(&proctree_lock); 473c8b1829dSJohn Baldwin KASSERT((error == 0) || (newpgrp != NULL), 474c8b1829dSJohn Baldwin ("setpgid failed and newpgrp is NULL")); 4756041fa0aSSeigo Tanimura if (newpgrp != NULL) 476f591779bSSeigo Tanimura FREE(newpgrp, M_PGRP); 477835a82eeSMatthew Dillon return (error); 478df8bae1dSRodney W. Grimes } 479df8bae1dSRodney W. Grimes 480a08f4bf6SPeter Wemm /* 481a08f4bf6SPeter Wemm * Use the clause in B.4.2.2 that allows setuid/setgid to be 4.2/4.3BSD 4822fa72ea7SJeroen Ruigrok van der Werven * compatible. It says that setting the uid/gid to euid/egid is a special 483a08f4bf6SPeter Wemm * case of "appropriate privilege". Once the rules are expanded out, this 484a08f4bf6SPeter Wemm * basically means that setuid(nnn) sets all three id's, in all permitted 485a08f4bf6SPeter Wemm * cases unless _POSIX_SAVED_IDS is enabled. In that case, setuid(getuid()) 486a08f4bf6SPeter Wemm * does not set the saved id - this is dangerous for traditional BSD 487a08f4bf6SPeter Wemm * programs. For this reason, we *really* do not want to set 488a08f4bf6SPeter Wemm * _POSIX_SAVED_IDS and do not want to clear POSIX_APPENDIX_B_4_2_2. 489a08f4bf6SPeter Wemm */ 490a08f4bf6SPeter Wemm #define POSIX_APPENDIX_B_4_2_2 491a08f4bf6SPeter Wemm 492d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 493df8bae1dSRodney W. Grimes struct setuid_args { 494df8bae1dSRodney W. Grimes uid_t uid; 495df8bae1dSRodney W. Grimes }; 496d2d3e875SBruce Evans #endif 497835a82eeSMatthew Dillon /* 498835a82eeSMatthew Dillon * MPSAFE 499835a82eeSMatthew Dillon */ 500df8bae1dSRodney W. Grimes /* ARGSUSED */ 50126f9a767SRodney W. Grimes int 5024c44ad8eSJohn Baldwin setuid(struct thread *td, struct setuid_args *uap) 503df8bae1dSRodney W. Grimes { 504b40ce416SJulian Elischer struct proc *p = td->td_proc; 505b1fc0ec1SRobert Watson struct ucred *newcred, *oldcred; 506b1fc0ec1SRobert Watson uid_t uid; 5071419eacbSAlfred Perlstein struct uidinfo *uip; 508eb725b4eSRobert Watson int error; 509df8bae1dSRodney W. Grimes 510835a82eeSMatthew Dillon mtx_lock(&Giant); 51107f3485dSJohn Baldwin uid = uap->uid; 51207f3485dSJohn Baldwin newcred = crget(); 5131419eacbSAlfred Perlstein uip = uifind(uid); 51407f3485dSJohn Baldwin PROC_LOCK(p); 515f605567cSRobert Watson oldcred = p->p_ucred; 5165a92ee3cSRobert Watson 517a08f4bf6SPeter Wemm /* 518a08f4bf6SPeter Wemm * See if we have "permission" by POSIX 1003.1 rules. 519a08f4bf6SPeter Wemm * 520a08f4bf6SPeter Wemm * Note that setuid(geteuid()) is a special case of 521a08f4bf6SPeter Wemm * "appropriate privileges" in appendix B.4.2.2. We need 5222fa72ea7SJeroen Ruigrok van der Werven * to use this clause to be compatible with traditional BSD 523a08f4bf6SPeter Wemm * semantics. Basically, it means that "setuid(xx)" sets all 524a08f4bf6SPeter Wemm * three id's (assuming you have privs). 525a08f4bf6SPeter Wemm * 526a08f4bf6SPeter Wemm * Notes on the logic. We do things in three steps. 527a08f4bf6SPeter Wemm * 1: We determine if the euid is going to change, and do EPERM 528a08f4bf6SPeter Wemm * right away. We unconditionally change the euid later if this 529a08f4bf6SPeter Wemm * test is satisfied, simplifying that part of the logic. 530eb725b4eSRobert Watson * 2: We determine if the real and/or saved uids are going to 531a08f4bf6SPeter Wemm * change. Determined by compile options. 532a08f4bf6SPeter Wemm * 3: Change euid last. (after tests in #2 for "appropriate privs") 533a08f4bf6SPeter Wemm */ 534b1fc0ec1SRobert Watson if (uid != oldcred->cr_ruid && /* allow setuid(getuid()) */ 5353f246666SAndrey A. Chernov #ifdef _POSIX_SAVED_IDS 536b1fc0ec1SRobert Watson uid != oldcred->cr_svuid && /* allow setuid(saved gid) */ 537a08f4bf6SPeter Wemm #endif 538a08f4bf6SPeter Wemm #ifdef POSIX_APPENDIX_B_4_2_2 /* Use BSD-compat clause from B.4.2.2 */ 539b1fc0ec1SRobert Watson uid != oldcred->cr_uid && /* allow setuid(geteuid()) */ 5403f246666SAndrey A. Chernov #endif 54107f3485dSJohn Baldwin (error = suser_cred(oldcred, PRISON_ROOT)) != 0) { 54207f3485dSJohn Baldwin PROC_UNLOCK(p); 5431419eacbSAlfred Perlstein uifree(uip); 54407f3485dSJohn Baldwin crfree(newcred); 54507f3485dSJohn Baldwin mtx_unlock(&Giant); 54607f3485dSJohn Baldwin return (error); 54707f3485dSJohn Baldwin } 548a08f4bf6SPeter Wemm 5491419eacbSAlfred Perlstein /* 5501419eacbSAlfred Perlstein * Copy credentials so other references do not see our changes. 5511419eacbSAlfred Perlstein */ 55207f3485dSJohn Baldwin crcopy(newcred, oldcred); 553a08f4bf6SPeter Wemm #ifdef _POSIX_SAVED_IDS 554df8bae1dSRodney W. Grimes /* 555a08f4bf6SPeter Wemm * Do we have "appropriate privileges" (are we root or uid == euid) 556a08f4bf6SPeter Wemm * If so, we are changing the real uid and/or saved uid. 557df8bae1dSRodney W. Grimes */ 5583f246666SAndrey A. Chernov if ( 559a08f4bf6SPeter Wemm #ifdef POSIX_APPENDIX_B_4_2_2 /* Use the clause from B.4.2.2 */ 560b1fc0ec1SRobert Watson uid == oldcred->cr_uid || 5613f246666SAndrey A. Chernov #endif 56244731cabSJohn Baldwin suser_cred(oldcred, PRISON_ROOT) == 0) /* we are using privs */ 563a08f4bf6SPeter Wemm #endif 564a08f4bf6SPeter Wemm { 565a08f4bf6SPeter Wemm /* 566f535380cSDon Lewis * Set the real uid and transfer proc count to new user. 567a08f4bf6SPeter Wemm */ 568b1fc0ec1SRobert Watson if (uid != oldcred->cr_ruid) { 5691419eacbSAlfred Perlstein change_ruid(newcred, uip); 570f535380cSDon Lewis setsugid(p); 571d3cdb93dSAndrey A. Chernov } 572a08f4bf6SPeter Wemm /* 573a08f4bf6SPeter Wemm * Set saved uid 574a08f4bf6SPeter Wemm * 575a08f4bf6SPeter Wemm * XXX always set saved uid even if not _POSIX_SAVED_IDS, as 576a08f4bf6SPeter Wemm * the security of seteuid() depends on it. B.4.2.2 says it 577a08f4bf6SPeter Wemm * is important that we should do this. 578a08f4bf6SPeter Wemm */ 579b1fc0ec1SRobert Watson if (uid != oldcred->cr_svuid) { 580b1fc0ec1SRobert Watson change_svuid(newcred, uid); 581d5f81602SSean Eric Fagan setsugid(p); 582a08f4bf6SPeter Wemm } 583a08f4bf6SPeter Wemm } 584a08f4bf6SPeter Wemm 585a08f4bf6SPeter Wemm /* 586a08f4bf6SPeter Wemm * In all permitted cases, we are changing the euid. 587a08f4bf6SPeter Wemm */ 588b1fc0ec1SRobert Watson if (uid != oldcred->cr_uid) { 5891419eacbSAlfred Perlstein change_euid(newcred, uip); 590d5f81602SSean Eric Fagan setsugid(p); 591a08f4bf6SPeter Wemm } 592b1fc0ec1SRobert Watson p->p_ucred = newcred; 59307f3485dSJohn Baldwin PROC_UNLOCK(p); 5941419eacbSAlfred Perlstein uifree(uip); 595b1fc0ec1SRobert Watson crfree(oldcred); 596835a82eeSMatthew Dillon mtx_unlock(&Giant); 59707f3485dSJohn Baldwin return (0); 598df8bae1dSRodney W. Grimes } 599df8bae1dSRodney W. Grimes 600d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 601df8bae1dSRodney W. Grimes struct seteuid_args { 602df8bae1dSRodney W. Grimes uid_t euid; 603df8bae1dSRodney W. Grimes }; 604d2d3e875SBruce Evans #endif 605835a82eeSMatthew Dillon /* 606835a82eeSMatthew Dillon * MPSAFE 607835a82eeSMatthew Dillon */ 608df8bae1dSRodney W. Grimes /* ARGSUSED */ 60926f9a767SRodney W. Grimes int 6104c44ad8eSJohn Baldwin seteuid(struct thread *td, struct seteuid_args *uap) 611df8bae1dSRodney W. Grimes { 612b40ce416SJulian Elischer struct proc *p = td->td_proc; 613b1fc0ec1SRobert Watson struct ucred *newcred, *oldcred; 614b1fc0ec1SRobert Watson uid_t euid; 6151419eacbSAlfred Perlstein struct uidinfo *euip; 616eb725b4eSRobert Watson int error; 617df8bae1dSRodney W. Grimes 618df8bae1dSRodney W. Grimes euid = uap->euid; 619835a82eeSMatthew Dillon mtx_lock(&Giant); 62007f3485dSJohn Baldwin newcred = crget(); 6211419eacbSAlfred Perlstein euip = uifind(euid); 62207f3485dSJohn Baldwin PROC_LOCK(p); 623b1fc0ec1SRobert Watson oldcred = p->p_ucred; 624b1fc0ec1SRobert Watson if (euid != oldcred->cr_ruid && /* allow seteuid(getuid()) */ 625b1fc0ec1SRobert Watson euid != oldcred->cr_svuid && /* allow seteuid(saved uid) */ 62607f3485dSJohn Baldwin (error = suser_cred(oldcred, PRISON_ROOT)) != 0) { 62707f3485dSJohn Baldwin PROC_UNLOCK(p); 6281419eacbSAlfred Perlstein uifree(euip); 62907f3485dSJohn Baldwin crfree(newcred); 63007f3485dSJohn Baldwin mtx_unlock(&Giant); 63107f3485dSJohn Baldwin return (error); 63207f3485dSJohn Baldwin } 633df8bae1dSRodney W. Grimes /* 634df8bae1dSRodney W. Grimes * Everything's okay, do it. Copy credentials so other references do 635df8bae1dSRodney W. Grimes * not see our changes. 636df8bae1dSRodney W. Grimes */ 63707f3485dSJohn Baldwin crcopy(newcred, oldcred); 638b1fc0ec1SRobert Watson if (oldcred->cr_uid != euid) { 6391419eacbSAlfred Perlstein change_euid(newcred, euip); 640d5f81602SSean Eric Fagan setsugid(p); 641229a15f0SPeter Wemm } 642b1fc0ec1SRobert Watson p->p_ucred = newcred; 64307f3485dSJohn Baldwin PROC_UNLOCK(p); 6441419eacbSAlfred Perlstein uifree(euip); 645b1fc0ec1SRobert Watson crfree(oldcred); 646835a82eeSMatthew Dillon mtx_unlock(&Giant); 64707f3485dSJohn Baldwin return (0); 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); 66907f3485dSJohn Baldwin newcred = crget(); 67007f3485dSJohn Baldwin PROC_LOCK(p); 671b1fc0ec1SRobert Watson oldcred = p->p_ucred; 6725a92ee3cSRobert Watson 673a08f4bf6SPeter Wemm /* 674a08f4bf6SPeter Wemm * See if we have "permission" by POSIX 1003.1 rules. 675a08f4bf6SPeter Wemm * 676a08f4bf6SPeter Wemm * Note that setgid(getegid()) is a special case of 677a08f4bf6SPeter Wemm * "appropriate privileges" in appendix B.4.2.2. We need 6782fa72ea7SJeroen Ruigrok van der Werven * to use this clause to be compatible with traditional BSD 679a08f4bf6SPeter Wemm * semantics. Basically, it means that "setgid(xx)" sets all 680a08f4bf6SPeter Wemm * three id's (assuming you have privs). 681a08f4bf6SPeter Wemm * 682a08f4bf6SPeter Wemm * For notes on the logic here, see setuid() above. 683a08f4bf6SPeter Wemm */ 684b1fc0ec1SRobert Watson if (gid != oldcred->cr_rgid && /* allow setgid(getgid()) */ 6853f246666SAndrey A. Chernov #ifdef _POSIX_SAVED_IDS 686b1fc0ec1SRobert Watson gid != oldcred->cr_svgid && /* allow setgid(saved gid) */ 687a08f4bf6SPeter Wemm #endif 688a08f4bf6SPeter Wemm #ifdef POSIX_APPENDIX_B_4_2_2 /* Use BSD-compat clause from B.4.2.2 */ 689b1fc0ec1SRobert Watson gid != oldcred->cr_groups[0] && /* allow setgid(getegid()) */ 6903f246666SAndrey A. Chernov #endif 69107f3485dSJohn Baldwin (error = suser_cred(oldcred, PRISON_ROOT)) != 0) { 69207f3485dSJohn Baldwin PROC_UNLOCK(p); 69307f3485dSJohn Baldwin crfree(newcred); 69407f3485dSJohn Baldwin mtx_unlock(&Giant); 69507f3485dSJohn Baldwin return (error); 69607f3485dSJohn Baldwin } 697a08f4bf6SPeter Wemm 69807f3485dSJohn Baldwin crcopy(newcred, oldcred); 699a08f4bf6SPeter Wemm #ifdef _POSIX_SAVED_IDS 700a08f4bf6SPeter Wemm /* 701a08f4bf6SPeter Wemm * Do we have "appropriate privileges" (are we root or gid == egid) 702a08f4bf6SPeter Wemm * If so, we are changing the real uid and saved gid. 703a08f4bf6SPeter Wemm */ 704a08f4bf6SPeter Wemm if ( 705a08f4bf6SPeter Wemm #ifdef POSIX_APPENDIX_B_4_2_2 /* use the clause from B.4.2.2 */ 706b1fc0ec1SRobert Watson gid == oldcred->cr_groups[0] || 707a08f4bf6SPeter Wemm #endif 70844731cabSJohn Baldwin suser_cred(oldcred, PRISON_ROOT) == 0) /* we are using privs */ 709a08f4bf6SPeter Wemm #endif 710a08f4bf6SPeter Wemm { 711a08f4bf6SPeter Wemm /* 712a08f4bf6SPeter Wemm * Set real gid 713a08f4bf6SPeter Wemm */ 714b1fc0ec1SRobert Watson if (oldcred->cr_rgid != gid) { 715b1fc0ec1SRobert Watson change_rgid(newcred, gid); 716d5f81602SSean Eric Fagan setsugid(p); 717a08f4bf6SPeter Wemm } 718a08f4bf6SPeter Wemm /* 719a08f4bf6SPeter Wemm * Set saved gid 720a08f4bf6SPeter Wemm * 721a08f4bf6SPeter Wemm * XXX always set saved gid even if not _POSIX_SAVED_IDS, as 722a08f4bf6SPeter Wemm * the security of setegid() depends on it. B.4.2.2 says it 723a08f4bf6SPeter Wemm * is important that we should do this. 724a08f4bf6SPeter Wemm */ 725b1fc0ec1SRobert Watson if (oldcred->cr_svgid != gid) { 726b1fc0ec1SRobert Watson change_svgid(newcred, gid); 727d5f81602SSean Eric Fagan setsugid(p); 728a08f4bf6SPeter Wemm } 729a08f4bf6SPeter Wemm } 730a08f4bf6SPeter Wemm /* 731a08f4bf6SPeter Wemm * In all cases permitted cases, we are changing the egid. 732a08f4bf6SPeter Wemm * Copy credentials so other references do not see our changes. 733a08f4bf6SPeter Wemm */ 734b1fc0ec1SRobert Watson if (oldcred->cr_groups[0] != gid) { 735b1fc0ec1SRobert Watson change_egid(newcred, gid); 736d5f81602SSean Eric Fagan setsugid(p); 737a08f4bf6SPeter Wemm } 738b1fc0ec1SRobert Watson p->p_ucred = newcred; 73907f3485dSJohn Baldwin PROC_UNLOCK(p); 740b1fc0ec1SRobert Watson crfree(oldcred); 741835a82eeSMatthew Dillon mtx_unlock(&Giant); 74207f3485dSJohn Baldwin return (0); 743df8bae1dSRodney W. Grimes } 744df8bae1dSRodney W. Grimes 745d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 746df8bae1dSRodney W. Grimes struct setegid_args { 747df8bae1dSRodney W. Grimes gid_t egid; 748df8bae1dSRodney W. Grimes }; 749d2d3e875SBruce Evans #endif 750835a82eeSMatthew Dillon /* 751835a82eeSMatthew Dillon * MPSAFE 752835a82eeSMatthew Dillon */ 753df8bae1dSRodney W. Grimes /* ARGSUSED */ 75426f9a767SRodney W. Grimes int 7554c44ad8eSJohn Baldwin setegid(struct thread *td, struct setegid_args *uap) 756df8bae1dSRodney W. Grimes { 757b40ce416SJulian Elischer struct proc *p = td->td_proc; 758b1fc0ec1SRobert Watson struct ucred *newcred, *oldcred; 759b1fc0ec1SRobert Watson gid_t egid; 760eb725b4eSRobert Watson int error; 761df8bae1dSRodney W. Grimes 762df8bae1dSRodney W. Grimes egid = uap->egid; 763835a82eeSMatthew Dillon mtx_lock(&Giant); 76407f3485dSJohn Baldwin newcred = crget(); 76507f3485dSJohn Baldwin PROC_LOCK(p); 766b1fc0ec1SRobert Watson oldcred = p->p_ucred; 767b1fc0ec1SRobert Watson if (egid != oldcred->cr_rgid && /* allow setegid(getgid()) */ 768b1fc0ec1SRobert Watson egid != oldcred->cr_svgid && /* allow setegid(saved gid) */ 76907f3485dSJohn Baldwin (error = suser_cred(oldcred, PRISON_ROOT)) != 0) { 77007f3485dSJohn Baldwin PROC_UNLOCK(p); 77107f3485dSJohn Baldwin crfree(newcred); 77207f3485dSJohn Baldwin mtx_unlock(&Giant); 77307f3485dSJohn Baldwin return (error); 77407f3485dSJohn Baldwin } 77507f3485dSJohn Baldwin crcopy(newcred, oldcred); 776b1fc0ec1SRobert Watson if (oldcred->cr_groups[0] != egid) { 777b1fc0ec1SRobert Watson change_egid(newcred, egid); 778d5f81602SSean Eric Fagan setsugid(p); 779229a15f0SPeter Wemm } 780b1fc0ec1SRobert Watson p->p_ucred = newcred; 78107f3485dSJohn Baldwin PROC_UNLOCK(p); 782b1fc0ec1SRobert Watson crfree(oldcred); 783835a82eeSMatthew Dillon mtx_unlock(&Giant); 78407f3485dSJohn Baldwin return (0); 785df8bae1dSRodney W. Grimes } 786df8bae1dSRodney W. Grimes 787d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 788df8bae1dSRodney W. Grimes struct setgroups_args { 789df8bae1dSRodney W. Grimes u_int gidsetsize; 790df8bae1dSRodney W. Grimes gid_t *gidset; 791df8bae1dSRodney W. Grimes }; 792d2d3e875SBruce Evans #endif 793835a82eeSMatthew Dillon /* 794835a82eeSMatthew Dillon * MPSAFE 795835a82eeSMatthew Dillon */ 796df8bae1dSRodney W. Grimes /* ARGSUSED */ 79726f9a767SRodney W. Grimes int 7984c44ad8eSJohn Baldwin setgroups(struct thread *td, struct setgroups_args *uap) 799df8bae1dSRodney W. Grimes { 800b40ce416SJulian Elischer struct proc *p = td->td_proc; 80107f3485dSJohn Baldwin struct ucred *newcred, *tempcred, *oldcred; 802b1fc0ec1SRobert Watson u_int ngrp; 803df8bae1dSRodney W. Grimes int error; 804df8bae1dSRodney W. Grimes 8053956a170SDavid Greenman ngrp = uap->gidsetsize; 80607f3485dSJohn Baldwin if (ngrp > NGROUPS) 80707f3485dSJohn Baldwin return (EINVAL); 8084f5a4612SRobert Watson mtx_lock(&Giant); 80907f3485dSJohn Baldwin tempcred = crget(); 8107f05b035SAlfred Perlstein error = copyin(uap->gidset, tempcred->cr_groups, ngrp * sizeof(gid_t)); 81107f3485dSJohn Baldwin if (error != 0) { 81207f3485dSJohn Baldwin crfree(tempcred); 81307f3485dSJohn Baldwin mtx_unlock(&Giant); 81407f3485dSJohn Baldwin return (error); 815835a82eeSMatthew Dillon } 81607f3485dSJohn Baldwin newcred = crget(); 81707f3485dSJohn Baldwin PROC_LOCK(p); 81807f3485dSJohn Baldwin oldcred = p->p_ucred; 81907f3485dSJohn Baldwin error = suser_cred(oldcred, PRISON_ROOT); 82007f3485dSJohn Baldwin if (error) { 82107f3485dSJohn Baldwin PROC_UNLOCK(p); 82207f3485dSJohn Baldwin crfree(newcred); 82307f3485dSJohn Baldwin crfree(tempcred); 82407f3485dSJohn Baldwin mtx_unlock(&Giant); 82507f3485dSJohn Baldwin return (error); 82607f3485dSJohn Baldwin } 82707f3485dSJohn Baldwin 8288a5d815aSPeter Wemm /* 8298a5d815aSPeter Wemm * XXX A little bit lazy here. We could test if anything has 8308a5d815aSPeter Wemm * changed before crcopy() and setting P_SUGID. 8318a5d815aSPeter Wemm */ 83207f3485dSJohn Baldwin crcopy(newcred, oldcred); 8338a5d815aSPeter Wemm if (ngrp < 1) { 8348a5d815aSPeter Wemm /* 8358a5d815aSPeter Wemm * setgroups(0, NULL) is a legitimate way of clearing the 8368a5d815aSPeter Wemm * groups vector on non-BSD systems (which generally do not 8378a5d815aSPeter Wemm * have the egid in the groups[0]). We risk security holes 8388a5d815aSPeter Wemm * when running non-BSD software if we do not do the same. 8398a5d815aSPeter Wemm */ 840b1fc0ec1SRobert Watson newcred->cr_ngroups = 1; 8418a5d815aSPeter Wemm } else { 84207f3485dSJohn Baldwin bcopy(tempcred->cr_groups, newcred->cr_groups, 84307f3485dSJohn Baldwin ngrp * sizeof(gid_t)); 844b1fc0ec1SRobert Watson newcred->cr_ngroups = ngrp; 8458a5d815aSPeter Wemm } 846d5f81602SSean Eric Fagan setsugid(p); 847b1fc0ec1SRobert Watson p->p_ucred = newcred; 84807f3485dSJohn Baldwin PROC_UNLOCK(p); 84907f3485dSJohn Baldwin crfree(tempcred); 850b1fc0ec1SRobert Watson crfree(oldcred); 851835a82eeSMatthew Dillon mtx_unlock(&Giant); 85207f3485dSJohn Baldwin return (0); 853df8bae1dSRodney W. Grimes } 854df8bae1dSRodney W. Grimes 855d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 856df8bae1dSRodney W. Grimes struct setreuid_args { 85700999cd6SAndrey A. Chernov uid_t ruid; 85800999cd6SAndrey A. Chernov uid_t euid; 859df8bae1dSRodney W. Grimes }; 860d2d3e875SBruce Evans #endif 861835a82eeSMatthew Dillon /* 862835a82eeSMatthew Dillon * MPSAFE 863835a82eeSMatthew Dillon */ 864df8bae1dSRodney W. Grimes /* ARGSUSED */ 86526f9a767SRodney W. Grimes int 8664c44ad8eSJohn Baldwin setreuid(register struct thread *td, struct setreuid_args *uap) 867df8bae1dSRodney W. Grimes { 868b40ce416SJulian Elischer struct proc *p = td->td_proc; 869b1fc0ec1SRobert Watson struct ucred *newcred, *oldcred; 870eb725b4eSRobert Watson uid_t euid, ruid; 8711419eacbSAlfred Perlstein struct uidinfo *euip, *ruip; 872eb725b4eSRobert Watson int error; 873df8bae1dSRodney W. Grimes 87400999cd6SAndrey A. Chernov euid = uap->euid; 875eb725b4eSRobert Watson ruid = uap->ruid; 876835a82eeSMatthew Dillon mtx_lock(&Giant); 87707f3485dSJohn Baldwin newcred = crget(); 8781419eacbSAlfred Perlstein euip = uifind(euid); 8791419eacbSAlfred Perlstein ruip = uifind(ruid); 88007f3485dSJohn Baldwin PROC_LOCK(p); 881b1fc0ec1SRobert Watson oldcred = p->p_ucred; 882b1fc0ec1SRobert Watson if (((ruid != (uid_t)-1 && ruid != oldcred->cr_ruid && 883b1fc0ec1SRobert Watson ruid != oldcred->cr_svuid) || 884b1fc0ec1SRobert Watson (euid != (uid_t)-1 && euid != oldcred->cr_uid && 885b1fc0ec1SRobert Watson euid != oldcred->cr_ruid && euid != oldcred->cr_svuid)) && 88607f3485dSJohn Baldwin (error = suser_cred(oldcred, PRISON_ROOT)) != 0) { 88707f3485dSJohn Baldwin PROC_UNLOCK(p); 8881419eacbSAlfred Perlstein uifree(ruip); 8891419eacbSAlfred Perlstein uifree(euip); 89007f3485dSJohn Baldwin crfree(newcred); 89107f3485dSJohn Baldwin mtx_unlock(&Giant); 89207f3485dSJohn Baldwin return (error); 89307f3485dSJohn Baldwin } 89407f3485dSJohn Baldwin crcopy(newcred, oldcred); 895b1fc0ec1SRobert Watson if (euid != (uid_t)-1 && oldcred->cr_uid != euid) { 8961419eacbSAlfred Perlstein change_euid(newcred, euip); 897d5f81602SSean Eric Fagan setsugid(p); 898a89a5370SPeter Wemm } 899b1fc0ec1SRobert Watson if (ruid != (uid_t)-1 && oldcred->cr_ruid != ruid) { 9001419eacbSAlfred Perlstein change_ruid(newcred, ruip); 901d5f81602SSean Eric Fagan setsugid(p); 90200999cd6SAndrey A. Chernov } 903b1fc0ec1SRobert Watson if ((ruid != (uid_t)-1 || newcred->cr_uid != newcred->cr_ruid) && 904b1fc0ec1SRobert Watson newcred->cr_svuid != newcred->cr_uid) { 905b1fc0ec1SRobert Watson change_svuid(newcred, newcred->cr_uid); 906d5f81602SSean Eric Fagan setsugid(p); 907a89a5370SPeter Wemm } 908b1fc0ec1SRobert Watson p->p_ucred = newcred; 90907f3485dSJohn Baldwin PROC_UNLOCK(p); 9101419eacbSAlfred Perlstein uifree(ruip); 9111419eacbSAlfred Perlstein uifree(euip); 912b1fc0ec1SRobert Watson crfree(oldcred); 913835a82eeSMatthew Dillon mtx_unlock(&Giant); 91407f3485dSJohn Baldwin return (0); 915df8bae1dSRodney W. Grimes } 916df8bae1dSRodney W. Grimes 917d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 918df8bae1dSRodney W. Grimes struct setregid_args { 91900999cd6SAndrey A. Chernov gid_t rgid; 92000999cd6SAndrey A. Chernov gid_t egid; 921df8bae1dSRodney W. Grimes }; 922d2d3e875SBruce Evans #endif 923835a82eeSMatthew Dillon /* 924835a82eeSMatthew Dillon * MPSAFE 925835a82eeSMatthew Dillon */ 926df8bae1dSRodney W. Grimes /* ARGSUSED */ 92726f9a767SRodney W. Grimes int 9284c44ad8eSJohn Baldwin setregid(register struct thread *td, struct setregid_args *uap) 929df8bae1dSRodney W. Grimes { 930b40ce416SJulian Elischer struct proc *p = td->td_proc; 931b1fc0ec1SRobert Watson struct ucred *newcred, *oldcred; 932eb725b4eSRobert Watson gid_t egid, rgid; 933eb725b4eSRobert Watson int error; 934df8bae1dSRodney W. Grimes 93500999cd6SAndrey A. Chernov egid = uap->egid; 936eb725b4eSRobert Watson rgid = uap->rgid; 937835a82eeSMatthew Dillon mtx_lock(&Giant); 93807f3485dSJohn Baldwin newcred = crget(); 93907f3485dSJohn Baldwin PROC_LOCK(p); 940b1fc0ec1SRobert Watson oldcred = p->p_ucred; 941b1fc0ec1SRobert Watson if (((rgid != (gid_t)-1 && rgid != oldcred->cr_rgid && 942b1fc0ec1SRobert Watson rgid != oldcred->cr_svgid) || 943b1fc0ec1SRobert Watson (egid != (gid_t)-1 && egid != oldcred->cr_groups[0] && 944b1fc0ec1SRobert Watson egid != oldcred->cr_rgid && egid != oldcred->cr_svgid)) && 94507f3485dSJohn Baldwin (error = suser_cred(oldcred, PRISON_ROOT)) != 0) { 94607f3485dSJohn Baldwin PROC_UNLOCK(p); 94707f3485dSJohn Baldwin crfree(newcred); 94807f3485dSJohn Baldwin mtx_unlock(&Giant); 94907f3485dSJohn Baldwin return (error); 95007f3485dSJohn Baldwin } 95107f3485dSJohn Baldwin 95207f3485dSJohn Baldwin crcopy(newcred, oldcred); 953b1fc0ec1SRobert Watson if (egid != (gid_t)-1 && oldcred->cr_groups[0] != egid) { 954b1fc0ec1SRobert Watson change_egid(newcred, egid); 955d5f81602SSean Eric Fagan setsugid(p); 956a89a5370SPeter Wemm } 957b1fc0ec1SRobert Watson if (rgid != (gid_t)-1 && oldcred->cr_rgid != rgid) { 958b1fc0ec1SRobert Watson change_rgid(newcred, rgid); 959d5f81602SSean Eric Fagan setsugid(p); 960a89a5370SPeter Wemm } 961b1fc0ec1SRobert Watson if ((rgid != (gid_t)-1 || newcred->cr_groups[0] != newcred->cr_rgid) && 962b1fc0ec1SRobert Watson newcred->cr_svgid != newcred->cr_groups[0]) { 963b1fc0ec1SRobert Watson change_svgid(newcred, newcred->cr_groups[0]); 964d5f81602SSean Eric Fagan setsugid(p); 965a89a5370SPeter Wemm } 9664589be70SRuslan Ermilov p->p_ucred = newcred; 96707f3485dSJohn Baldwin PROC_UNLOCK(p); 9684589be70SRuslan Ermilov crfree(oldcred); 969835a82eeSMatthew Dillon mtx_unlock(&Giant); 97007f3485dSJohn Baldwin return (0); 971df8bae1dSRodney W. Grimes } 972df8bae1dSRodney W. Grimes 9738ccd6334SPeter Wemm /* 9748ccd6334SPeter Wemm * setresuid(ruid, euid, suid) is like setreuid except control over the 9758ccd6334SPeter Wemm * saved uid is explicit. 9768ccd6334SPeter Wemm */ 9778ccd6334SPeter Wemm 9788ccd6334SPeter Wemm #ifndef _SYS_SYSPROTO_H_ 9798ccd6334SPeter Wemm struct setresuid_args { 9808ccd6334SPeter Wemm uid_t ruid; 9818ccd6334SPeter Wemm uid_t euid; 9828ccd6334SPeter Wemm uid_t suid; 9838ccd6334SPeter Wemm }; 9848ccd6334SPeter Wemm #endif 985835a82eeSMatthew Dillon /* 986835a82eeSMatthew Dillon * MPSAFE 987835a82eeSMatthew Dillon */ 9888ccd6334SPeter Wemm /* ARGSUSED */ 9898ccd6334SPeter Wemm int 9904c44ad8eSJohn Baldwin setresuid(register struct thread *td, struct setresuid_args *uap) 9918ccd6334SPeter Wemm { 992b40ce416SJulian Elischer struct proc *p = td->td_proc; 993b1fc0ec1SRobert Watson struct ucred *newcred, *oldcred; 994eb725b4eSRobert Watson uid_t euid, ruid, suid; 9951419eacbSAlfred Perlstein struct uidinfo *euip, *ruip; 9968ccd6334SPeter Wemm int error; 9978ccd6334SPeter Wemm 9988ccd6334SPeter Wemm euid = uap->euid; 999eb725b4eSRobert Watson ruid = uap->ruid; 10008ccd6334SPeter Wemm suid = uap->suid; 1001835a82eeSMatthew Dillon mtx_lock(&Giant); 100207f3485dSJohn Baldwin newcred = crget(); 10031419eacbSAlfred Perlstein euip = uifind(euid); 10041419eacbSAlfred Perlstein ruip = uifind(ruid); 100507f3485dSJohn Baldwin PROC_LOCK(p); 1006b1fc0ec1SRobert Watson oldcred = p->p_ucred; 1007b1fc0ec1SRobert Watson if (((ruid != (uid_t)-1 && ruid != oldcred->cr_ruid && 1008b1fc0ec1SRobert Watson ruid != oldcred->cr_svuid && 1009b1fc0ec1SRobert Watson ruid != oldcred->cr_uid) || 1010b1fc0ec1SRobert Watson (euid != (uid_t)-1 && euid != oldcred->cr_ruid && 1011b1fc0ec1SRobert Watson euid != oldcred->cr_svuid && 1012b1fc0ec1SRobert Watson euid != oldcred->cr_uid) || 1013b1fc0ec1SRobert Watson (suid != (uid_t)-1 && suid != oldcred->cr_ruid && 1014b1fc0ec1SRobert Watson suid != oldcred->cr_svuid && 1015b1fc0ec1SRobert Watson suid != oldcred->cr_uid)) && 101607f3485dSJohn Baldwin (error = suser_cred(oldcred, PRISON_ROOT)) != 0) { 101707f3485dSJohn Baldwin PROC_UNLOCK(p); 10181419eacbSAlfred Perlstein uifree(ruip); 10191419eacbSAlfred Perlstein uifree(euip); 102007f3485dSJohn Baldwin crfree(newcred); 102107f3485dSJohn Baldwin mtx_unlock(&Giant); 102207f3485dSJohn Baldwin return (error); 102307f3485dSJohn Baldwin } 102407f3485dSJohn Baldwin 102507f3485dSJohn Baldwin crcopy(newcred, oldcred); 1026b1fc0ec1SRobert Watson if (euid != (uid_t)-1 && oldcred->cr_uid != euid) { 10271419eacbSAlfred Perlstein change_euid(newcred, euip); 10288ccd6334SPeter Wemm setsugid(p); 10298ccd6334SPeter Wemm } 1030b1fc0ec1SRobert Watson if (ruid != (uid_t)-1 && oldcred->cr_ruid != ruid) { 10311419eacbSAlfred Perlstein change_ruid(newcred, ruip); 10328ccd6334SPeter Wemm setsugid(p); 10338ccd6334SPeter Wemm } 1034b1fc0ec1SRobert Watson if (suid != (uid_t)-1 && oldcred->cr_svuid != suid) { 1035b1fc0ec1SRobert Watson change_svuid(newcred, suid); 10368ccd6334SPeter Wemm setsugid(p); 10378ccd6334SPeter Wemm } 1038b1fc0ec1SRobert Watson p->p_ucred = newcred; 103907f3485dSJohn Baldwin PROC_UNLOCK(p); 10401419eacbSAlfred Perlstein uifree(ruip); 10411419eacbSAlfred Perlstein uifree(euip); 1042b1fc0ec1SRobert Watson crfree(oldcred); 1043835a82eeSMatthew Dillon mtx_unlock(&Giant); 104407f3485dSJohn Baldwin return (0); 10458ccd6334SPeter Wemm } 10468ccd6334SPeter Wemm 10478ccd6334SPeter Wemm /* 10488ccd6334SPeter Wemm * setresgid(rgid, egid, sgid) is like setregid except control over the 10498ccd6334SPeter Wemm * saved gid is explicit. 10508ccd6334SPeter Wemm */ 10518ccd6334SPeter Wemm 10528ccd6334SPeter Wemm #ifndef _SYS_SYSPROTO_H_ 10538ccd6334SPeter Wemm struct setresgid_args { 10548ccd6334SPeter Wemm gid_t rgid; 10558ccd6334SPeter Wemm gid_t egid; 10568ccd6334SPeter Wemm gid_t sgid; 10578ccd6334SPeter Wemm }; 10588ccd6334SPeter Wemm #endif 1059835a82eeSMatthew Dillon /* 1060835a82eeSMatthew Dillon * MPSAFE 1061835a82eeSMatthew Dillon */ 10628ccd6334SPeter Wemm /* ARGSUSED */ 10638ccd6334SPeter Wemm int 10644c44ad8eSJohn Baldwin setresgid(register struct thread *td, struct setresgid_args *uap) 10658ccd6334SPeter Wemm { 1066b40ce416SJulian Elischer struct proc *p = td->td_proc; 1067b1fc0ec1SRobert Watson struct ucred *newcred, *oldcred; 1068eb725b4eSRobert Watson gid_t egid, rgid, sgid; 10698ccd6334SPeter Wemm int error; 10708ccd6334SPeter Wemm 10718ccd6334SPeter Wemm egid = uap->egid; 1072eb725b4eSRobert Watson rgid = uap->rgid; 10738ccd6334SPeter Wemm sgid = uap->sgid; 1074835a82eeSMatthew Dillon mtx_lock(&Giant); 107507f3485dSJohn Baldwin newcred = crget(); 107607f3485dSJohn Baldwin PROC_LOCK(p); 1077b1fc0ec1SRobert Watson oldcred = p->p_ucred; 1078b1fc0ec1SRobert Watson if (((rgid != (gid_t)-1 && rgid != oldcred->cr_rgid && 1079b1fc0ec1SRobert Watson rgid != oldcred->cr_svgid && 1080b1fc0ec1SRobert Watson rgid != oldcred->cr_groups[0]) || 1081b1fc0ec1SRobert Watson (egid != (gid_t)-1 && egid != oldcred->cr_rgid && 1082b1fc0ec1SRobert Watson egid != oldcred->cr_svgid && 1083b1fc0ec1SRobert Watson egid != oldcred->cr_groups[0]) || 1084b1fc0ec1SRobert Watson (sgid != (gid_t)-1 && sgid != oldcred->cr_rgid && 1085b1fc0ec1SRobert Watson sgid != oldcred->cr_svgid && 1086b1fc0ec1SRobert Watson sgid != oldcred->cr_groups[0])) && 108707f3485dSJohn Baldwin (error = suser_cred(oldcred, PRISON_ROOT)) != 0) { 108807f3485dSJohn Baldwin PROC_UNLOCK(p); 108907f3485dSJohn Baldwin crfree(newcred); 109007f3485dSJohn Baldwin mtx_unlock(&Giant); 109107f3485dSJohn Baldwin return (error); 109207f3485dSJohn Baldwin } 109307f3485dSJohn Baldwin 109407f3485dSJohn Baldwin crcopy(newcred, oldcred); 1095b1fc0ec1SRobert Watson if (egid != (gid_t)-1 && oldcred->cr_groups[0] != egid) { 1096b1fc0ec1SRobert Watson change_egid(newcred, egid); 10978ccd6334SPeter Wemm setsugid(p); 10988ccd6334SPeter Wemm } 1099b1fc0ec1SRobert Watson if (rgid != (gid_t)-1 && oldcred->cr_rgid != rgid) { 1100b1fc0ec1SRobert Watson change_rgid(newcred, rgid); 11018ccd6334SPeter Wemm setsugid(p); 11028ccd6334SPeter Wemm } 1103b1fc0ec1SRobert Watson if (sgid != (gid_t)-1 && oldcred->cr_svgid != sgid) { 1104b1fc0ec1SRobert Watson change_svgid(newcred, sgid); 11058ccd6334SPeter Wemm setsugid(p); 11068ccd6334SPeter Wemm } 1107b1fc0ec1SRobert Watson p->p_ucred = newcred; 110807f3485dSJohn Baldwin PROC_UNLOCK(p); 1109b1fc0ec1SRobert Watson crfree(oldcred); 1110835a82eeSMatthew Dillon mtx_unlock(&Giant); 111107f3485dSJohn Baldwin return (0); 11128ccd6334SPeter Wemm } 11138ccd6334SPeter Wemm 11148ccd6334SPeter Wemm #ifndef _SYS_SYSPROTO_H_ 11158ccd6334SPeter Wemm struct getresuid_args { 11168ccd6334SPeter Wemm uid_t *ruid; 11178ccd6334SPeter Wemm uid_t *euid; 11188ccd6334SPeter Wemm uid_t *suid; 11198ccd6334SPeter Wemm }; 11208ccd6334SPeter Wemm #endif 1121835a82eeSMatthew Dillon /* 1122835a82eeSMatthew Dillon * MPSAFE 1123835a82eeSMatthew Dillon */ 11248ccd6334SPeter Wemm /* ARGSUSED */ 11258ccd6334SPeter Wemm int 11264c44ad8eSJohn Baldwin getresuid(register struct thread *td, struct getresuid_args *uap) 11278ccd6334SPeter Wemm { 1128835a82eeSMatthew Dillon struct ucred *cred; 11298ccd6334SPeter Wemm int error1 = 0, error2 = 0, error3 = 0; 11308ccd6334SPeter Wemm 1131d74ac681SMatthew Dillon cred = td->td_ucred; 11328ccd6334SPeter Wemm if (uap->ruid) 11337f05b035SAlfred Perlstein error1 = copyout(&cred->cr_ruid, 11347f05b035SAlfred Perlstein uap->ruid, sizeof(cred->cr_ruid)); 11358ccd6334SPeter Wemm if (uap->euid) 11367f05b035SAlfred Perlstein error2 = copyout(&cred->cr_uid, 11377f05b035SAlfred Perlstein uap->euid, sizeof(cred->cr_uid)); 11388ccd6334SPeter Wemm if (uap->suid) 11397f05b035SAlfred Perlstein error3 = copyout(&cred->cr_svuid, 11407f05b035SAlfred Perlstein uap->suid, sizeof(cred->cr_svuid)); 1141eb725b4eSRobert Watson return (error1 ? error1 : error2 ? error2 : error3); 11428ccd6334SPeter Wemm } 11438ccd6334SPeter Wemm 11448ccd6334SPeter Wemm #ifndef _SYS_SYSPROTO_H_ 11458ccd6334SPeter Wemm struct getresgid_args { 11468ccd6334SPeter Wemm gid_t *rgid; 11478ccd6334SPeter Wemm gid_t *egid; 11488ccd6334SPeter Wemm gid_t *sgid; 11498ccd6334SPeter Wemm }; 11508ccd6334SPeter Wemm #endif 1151835a82eeSMatthew Dillon /* 1152835a82eeSMatthew Dillon * MPSAFE 1153835a82eeSMatthew Dillon */ 11548ccd6334SPeter Wemm /* ARGSUSED */ 11558ccd6334SPeter Wemm int 11564c44ad8eSJohn Baldwin getresgid(register struct thread *td, struct getresgid_args *uap) 11578ccd6334SPeter Wemm { 1158835a82eeSMatthew Dillon struct ucred *cred; 11598ccd6334SPeter Wemm int error1 = 0, error2 = 0, error3 = 0; 11608ccd6334SPeter Wemm 1161d74ac681SMatthew Dillon cred = td->td_ucred; 11628ccd6334SPeter Wemm if (uap->rgid) 11637f05b035SAlfred Perlstein error1 = copyout(&cred->cr_rgid, 11647f05b035SAlfred Perlstein uap->rgid, sizeof(cred->cr_rgid)); 11658ccd6334SPeter Wemm if (uap->egid) 11667f05b035SAlfred Perlstein error2 = copyout(&cred->cr_groups[0], 11677f05b035SAlfred Perlstein uap->egid, sizeof(cred->cr_groups[0])); 11688ccd6334SPeter Wemm if (uap->sgid) 11697f05b035SAlfred Perlstein error3 = copyout(&cred->cr_svgid, 11707f05b035SAlfred Perlstein uap->sgid, sizeof(cred->cr_svgid)); 1171eb725b4eSRobert Watson return (error1 ? error1 : error2 ? error2 : error3); 11728ccd6334SPeter Wemm } 11738ccd6334SPeter Wemm 1174b67cbc65SPeter Wemm #ifndef _SYS_SYSPROTO_H_ 1175b67cbc65SPeter Wemm struct issetugid_args { 1176b67cbc65SPeter Wemm int dummy; 1177b67cbc65SPeter Wemm }; 1178b67cbc65SPeter Wemm #endif 1179eb725b4eSRobert Watson /* 1180eb725b4eSRobert Watson * NOT MPSAFE? 1181eb725b4eSRobert Watson */ 1182b67cbc65SPeter Wemm /* ARGSUSED */ 1183b67cbc65SPeter Wemm int 11844c44ad8eSJohn Baldwin issetugid(register struct thread *td, struct issetugid_args *uap) 1185b67cbc65SPeter Wemm { 1186b40ce416SJulian Elischer struct proc *p = td->td_proc; 1187b40ce416SJulian Elischer 1188b67cbc65SPeter Wemm /* 1189b67cbc65SPeter Wemm * Note: OpenBSD sets a P_SUGIDEXEC flag set at execve() time, 1190b67cbc65SPeter Wemm * we use P_SUGID because we consider changing the owners as 1191b67cbc65SPeter Wemm * "tainting" as well. 1192b67cbc65SPeter Wemm * This is significant for procs that start as root and "become" 1193b67cbc65SPeter Wemm * a user without an exec - programs cannot know *everything* 1194b67cbc65SPeter Wemm * that libc *might* have put in their data segment. 1195b67cbc65SPeter Wemm */ 1196f591779bSSeigo Tanimura PROC_LOCK(p); 1197b40ce416SJulian Elischer td->td_retval[0] = (p->p_flag & P_SUGID) ? 1 : 0; 1198f591779bSSeigo Tanimura PROC_UNLOCK(p); 1199b67cbc65SPeter Wemm return (0); 1200b67cbc65SPeter Wemm } 1201b67cbc65SPeter Wemm 1202835a82eeSMatthew Dillon /* 1203835a82eeSMatthew Dillon * MPSAFE 1204835a82eeSMatthew Dillon */ 1205130d0157SRobert Watson int 12064c44ad8eSJohn Baldwin __setugid(struct thread *td, struct __setugid_args *uap) 1207130d0157SRobert Watson { 1208130d0157SRobert Watson #ifdef REGRESSION 120907f3485dSJohn Baldwin struct proc *p; 1210835a82eeSMatthew Dillon 121107f3485dSJohn Baldwin p = td->td_proc; 1212130d0157SRobert Watson switch (uap->flag) { 1213130d0157SRobert Watson case 0: 121407f3485dSJohn Baldwin mtx_lock(&Giant); 121507f3485dSJohn Baldwin PROC_LOCK(p); 121607f3485dSJohn Baldwin p->p_flag &= ~P_SUGID; 121707f3485dSJohn Baldwin PROC_UNLOCK(p); 1218835a82eeSMatthew Dillon mtx_unlock(&Giant); 121907f3485dSJohn Baldwin return (0); 122007f3485dSJohn Baldwin case 1: 122107f3485dSJohn Baldwin mtx_lock(&Giant); 122207f3485dSJohn Baldwin PROC_LOCK(p); 122307f3485dSJohn Baldwin p->p_flag |= P_SUGID; 122407f3485dSJohn Baldwin PROC_UNLOCK(p); 122507f3485dSJohn Baldwin mtx_unlock(&Giant); 122607f3485dSJohn Baldwin return (0); 122707f3485dSJohn Baldwin default: 122807f3485dSJohn Baldwin return (EINVAL); 122907f3485dSJohn Baldwin } 1230130d0157SRobert Watson #else /* !REGRESSION */ 1231eb725b4eSRobert Watson 1232130d0157SRobert Watson return (ENOSYS); 1233eb725b4eSRobert Watson #endif /* REGRESSION */ 1234130d0157SRobert Watson } 1235130d0157SRobert Watson 1236df8bae1dSRodney W. Grimes /* 1237df8bae1dSRodney W. Grimes * Check if gid is a member of the group set. 1238d74ac681SMatthew Dillon * 1239d74ac681SMatthew Dillon * MPSAFE (cred must be held) 1240df8bae1dSRodney W. Grimes */ 124126f9a767SRodney W. Grimes int 12424c44ad8eSJohn Baldwin groupmember(gid_t gid, struct ucred *cred) 1243df8bae1dSRodney W. Grimes { 1244df8bae1dSRodney W. Grimes register gid_t *gp; 1245df8bae1dSRodney W. Grimes gid_t *egp; 1246df8bae1dSRodney W. Grimes 1247df8bae1dSRodney W. Grimes egp = &(cred->cr_groups[cred->cr_ngroups]); 1248df8bae1dSRodney W. Grimes for (gp = cred->cr_groups; gp < egp; gp++) 1249df8bae1dSRodney W. Grimes if (*gp == gid) 1250df8bae1dSRodney W. Grimes return (1); 1251df8bae1dSRodney W. Grimes return (0); 1252df8bae1dSRodney W. Grimes } 1253df8bae1dSRodney W. Grimes 12543b243b72SRobert Watson /* 1255d0615c64SAndrew R. Reiter * `suser_enabled' (which can be set by the security.suser_enabled 12567fd6a959SRobert Watson * sysctl) determines whether the system 'super-user' policy is in effect. 12577fd6a959SRobert Watson * If it is nonzero, an effective uid of 0 connotes special privilege, 12587fd6a959SRobert Watson * overriding many mandatory and discretionary protections. If it is zero, 12597fd6a959SRobert Watson * uid 0 is offered no special privilege in the kernel security policy. 12607fd6a959SRobert Watson * Setting it to zero may seriously impact the functionality of many 12617fd6a959SRobert Watson * existing userland programs, and should not be done without careful 12627fd6a959SRobert Watson * consideration of the consequences. 12633b243b72SRobert Watson */ 126493f4fd1cSRobert Watson int suser_enabled = 1; 1265d0615c64SAndrew R. Reiter SYSCTL_INT(_security_bsd, OID_AUTO, suser_enabled, CTLFLAG_RW, 126693f4fd1cSRobert Watson &suser_enabled, 0, "processes with uid 0 have privilege"); 1267d0615c64SAndrew R. Reiter TUNABLE_INT("security.bsd.suser_enabled", &suser_enabled); 1268579f4eb4SRobert Watson 1269df8bae1dSRodney W. Grimes /* 12707fd6a959SRobert Watson * Test whether the specified credentials imply "super-user" privilege. 127144731cabSJohn Baldwin * Return 0 or EPERM. The flag argument is currently used only to 127244731cabSJohn Baldwin * specify jail interaction. 1273df8bae1dSRodney W. Grimes */ 127426f9a767SRodney W. Grimes int 127544731cabSJohn Baldwin suser_cred(struct ucred *cred, int flag) 1276f711d546SPoul-Henning Kamp { 1277eb725b4eSRobert Watson 127893f4fd1cSRobert Watson if (!suser_enabled) 127903095547SRobert Watson return (EPERM); 128075c13541SPoul-Henning Kamp if (cred->cr_uid != 0) 128175c13541SPoul-Henning Kamp return (EPERM); 128291421ba2SRobert Watson if (jailed(cred) && !(flag & PRISON_ROOT)) 128375c13541SPoul-Henning Kamp return (EPERM); 128475c13541SPoul-Henning Kamp return (0); 128575c13541SPoul-Henning Kamp } 1286df8bae1dSRodney W. Grimes 12873ca719f1SRobert Watson /* 128844731cabSJohn Baldwin * Shortcut to hide contents of struct td and struct proc from the 128944731cabSJohn Baldwin * caller, promoting binary compatibility. 129044731cabSJohn Baldwin */ 129144731cabSJohn Baldwin int 129244731cabSJohn Baldwin suser(struct thread *td) 129344731cabSJohn Baldwin { 129444731cabSJohn Baldwin 129544731cabSJohn Baldwin return (suser_cred(td->td_ucred, 0)); 129644731cabSJohn Baldwin } 129744731cabSJohn Baldwin 129844731cabSJohn Baldwin /* 1299eb725b4eSRobert Watson * Test the active securelevel against a given level. securelevel_gt() 1300eb725b4eSRobert Watson * implements (securelevel > level). securelevel_ge() implements 1301eb725b4eSRobert Watson * (securelevel >= level). Note that the logic is inverted -- these 1302eb725b4eSRobert Watson * functions return EPERM on "success" and 0 on "failure". 13033ca719f1SRobert Watson * 1304d74ac681SMatthew Dillon * MPSAFE 13053ca719f1SRobert Watson */ 13063ca719f1SRobert Watson int 13073ca719f1SRobert Watson securelevel_gt(struct ucred *cr, int level) 13083ca719f1SRobert Watson { 1309eb725b4eSRobert Watson int active_securelevel; 13103ca719f1SRobert Watson 1311eb725b4eSRobert Watson active_securelevel = securelevel; 131270499328SJohn Baldwin KASSERT(cr != NULL, ("securelevel_gt: null cr")); 131301137630SRobert Watson if (cr->cr_prison != NULL) { 131401137630SRobert Watson mtx_lock(&cr->cr_prison->pr_mtx); 1315eb725b4eSRobert Watson active_securelevel = imax(cr->cr_prison->pr_securelevel, 1316eb725b4eSRobert Watson active_securelevel); 131701137630SRobert Watson mtx_unlock(&cr->cr_prison->pr_mtx); 131801137630SRobert Watson } 1319eb725b4eSRobert Watson return (active_securelevel > level ? EPERM : 0); 13203ca719f1SRobert Watson } 13213ca719f1SRobert Watson 13223ca719f1SRobert Watson int 13233ca719f1SRobert Watson securelevel_ge(struct ucred *cr, int level) 13243ca719f1SRobert Watson { 1325eb725b4eSRobert Watson int active_securelevel; 13263ca719f1SRobert Watson 1327eb725b4eSRobert Watson active_securelevel = securelevel; 132870499328SJohn Baldwin KASSERT(cr != NULL, ("securelevel_ge: null cr")); 132901137630SRobert Watson if (cr->cr_prison != NULL) { 133001137630SRobert Watson mtx_lock(&cr->cr_prison->pr_mtx); 1331eb725b4eSRobert Watson active_securelevel = imax(cr->cr_prison->pr_securelevel, 1332eb725b4eSRobert Watson active_securelevel); 133301137630SRobert Watson mtx_unlock(&cr->cr_prison->pr_mtx); 133401137630SRobert Watson } 1335eb725b4eSRobert Watson return (active_securelevel >= level ? EPERM : 0); 13363ca719f1SRobert Watson } 13373ca719f1SRobert Watson 13388a7d8cc6SRobert Watson /* 1339e409590dSRobert Watson * 'see_other_uids' determines whether or not visibility of processes 1340eb725b4eSRobert Watson * and sockets with credentials holding different real uids is possible 134148713bdcSRobert Watson * using a variety of system MIBs. 1342eb725b4eSRobert Watson * XXX: data declarations should be together near the beginning of the file. 13438a7d8cc6SRobert Watson */ 1344e409590dSRobert Watson static int see_other_uids = 1; 1345d0615c64SAndrew R. Reiter SYSCTL_INT(_security_bsd, OID_AUTO, see_other_uids, CTLFLAG_RW, 1346eb725b4eSRobert Watson &see_other_uids, 0, 13478a7d8cc6SRobert Watson "Unprivileged processes may see subjects/objects with different real uid"); 13488a7d8cc6SRobert Watson 13497fd6a959SRobert Watson /*- 13501b350b45SRobert Watson * Determine if u1 "can see" the subject specified by u2, according to the 13511b350b45SRobert Watson * 'see_other_uids' policy. 13521b350b45SRobert Watson * Returns: 0 for permitted, ESRCH otherwise 13531b350b45SRobert Watson * Locks: none 13541b350b45SRobert Watson * References: *u1 and *u2 must not change during the call 13551b350b45SRobert Watson * u1 may equal u2, in which case only one reference is required 13561b350b45SRobert Watson */ 13571b350b45SRobert Watson static int 13581b350b45SRobert Watson cr_seeotheruids(struct ucred *u1, struct ucred *u2) 13591b350b45SRobert Watson { 13601b350b45SRobert Watson 13611b350b45SRobert Watson if (!see_other_uids && u1->cr_ruid != u2->cr_ruid) { 136244731cabSJohn Baldwin if (suser_cred(u1, PRISON_ROOT) != 0) 13631b350b45SRobert Watson return (ESRCH); 13641b350b45SRobert Watson } 13651b350b45SRobert Watson return (0); 13661b350b45SRobert Watson } 13671b350b45SRobert Watson 13681b350b45SRobert Watson /*- 13697fd6a959SRobert Watson * Determine if u1 "can see" the subject specified by u2. 1370ed639720SRobert Watson * Returns: 0 for permitted, an errno value otherwise 1371ed639720SRobert Watson * Locks: none 1372eb725b4eSRobert Watson * References: *u1 and *u2 must not change during the call 1373ed639720SRobert Watson * u1 may equal u2, in which case only one reference is required 1374ed639720SRobert Watson */ 1375ed639720SRobert Watson int 137694088977SRobert Watson cr_cansee(struct ucred *u1, struct ucred *u2) 1377a9e0361bSPoul-Henning Kamp { 137891421ba2SRobert Watson int error; 1379a9e0361bSPoul-Henning Kamp 1380ed639720SRobert Watson if ((error = prison_check(u1, u2))) 138191421ba2SRobert Watson return (error); 13828a1d977dSRobert Watson #ifdef MAC 13838a1d977dSRobert Watson if ((error = mac_check_cred_visible(u1, u2))) 13848a1d977dSRobert Watson return (error); 13858a1d977dSRobert Watson #endif 13861b350b45SRobert Watson if ((error = cr_seeotheruids(u1, u2))) 13871b350b45SRobert Watson return (error); 1388387d2c03SRobert Watson return (0); 1389387d2c03SRobert Watson } 1390387d2c03SRobert Watson 13917fd6a959SRobert Watson /*- 1392f44d9e24SJohn Baldwin * Determine if td "can see" the subject specified by p. 13933b243b72SRobert Watson * Returns: 0 for permitted, an errno value otherwise 1394f44d9e24SJohn Baldwin * Locks: Sufficient locks to protect p->p_ucred must be held. td really 1395f44d9e24SJohn Baldwin * should be curthread. 1396f44d9e24SJohn Baldwin * References: td and p must be valid for the lifetime of the call 13973b243b72SRobert Watson */ 1398a0f75161SRobert Watson int 1399f44d9e24SJohn Baldwin p_cansee(struct thread *td, struct proc *p) 1400ed639720SRobert Watson { 1401ed639720SRobert Watson 140294088977SRobert Watson /* Wrap cr_cansee() for all functionality. */ 1403f44d9e24SJohn Baldwin KASSERT(td == curthread, ("%s: td not curthread", __func__)); 1404f44d9e24SJohn Baldwin PROC_LOCK_ASSERT(p, MA_OWNED); 1405f44d9e24SJohn Baldwin return (cr_cansee(td->td_ucred, p->p_ucred)); 1406ed639720SRobert Watson } 1407ed639720SRobert Watson 14087fd6a959SRobert Watson /*- 1409c83f8015SRobert Watson * Determine whether cred may deliver the specified signal to proc. 1410c83f8015SRobert Watson * Returns: 0 for permitted, an errno value otherwise. 1411c83f8015SRobert Watson * Locks: A lock must be held for proc. 1412c83f8015SRobert Watson * References: cred and proc must be valid for the lifetime of the call. 14134c5eb9c3SRobert Watson */ 14144c5eb9c3SRobert Watson int 1415c83f8015SRobert Watson cr_cansignal(struct ucred *cred, struct proc *proc, int signum) 1416387d2c03SRobert Watson { 141791421ba2SRobert Watson int error; 1418387d2c03SRobert Watson 1419f44d9e24SJohn Baldwin PROC_LOCK_ASSERT(proc, MA_OWNED); 14204c5eb9c3SRobert Watson /* 1421c83f8015SRobert Watson * Jail semantics limit the scope of signalling to proc in the 1422c83f8015SRobert Watson * same jail as cred, if cred is in jail. 14234c5eb9c3SRobert Watson */ 1424c83f8015SRobert Watson error = prison_check(cred, proc->p_ucred); 1425c83f8015SRobert Watson if (error) 142691421ba2SRobert Watson return (error); 14278a1d977dSRobert Watson #ifdef MAC 14288a1d977dSRobert Watson if ((error = mac_check_proc_signal(cred, proc, signum))) 14298a1d977dSRobert Watson return (error); 14308a1d977dSRobert Watson #endif 14311b350b45SRobert Watson error = cr_seeotheruids(cred, proc->p_ucred); 14321b350b45SRobert Watson if (error) 14331b350b45SRobert Watson return (error); 1434387d2c03SRobert Watson 1435387d2c03SRobert Watson /* 14363b243b72SRobert Watson * UNIX signal semantics depend on the status of the P_SUGID 14373b243b72SRobert Watson * bit on the target process. If the bit is set, then additional 14383b243b72SRobert Watson * restrictions are placed on the set of available signals. 14394c5eb9c3SRobert Watson */ 1440c83f8015SRobert Watson if (proc->p_flag & P_SUGID) { 14414c5eb9c3SRobert Watson switch (signum) { 14424c5eb9c3SRobert Watson case 0: 14434c5eb9c3SRobert Watson case SIGKILL: 14444c5eb9c3SRobert Watson case SIGINT: 14454c5eb9c3SRobert Watson case SIGTERM: 14464c5eb9c3SRobert Watson case SIGSTOP: 14474c5eb9c3SRobert Watson case SIGTTIN: 14484c5eb9c3SRobert Watson case SIGTTOU: 14494c5eb9c3SRobert Watson case SIGTSTP: 14504c5eb9c3SRobert Watson case SIGHUP: 14514c5eb9c3SRobert Watson case SIGUSR1: 14524c5eb9c3SRobert Watson case SIGUSR2: 14537fd6a959SRobert Watson /* 14547fd6a959SRobert Watson * Generally, permit job and terminal control 14557fd6a959SRobert Watson * signals. 14567fd6a959SRobert Watson */ 14574c5eb9c3SRobert Watson break; 14584c5eb9c3SRobert Watson default: 1459c83f8015SRobert Watson /* Not permitted without privilege. */ 146044731cabSJohn Baldwin error = suser_cred(cred, PRISON_ROOT); 14614c5eb9c3SRobert Watson if (error) 14624c5eb9c3SRobert Watson return (error); 14634c5eb9c3SRobert Watson } 1464e9e7ff5bSRobert Watson } 1465e9e7ff5bSRobert Watson 14664c5eb9c3SRobert Watson /* 14673b243b72SRobert Watson * Generally, the target credential's ruid or svuid must match the 1468e9e7ff5bSRobert Watson * subject credential's ruid or euid. 14694c5eb9c3SRobert Watson */ 1470c83f8015SRobert Watson if (cred->cr_ruid != proc->p_ucred->cr_ruid && 1471c83f8015SRobert Watson cred->cr_ruid != proc->p_ucred->cr_svuid && 1472c83f8015SRobert Watson cred->cr_uid != proc->p_ucred->cr_ruid && 1473c83f8015SRobert Watson cred->cr_uid != proc->p_ucred->cr_svuid) { 1474c83f8015SRobert Watson /* Not permitted without privilege. */ 147544731cabSJohn Baldwin error = suser_cred(cred, PRISON_ROOT); 14764c5eb9c3SRobert Watson if (error) 14774c5eb9c3SRobert Watson return (error); 14784c5eb9c3SRobert Watson } 1479387d2c03SRobert Watson 1480387d2c03SRobert Watson return (0); 1481387d2c03SRobert Watson } 1482a9e0361bSPoul-Henning Kamp 1483c83f8015SRobert Watson 1484c83f8015SRobert Watson /*- 1485f44d9e24SJohn Baldwin * Determine whether td may deliver the specified signal to p. 1486c83f8015SRobert Watson * Returns: 0 for permitted, an errno value otherwise 1487f44d9e24SJohn Baldwin * Locks: Sufficient locks to protect various components of td and p 1488f44d9e24SJohn Baldwin * must be held. td must be curthread, and a lock must be 1489f44d9e24SJohn Baldwin * held for p. 1490f44d9e24SJohn Baldwin * References: td and p must be valid for the lifetime of the call 1491c83f8015SRobert Watson */ 1492c83f8015SRobert Watson int 1493f44d9e24SJohn Baldwin p_cansignal(struct thread *td, struct proc *p, int signum) 1494c83f8015SRobert Watson { 1495c83f8015SRobert Watson 1496f44d9e24SJohn Baldwin KASSERT(td == curthread, ("%s: td not curthread", __func__)); 1497f44d9e24SJohn Baldwin PROC_LOCK_ASSERT(p, MA_OWNED); 1498f44d9e24SJohn Baldwin if (td->td_proc == p) 1499c83f8015SRobert Watson return (0); 1500c83f8015SRobert Watson 1501c83f8015SRobert Watson /* 1502c83f8015SRobert Watson * UNIX signalling semantics require that processes in the same 1503c83f8015SRobert Watson * session always be able to deliver SIGCONT to one another, 1504c83f8015SRobert Watson * overriding the remaining protections. 1505c83f8015SRobert Watson */ 1506f44d9e24SJohn Baldwin /* XXX: This will require an additional lock of some sort. */ 1507f44d9e24SJohn Baldwin if (signum == SIGCONT && td->td_proc->p_session == p->p_session) 1508c83f8015SRobert Watson return (0); 1509c83f8015SRobert Watson 1510f44d9e24SJohn Baldwin return (cr_cansignal(td->td_ucred, p, signum)); 1511c83f8015SRobert Watson } 1512c83f8015SRobert Watson 15137fd6a959SRobert Watson /*- 1514f44d9e24SJohn Baldwin * Determine whether td may reschedule p. 15157fd6a959SRobert Watson * Returns: 0 for permitted, an errno value otherwise 1516f44d9e24SJohn Baldwin * Locks: Sufficient locks to protect various components of td and p 1517f44d9e24SJohn Baldwin * must be held. td must be curthread, and a lock must 1518f44d9e24SJohn Baldwin * be held for p. 1519f44d9e24SJohn Baldwin * References: td and p must be valid for the lifetime of the call 15203b243b72SRobert Watson */ 1521a0f75161SRobert Watson int 1522f44d9e24SJohn Baldwin p_cansched(struct thread *td, struct proc *p) 1523387d2c03SRobert Watson { 152491421ba2SRobert Watson int error; 1525387d2c03SRobert Watson 1526f44d9e24SJohn Baldwin KASSERT(td == curthread, ("%s: td not curthread", __func__)); 1527f44d9e24SJohn Baldwin PROC_LOCK_ASSERT(p, MA_OWNED); 1528f44d9e24SJohn Baldwin if (td->td_proc == p) 1529387d2c03SRobert Watson return (0); 1530f44d9e24SJohn Baldwin if ((error = prison_check(td->td_ucred, p->p_ucred))) 153191421ba2SRobert Watson return (error); 15328a1d977dSRobert Watson #ifdef MAC 15338a1d977dSRobert Watson if ((error = mac_check_proc_sched(td->td_ucred, p))) 15348a1d977dSRobert Watson return (error); 15358a1d977dSRobert Watson #endif 1536f44d9e24SJohn Baldwin if ((error = cr_seeotheruids(td->td_ucred, p->p_ucred))) 15371b350b45SRobert Watson return (error); 1538f44d9e24SJohn Baldwin if (td->td_ucred->cr_ruid == p->p_ucred->cr_ruid) 1539387d2c03SRobert Watson return (0); 1540f44d9e24SJohn Baldwin if (td->td_ucred->cr_uid == p->p_ucred->cr_ruid) 1541387d2c03SRobert Watson return (0); 1542f44d9e24SJohn Baldwin if (suser_cred(td->td_ucred, PRISON_ROOT) == 0) 1543387d2c03SRobert Watson return (0); 1544387d2c03SRobert Watson 1545387d2c03SRobert Watson #ifdef CAPABILITIES 1546f44d9e24SJohn Baldwin if (!cap_check(NULL, td, CAP_SYS_NICE, PRISON_ROOT)) 1547387d2c03SRobert Watson return (0); 1548387d2c03SRobert Watson #endif 1549387d2c03SRobert Watson 1550387d2c03SRobert Watson return (EPERM); 1551387d2c03SRobert Watson } 1552387d2c03SRobert Watson 15533b243b72SRobert Watson /* 15545d476e73SRobert Watson * The 'unprivileged_proc_debug' flag may be used to disable a variety of 15555d476e73SRobert Watson * unprivileged inter-process debugging services, including some procfs 15565d476e73SRobert Watson * functionality, ptrace(), and ktrace(). In the past, inter-process 15575d476e73SRobert Watson * debugging has been involved in a variety of security problems, and sites 15585d476e73SRobert Watson * not requiring the service might choose to disable it when hardening 15595d476e73SRobert Watson * systems. 15603b243b72SRobert Watson * 15613b243b72SRobert Watson * XXX: Should modifying and reading this variable require locking? 1562eb725b4eSRobert Watson * XXX: data declarations should be together near the beginning of the file. 15633b243b72SRobert Watson */ 1564e409590dSRobert Watson static int unprivileged_proc_debug = 1; 1565d0615c64SAndrew R. Reiter SYSCTL_INT(_security_bsd, OID_AUTO, unprivileged_proc_debug, CTLFLAG_RW, 1566eb725b4eSRobert Watson &unprivileged_proc_debug, 0, 15670ef5652eSRobert Watson "Unprivileged processes may use process debugging facilities"); 15680ef5652eSRobert Watson 15697fd6a959SRobert Watson /*- 1570f44d9e24SJohn Baldwin * Determine whether td may debug p. 15717fd6a959SRobert Watson * Returns: 0 for permitted, an errno value otherwise 1572f44d9e24SJohn Baldwin * Locks: Sufficient locks to protect various components of td and p 1573f44d9e24SJohn Baldwin * must be held. td must be curthread, and a lock must 1574f44d9e24SJohn Baldwin * be held for p. 1575f44d9e24SJohn Baldwin * References: td and p must be valid for the lifetime of the call 15763b243b72SRobert Watson */ 1577a0f75161SRobert Watson int 1578f44d9e24SJohn Baldwin p_candebug(struct thread *td, struct proc *p) 1579387d2c03SRobert Watson { 1580eb725b4eSRobert Watson int credentialchanged, error, grpsubset, i, uidsubset; 1581387d2c03SRobert Watson 1582f44d9e24SJohn Baldwin KASSERT(td == curthread, ("%s: td not curthread", __func__)); 1583f44d9e24SJohn Baldwin PROC_LOCK_ASSERT(p, MA_OWNED); 1584e409590dSRobert Watson if (!unprivileged_proc_debug) { 1585f44d9e24SJohn Baldwin error = suser_cred(td->td_ucred, PRISON_ROOT); 158632d18604SRobert Watson if (error) 158732d18604SRobert Watson return (error); 158832d18604SRobert Watson } 1589f44d9e24SJohn Baldwin if (td->td_proc == p) 159023fad5b6SDag-Erling Smørgrav return (0); 1591f44d9e24SJohn Baldwin if ((error = prison_check(td->td_ucred, p->p_ucred))) 159291421ba2SRobert Watson return (error); 15938a1d977dSRobert Watson #ifdef MAC 15948a1d977dSRobert Watson if ((error = mac_check_proc_debug(td->td_ucred, p))) 15958a1d977dSRobert Watson return (error); 15968a1d977dSRobert Watson #endif 1597f44d9e24SJohn Baldwin if ((error = cr_seeotheruids(td->td_ucred, p->p_ucred))) 15981b350b45SRobert Watson return (error); 1599387d2c03SRobert Watson 16007fd6a959SRobert Watson /* 1601f44d9e24SJohn Baldwin * Is p's group set a subset of td's effective group set? This 1602f44d9e24SJohn Baldwin * includes p's egid, group access list, rgid, and svgid. 16037fd6a959SRobert Watson */ 1604db42a33dSRobert Watson grpsubset = 1; 1605f44d9e24SJohn Baldwin for (i = 0; i < p->p_ucred->cr_ngroups; i++) { 1606f44d9e24SJohn Baldwin if (!groupmember(p->p_ucred->cr_groups[i], td->td_ucred)) { 1607db42a33dSRobert Watson grpsubset = 0; 1608db42a33dSRobert Watson break; 1609db42a33dSRobert Watson } 1610db42a33dSRobert Watson } 1611db42a33dSRobert Watson grpsubset = grpsubset && 1612f44d9e24SJohn Baldwin groupmember(p->p_ucred->cr_rgid, td->td_ucred) && 1613f44d9e24SJohn Baldwin groupmember(p->p_ucred->cr_svgid, td->td_ucred); 1614db42a33dSRobert Watson 1615db42a33dSRobert Watson /* 1616f44d9e24SJohn Baldwin * Are the uids present in p's credential equal to td's 1617f44d9e24SJohn Baldwin * effective uid? This includes p's euid, svuid, and ruid. 1618db42a33dSRobert Watson */ 1619f44d9e24SJohn Baldwin uidsubset = (td->td_ucred->cr_uid == p->p_ucred->cr_uid && 1620f44d9e24SJohn Baldwin td->td_ucred->cr_uid == p->p_ucred->cr_svuid && 1621f44d9e24SJohn Baldwin td->td_ucred->cr_uid == p->p_ucred->cr_ruid); 1622db42a33dSRobert Watson 1623db42a33dSRobert Watson /* 1624db42a33dSRobert Watson * Has the credential of the process changed since the last exec()? 1625db42a33dSRobert Watson */ 1626f44d9e24SJohn Baldwin credentialchanged = (p->p_flag & P_SUGID); 1627db42a33dSRobert Watson 1628db42a33dSRobert Watson /* 1629f44d9e24SJohn Baldwin * If p's gids aren't a subset, or the uids aren't a subset, 1630db42a33dSRobert Watson * or the credential has changed, require appropriate privilege 1631f44d9e24SJohn Baldwin * for td to debug p. For POSIX.1e capabilities, this will 1632db42a33dSRobert Watson * require CAP_SYS_PTRACE. 1633db42a33dSRobert Watson */ 1634db42a33dSRobert Watson if (!grpsubset || !uidsubset || credentialchanged) { 1635f44d9e24SJohn Baldwin error = suser_cred(td->td_ucred, PRISON_ROOT); 163632d18604SRobert Watson if (error) 1637387d2c03SRobert Watson return (error); 16387fd6a959SRobert Watson } 1639387d2c03SRobert Watson 1640eb725b4eSRobert Watson /* Can't trace init when securelevel > 0. */ 1641f44d9e24SJohn Baldwin if (p == initproc) { 1642f44d9e24SJohn Baldwin error = securelevel_gt(td->td_ucred, 0); 16433ca719f1SRobert Watson if (error) 16443ca719f1SRobert Watson return (error); 16453ca719f1SRobert Watson } 1646387d2c03SRobert Watson 16475fab7614SRobert Watson /* 16485fab7614SRobert Watson * Can't trace a process that's currently exec'ing. 16495fab7614SRobert Watson * XXX: Note, this is not a security policy decision, it's a 16505fab7614SRobert Watson * basic correctness/functionality decision. Therefore, this check 16515fab7614SRobert Watson * should be moved to the caller's of p_candebug(). 16525fab7614SRobert Watson */ 1653f44d9e24SJohn Baldwin if ((p->p_flag & P_INEXEC) != 0) 16549ca45e81SDag-Erling Smørgrav return (EAGAIN); 16559ca45e81SDag-Erling Smørgrav 1656387d2c03SRobert Watson return (0); 1657387d2c03SRobert Watson } 1658387d2c03SRobert Watson 165929dc1288SRobert Watson /*- 166029dc1288SRobert Watson * Determine whether the subject represented by cred can "see" a socket. 166129dc1288SRobert Watson * Returns: 0 for permitted, ENOENT otherwise. 166229dc1288SRobert Watson */ 166329dc1288SRobert Watson int 166429dc1288SRobert Watson cr_canseesocket(struct ucred *cred, struct socket *so) 166529dc1288SRobert Watson { 166629dc1288SRobert Watson int error; 166729dc1288SRobert Watson 166829dc1288SRobert Watson error = prison_check(cred, so->so_cred); 166929dc1288SRobert Watson if (error) 167029dc1288SRobert Watson return (ENOENT); 16718a1d977dSRobert Watson #ifdef MAC 16728a1d977dSRobert Watson error = mac_check_socket_visible(cred, so); 16738a1d977dSRobert Watson if (error) 16748a1d977dSRobert Watson return (error); 16758a1d977dSRobert Watson #endif 167629dc1288SRobert Watson if (cr_seeotheruids(cred, so->so_cred)) 167729dc1288SRobert Watson return (ENOENT); 167829dc1288SRobert Watson 167929dc1288SRobert Watson return (0); 168029dc1288SRobert Watson } 168129dc1288SRobert Watson 1682a9e0361bSPoul-Henning Kamp /* 1683df8bae1dSRodney W. Grimes * Allocate a zeroed cred structure. 1684df8bae1dSRodney W. Grimes */ 1685df8bae1dSRodney W. Grimes struct ucred * 16864c44ad8eSJohn Baldwin crget(void) 1687df8bae1dSRodney W. Grimes { 1688df8bae1dSRodney W. Grimes register struct ucred *cr; 1689df8bae1dSRodney W. Grimes 16901e5d626aSAlfred Perlstein MALLOC(cr, struct ucred *, sizeof(*cr), M_CRED, M_WAITOK | M_ZERO); 1691df8bae1dSRodney W. Grimes cr->cr_ref = 1; 1692e1bca29fSMatthew Dillon cr->cr_mtxp = mtx_pool_find(cr); 169340244964SRobert Watson #ifdef MAC 169440244964SRobert Watson mac_init_cred(cr); 169540244964SRobert Watson #endif 1696df8bae1dSRodney W. Grimes return (cr); 1697df8bae1dSRodney W. Grimes } 1698df8bae1dSRodney W. Grimes 1699df8bae1dSRodney W. Grimes /* 17007fd6a959SRobert Watson * Claim another reference to a ucred structure. 17015c3f70d7SAlfred Perlstein */ 1702bd78ceceSJohn Baldwin struct ucred * 17034c44ad8eSJohn Baldwin crhold(struct ucred *cr) 17045c3f70d7SAlfred Perlstein { 17055c3f70d7SAlfred Perlstein 1706e1bca29fSMatthew Dillon mtx_lock(cr->cr_mtxp); 17075c3f70d7SAlfred Perlstein cr->cr_ref++; 1708e1bca29fSMatthew Dillon mtx_unlock(cr->cr_mtxp); 1709bd78ceceSJohn Baldwin return (cr); 17105c3f70d7SAlfred Perlstein } 17115c3f70d7SAlfred Perlstein 17125c3f70d7SAlfred Perlstein /* 1713df8bae1dSRodney W. Grimes * Free a cred structure. 1714df8bae1dSRodney W. Grimes * Throws away space when ref count gets to 0. 1715df8bae1dSRodney W. Grimes */ 171626f9a767SRodney W. Grimes void 17174c44ad8eSJohn Baldwin crfree(struct ucred *cr) 1718df8bae1dSRodney W. Grimes { 1719e1bca29fSMatthew Dillon struct mtx *mtxp = cr->cr_mtxp; 17201e5d626aSAlfred Perlstein 1721e1bca29fSMatthew Dillon mtx_lock(mtxp); 1722e04670b7SAlfred Perlstein KASSERT(cr->cr_ref > 0, ("bad ucred refcount: %d", cr->cr_ref)); 1723f535380cSDon Lewis if (--cr->cr_ref == 0) { 1724f535380cSDon Lewis /* 1725f535380cSDon Lewis * Some callers of crget(), such as nfs_statfs(), 1726f535380cSDon Lewis * allocate a temporary credential, but don't 1727f535380cSDon Lewis * allocate a uidinfo structure. 1728f535380cSDon Lewis */ 1729e1bca29fSMatthew Dillon mtx_unlock(mtxp); 1730c1a513c9SJohn Baldwin mtx_lock(&Giant); 1731f535380cSDon Lewis if (cr->cr_uidinfo != NULL) 1732f535380cSDon Lewis uifree(cr->cr_uidinfo); 1733823c224eSRobert Watson if (cr->cr_ruidinfo != NULL) 1734823c224eSRobert Watson uifree(cr->cr_ruidinfo); 173591421ba2SRobert Watson /* 173691421ba2SRobert Watson * Free a prison, if any. 173791421ba2SRobert Watson */ 173891421ba2SRobert Watson if (jailed(cr)) 173991421ba2SRobert Watson prison_free(cr->cr_prison); 174040244964SRobert Watson #ifdef MAC 174140244964SRobert Watson mac_destroy_cred(cr); 174240244964SRobert Watson #endif 17437f05b035SAlfred Perlstein FREE(cr, M_CRED); 1744c1a513c9SJohn Baldwin mtx_unlock(&Giant); 1745e1bca29fSMatthew Dillon } else { 1746e1bca29fSMatthew Dillon mtx_unlock(mtxp); 1747e1bca29fSMatthew Dillon } 1748df8bae1dSRodney W. Grimes } 1749df8bae1dSRodney W. Grimes 1750df8bae1dSRodney W. Grimes /* 1751bd78ceceSJohn Baldwin * Check to see if this ucred is shared. 1752df8bae1dSRodney W. Grimes */ 1753bd78ceceSJohn Baldwin int 17544c44ad8eSJohn Baldwin crshared(struct ucred *cr) 1755df8bae1dSRodney W. Grimes { 1756bd78ceceSJohn Baldwin int shared; 1757df8bae1dSRodney W. Grimes 1758e1bca29fSMatthew Dillon mtx_lock(cr->cr_mtxp); 1759bd78ceceSJohn Baldwin shared = (cr->cr_ref > 1); 1760e1bca29fSMatthew Dillon mtx_unlock(cr->cr_mtxp); 1761bd78ceceSJohn Baldwin return (shared); 17621e5d626aSAlfred Perlstein } 1763bd78ceceSJohn Baldwin 1764bd78ceceSJohn Baldwin /* 1765bd78ceceSJohn Baldwin * Copy a ucred's contents from a template. Does not block. 1766bd78ceceSJohn Baldwin */ 1767bd78ceceSJohn Baldwin void 17684c44ad8eSJohn Baldwin crcopy(struct ucred *dest, struct ucred *src) 1769bd78ceceSJohn Baldwin { 1770bd78ceceSJohn Baldwin 1771bd78ceceSJohn Baldwin KASSERT(crshared(dest) == 0, ("crcopy of shared ucred")); 1772bd78ceceSJohn Baldwin bcopy(&src->cr_startcopy, &dest->cr_startcopy, 1773bd78ceceSJohn Baldwin (unsigned)((caddr_t)&src->cr_endcopy - 1774bd78ceceSJohn Baldwin (caddr_t)&src->cr_startcopy)); 1775bd78ceceSJohn Baldwin uihold(dest->cr_uidinfo); 1776bd78ceceSJohn Baldwin uihold(dest->cr_ruidinfo); 1777bd78ceceSJohn Baldwin if (jailed(dest)) 1778bd78ceceSJohn Baldwin prison_hold(dest->cr_prison); 177940244964SRobert Watson #ifdef MAC 178040244964SRobert Watson mac_create_cred(src, dest); 178140244964SRobert Watson #endif 1782df8bae1dSRodney W. Grimes } 1783df8bae1dSRodney W. Grimes 1784df8bae1dSRodney W. Grimes /* 1785df8bae1dSRodney W. Grimes * Dup cred struct to a new held one. 1786df8bae1dSRodney W. Grimes */ 1787df8bae1dSRodney W. Grimes struct ucred * 17884c44ad8eSJohn Baldwin crdup(struct ucred *cr) 1789df8bae1dSRodney W. Grimes { 1790df8bae1dSRodney W. Grimes struct ucred *newcr; 1791df8bae1dSRodney W. Grimes 1792bd78ceceSJohn Baldwin newcr = crget(); 1793bd78ceceSJohn Baldwin crcopy(newcr, cr); 1794df8bae1dSRodney W. Grimes return (newcr); 1795df8bae1dSRodney W. Grimes } 1796df8bae1dSRodney W. Grimes 1797aaa1c771SJonathan Mini #ifdef DIAGNOSTIC 1798aaa1c771SJonathan Mini void 1799aaa1c771SJonathan Mini cred_free_thread(struct thread *td) 1800aaa1c771SJonathan Mini { 1801aaa1c771SJonathan Mini struct ucred *cred; 1802aaa1c771SJonathan Mini 1803aaa1c771SJonathan Mini cred = td->td_ucred; 1804aaa1c771SJonathan Mini td->td_ucred = NULL; 1805aaa1c771SJonathan Mini if (cred != NULL) 1806aaa1c771SJonathan Mini crfree(cred); 1807aaa1c771SJonathan Mini } 1808aaa1c771SJonathan Mini #endif 1809aaa1c771SJonathan Mini 1810df8bae1dSRodney W. Grimes /* 181176183f34SDima Dorfman * Fill in a struct xucred based on a struct ucred. 181276183f34SDima Dorfman */ 181376183f34SDima Dorfman void 18144c44ad8eSJohn Baldwin cru2x(struct ucred *cr, struct xucred *xcr) 181576183f34SDima Dorfman { 181676183f34SDima Dorfman 181776183f34SDima Dorfman bzero(xcr, sizeof(*xcr)); 181876183f34SDima Dorfman xcr->cr_version = XUCRED_VERSION; 181976183f34SDima Dorfman xcr->cr_uid = cr->cr_uid; 182076183f34SDima Dorfman xcr->cr_ngroups = cr->cr_ngroups; 182176183f34SDima Dorfman bcopy(cr->cr_groups, xcr->cr_groups, sizeof(cr->cr_groups)); 182276183f34SDima Dorfman } 182376183f34SDima Dorfman 182476183f34SDima Dorfman /* 18252eb927e2SJulian Elischer * small routine to swap a thread's current ucred for the correct one 18262eb927e2SJulian Elischer * taken from the process. 18272eb927e2SJulian Elischer */ 18282eb927e2SJulian Elischer void 18292eb927e2SJulian Elischer cred_update_thread(struct thread *td) 18302eb927e2SJulian Elischer { 18312eb927e2SJulian Elischer struct proc *p; 183265e3406dSJohn Baldwin struct ucred *cred; 18332eb927e2SJulian Elischer 18342eb927e2SJulian Elischer p = td->td_proc; 183565e3406dSJohn Baldwin cred = td->td_ucred; 18362eb927e2SJulian Elischer mtx_lock(&Giant); 18372eb927e2SJulian Elischer PROC_LOCK(p); 18382eb927e2SJulian Elischer td->td_ucred = crhold(p->p_ucred); 18392eb927e2SJulian Elischer PROC_UNLOCK(p); 184065e3406dSJohn Baldwin if (cred != NULL) 184165e3406dSJohn Baldwin crfree(cred); 184265e3406dSJohn Baldwin mtx_unlock(&Giant); 18432eb927e2SJulian Elischer } 18442eb927e2SJulian Elischer 18452eb927e2SJulian Elischer /* 1846df8bae1dSRodney W. Grimes * Get login name, if available. 1847df8bae1dSRodney W. Grimes */ 1848d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 1849df8bae1dSRodney W. Grimes struct getlogin_args { 1850df8bae1dSRodney W. Grimes char *namebuf; 1851df8bae1dSRodney W. Grimes u_int namelen; 1852df8bae1dSRodney W. Grimes }; 1853d2d3e875SBruce Evans #endif 1854835a82eeSMatthew Dillon /* 1855835a82eeSMatthew Dillon * MPSAFE 1856835a82eeSMatthew Dillon */ 1857df8bae1dSRodney W. Grimes /* ARGSUSED */ 185826f9a767SRodney W. Grimes int 18594c44ad8eSJohn Baldwin getlogin(struct thread *td, struct getlogin_args *uap) 1860df8bae1dSRodney W. Grimes { 1861835a82eeSMatthew Dillon int error; 1862f591779bSSeigo Tanimura char login[MAXLOGNAME]; 1863b40ce416SJulian Elischer struct proc *p = td->td_proc; 1864df8bae1dSRodney W. Grimes 186530cf3ac4SAndrey A. Chernov if (uap->namelen > MAXLOGNAME) 186653490b76SAndrey A. Chernov uap->namelen = MAXLOGNAME; 1867f591779bSSeigo Tanimura PROC_LOCK(p); 1868f591779bSSeigo Tanimura SESS_LOCK(p->p_session); 1869f591779bSSeigo Tanimura bcopy(p->p_session->s_login, login, uap->namelen); 1870f591779bSSeigo Tanimura SESS_UNLOCK(p->p_session); 1871f591779bSSeigo Tanimura PROC_UNLOCK(p); 18727f05b035SAlfred Perlstein error = copyout(login, uap->namebuf, uap->namelen); 1873835a82eeSMatthew Dillon return(error); 1874df8bae1dSRodney W. Grimes } 1875df8bae1dSRodney W. Grimes 1876df8bae1dSRodney W. Grimes /* 1877df8bae1dSRodney W. Grimes * Set login name. 1878df8bae1dSRodney W. Grimes */ 1879d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 1880df8bae1dSRodney W. Grimes struct setlogin_args { 1881df8bae1dSRodney W. Grimes char *namebuf; 1882df8bae1dSRodney W. Grimes }; 1883d2d3e875SBruce Evans #endif 1884835a82eeSMatthew Dillon /* 1885835a82eeSMatthew Dillon * MPSAFE 1886835a82eeSMatthew Dillon */ 1887df8bae1dSRodney W. Grimes /* ARGSUSED */ 188826f9a767SRodney W. Grimes int 18894c44ad8eSJohn Baldwin setlogin(struct thread *td, struct setlogin_args *uap) 1890df8bae1dSRodney W. Grimes { 1891b40ce416SJulian Elischer struct proc *p = td->td_proc; 1892df8bae1dSRodney W. Grimes int error; 1893964ca0caSAndrey A. Chernov char logintmp[MAXLOGNAME]; 1894df8bae1dSRodney W. Grimes 189507f3485dSJohn Baldwin error = suser_cred(td->td_ucred, PRISON_ROOT); 189607f3485dSJohn Baldwin if (error) 189707f3485dSJohn Baldwin return (error); 18987f05b035SAlfred Perlstein error = copyinstr(uap->namebuf, logintmp, sizeof(logintmp), NULL); 1899eb725b4eSRobert Watson if (error == ENAMETOOLONG) 1900df8bae1dSRodney W. Grimes error = EINVAL; 1901f591779bSSeigo Tanimura else if (!error) { 1902f591779bSSeigo Tanimura PROC_LOCK(p); 1903f591779bSSeigo Tanimura SESS_LOCK(p->p_session); 1904f591779bSSeigo Tanimura (void) memcpy(p->p_session->s_login, logintmp, 1905964ca0caSAndrey A. Chernov sizeof(logintmp)); 1906f591779bSSeigo Tanimura SESS_UNLOCK(p->p_session); 1907f591779bSSeigo Tanimura PROC_UNLOCK(p); 1908f591779bSSeigo Tanimura } 1909df8bae1dSRodney W. Grimes return (error); 1910df8bae1dSRodney W. Grimes } 1911d5f81602SSean Eric Fagan 1912d5f81602SSean Eric Fagan void 19134c44ad8eSJohn Baldwin setsugid(struct proc *p) 1914d5f81602SSean Eric Fagan { 1915f2102dadSAlfred Perlstein 1916f2102dadSAlfred Perlstein PROC_LOCK_ASSERT(p, MA_OWNED); 1917d5f81602SSean Eric Fagan p->p_flag |= P_SUGID; 191889361835SSean Eric Fagan if (!(p->p_pfsflags & PF_ISUGID)) 1919d5f81602SSean Eric Fagan p->p_stops = 0; 1920d5f81602SSean Eric Fagan } 1921f535380cSDon Lewis 19227fd6a959SRobert Watson /*- 19237fd6a959SRobert Watson * Change a process's effective uid. 1924b1fc0ec1SRobert Watson * Side effects: newcred->cr_uid and newcred->cr_uidinfo will be modified. 1925b1fc0ec1SRobert Watson * References: newcred must be an exclusive credential reference for the 1926b1fc0ec1SRobert Watson * duration of the call. 1927f535380cSDon Lewis */ 1928f535380cSDon Lewis void 19291419eacbSAlfred Perlstein change_euid(struct ucred *newcred, struct uidinfo *euip) 1930f535380cSDon Lewis { 1931f535380cSDon Lewis 19321419eacbSAlfred Perlstein newcred->cr_uid = euip->ui_uid; 19331419eacbSAlfred Perlstein uihold(euip); 1934b1fc0ec1SRobert Watson uifree(newcred->cr_uidinfo); 19351419eacbSAlfred Perlstein newcred->cr_uidinfo = euip; 1936f535380cSDon Lewis } 1937f535380cSDon Lewis 19387fd6a959SRobert Watson /*- 19397fd6a959SRobert Watson * Change a process's effective gid. 1940b1fc0ec1SRobert Watson * Side effects: newcred->cr_gid will be modified. 1941b1fc0ec1SRobert Watson * References: newcred must be an exclusive credential reference for the 1942b1fc0ec1SRobert Watson * duration of the call. 1943f535380cSDon Lewis */ 1944810bfc8eSAndrew Gallatin void 19454c44ad8eSJohn Baldwin change_egid(struct ucred *newcred, gid_t egid) 1946b1fc0ec1SRobert Watson { 1947b1fc0ec1SRobert Watson 1948b1fc0ec1SRobert Watson newcred->cr_groups[0] = egid; 1949b1fc0ec1SRobert Watson } 1950b1fc0ec1SRobert Watson 19517fd6a959SRobert Watson /*- 19527fd6a959SRobert Watson * Change a process's real uid. 1953b1fc0ec1SRobert Watson * Side effects: newcred->cr_ruid will be updated, newcred->cr_ruidinfo 1954b1fc0ec1SRobert Watson * will be updated, and the old and new cr_ruidinfo proc 1955b1fc0ec1SRobert Watson * counts will be updated. 1956b1fc0ec1SRobert Watson * References: newcred must be an exclusive credential reference for the 1957b1fc0ec1SRobert Watson * duration of the call. 1958b1fc0ec1SRobert Watson */ 1959b1fc0ec1SRobert Watson void 19601419eacbSAlfred Perlstein change_ruid(struct ucred *newcred, struct uidinfo *ruip) 1961f535380cSDon Lewis { 1962f535380cSDon Lewis 1963b1fc0ec1SRobert Watson (void)chgproccnt(newcred->cr_ruidinfo, -1, 0); 19641419eacbSAlfred Perlstein newcred->cr_ruid = ruip->ui_uid; 19651419eacbSAlfred Perlstein uihold(ruip); 1966b1fc0ec1SRobert Watson uifree(newcred->cr_ruidinfo); 19671419eacbSAlfred Perlstein newcred->cr_ruidinfo = ruip; 1968b1fc0ec1SRobert Watson (void)chgproccnt(newcred->cr_ruidinfo, 1, 0); 1969b1fc0ec1SRobert Watson } 1970b1fc0ec1SRobert Watson 19717fd6a959SRobert Watson /*- 19727fd6a959SRobert Watson * Change a process's real gid. 1973b1fc0ec1SRobert Watson * Side effects: newcred->cr_rgid will be updated. 1974b1fc0ec1SRobert Watson * References: newcred must be an exclusive credential reference for the 1975b1fc0ec1SRobert Watson * duration of the call. 1976b1fc0ec1SRobert Watson */ 1977b1fc0ec1SRobert Watson void 19784c44ad8eSJohn Baldwin change_rgid(struct ucred *newcred, gid_t rgid) 1979b1fc0ec1SRobert Watson { 1980b1fc0ec1SRobert Watson 1981b1fc0ec1SRobert Watson newcred->cr_rgid = rgid; 1982b1fc0ec1SRobert Watson } 1983b1fc0ec1SRobert Watson 19847fd6a959SRobert Watson /*- 19857fd6a959SRobert Watson * Change a process's saved uid. 1986b1fc0ec1SRobert Watson * Side effects: newcred->cr_svuid will be updated. 1987b1fc0ec1SRobert Watson * References: newcred must be an exclusive credential reference for the 1988b1fc0ec1SRobert Watson * duration of the call. 1989b1fc0ec1SRobert Watson */ 1990b1fc0ec1SRobert Watson void 19914c44ad8eSJohn Baldwin change_svuid(struct ucred *newcred, uid_t svuid) 1992b1fc0ec1SRobert Watson { 1993b1fc0ec1SRobert Watson 1994b1fc0ec1SRobert Watson newcred->cr_svuid = svuid; 1995b1fc0ec1SRobert Watson } 1996b1fc0ec1SRobert Watson 19977fd6a959SRobert Watson /*- 19987fd6a959SRobert Watson * Change a process's saved gid. 1999b1fc0ec1SRobert Watson * Side effects: newcred->cr_svgid will be updated. 2000b1fc0ec1SRobert Watson * References: newcred must be an exclusive credential reference for the 2001b1fc0ec1SRobert Watson * duration of the call. 2002b1fc0ec1SRobert Watson */ 2003b1fc0ec1SRobert Watson void 20044c44ad8eSJohn Baldwin change_svgid(struct ucred *newcred, gid_t svgid) 2005b1fc0ec1SRobert Watson { 2006b1fc0ec1SRobert Watson 2007b1fc0ec1SRobert Watson newcred->cr_svgid = svgid; 2008f535380cSDon Lewis } 2009