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 * 4. Neither the name of the University nor the names of its contributors 20df8bae1dSRodney W. Grimes * may be used to endorse or promote products derived from this software 21df8bae1dSRodney W. Grimes * without specific prior written permission. 22df8bae1dSRodney W. Grimes * 23df8bae1dSRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24df8bae1dSRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25df8bae1dSRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26df8bae1dSRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27df8bae1dSRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28df8bae1dSRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29df8bae1dSRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30df8bae1dSRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31df8bae1dSRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32df8bae1dSRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33df8bae1dSRodney W. Grimes * SUCH DAMAGE. 34df8bae1dSRodney W. Grimes * 35df8bae1dSRodney W. Grimes * @(#)kern_prot.c 8.6 (Berkeley) 1/21/94 36df8bae1dSRodney W. Grimes */ 37df8bae1dSRodney W. Grimes 38df8bae1dSRodney W. Grimes /* 39df8bae1dSRodney W. Grimes * System calls related to processes and protection 40df8bae1dSRodney W. Grimes */ 41df8bae1dSRodney W. Grimes 42677b542eSDavid E. O'Brien #include <sys/cdefs.h> 43677b542eSDavid E. O'Brien __FBSDID("$FreeBSD$"); 44677b542eSDavid E. O'Brien 455591b823SEivind Eklund #include "opt_compat.h" 4640244964SRobert Watson #include "opt_mac.h" 475591b823SEivind Eklund 48df8bae1dSRodney W. Grimes #include <sys/param.h> 49df8bae1dSRodney W. Grimes #include <sys/systm.h> 50fb919e4dSMark Murray #include <sys/acct.h> 51df04411aSRobert Watson #include <sys/kdb.h> 521c5bb3eaSPeter Wemm #include <sys/kernel.h> 5398f03f90SJake Burkholder #include <sys/lock.h> 5440244964SRobert Watson #include <sys/mac.h> 55f9d0d524SRobert Watson #include <sys/malloc.h> 56fb919e4dSMark Murray #include <sys/mutex.h> 575b29d6e9SJohn Baldwin #include <sys/sx.h> 58f591779bSSeigo Tanimura #include <sys/proc.h> 59fb919e4dSMark Murray #include <sys/sysproto.h> 60eb725b4eSRobert Watson #include <sys/jail.h> 61d5f81602SSean Eric Fagan #include <sys/pioctl.h> 62f535380cSDon Lewis #include <sys/resourcevar.h> 6329dc1288SRobert Watson #include <sys/socket.h> 6429dc1288SRobert Watson #include <sys/socketvar.h> 65579f4eb4SRobert Watson #include <sys/sysctl.h> 66df8bae1dSRodney W. Grimes 67a1c995b6SPoul-Henning Kamp static MALLOC_DEFINE(M_CRED, "cred", "credentials"); 68a1c995b6SPoul-Henning Kamp 69d0615c64SAndrew R. Reiter SYSCTL_DECL(_security); 70d0615c64SAndrew R. Reiter SYSCTL_NODE(_security, OID_AUTO, bsd, CTLFLAG_RW, 0, 7148713bdcSRobert Watson "BSD security policy"); 7248713bdcSRobert Watson 73d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 74ad7507e2SSteven Wallace struct getpid_args { 75df8bae1dSRodney W. Grimes int dummy; 76df8bae1dSRodney W. Grimes }; 77d2d3e875SBruce Evans #endif 78835a82eeSMatthew Dillon /* 79835a82eeSMatthew Dillon * MPSAFE 80835a82eeSMatthew Dillon */ 81df8bae1dSRodney W. Grimes /* ARGSUSED */ 8226f9a767SRodney W. Grimes int 834c44ad8eSJohn Baldwin getpid(struct thread *td, struct getpid_args *uap) 84df8bae1dSRodney W. Grimes { 85b40ce416SJulian Elischer struct proc *p = td->td_proc; 86df8bae1dSRodney W. Grimes 87b40ce416SJulian Elischer td->td_retval[0] = p->p_pid; 881930e303SPoul-Henning Kamp #if defined(COMPAT_43) 89bae3a80bSJohn Baldwin PROC_LOCK(p); 90b40ce416SJulian Elischer td->td_retval[1] = p->p_pptr->p_pid; 91bae3a80bSJohn Baldwin PROC_UNLOCK(p); 92df8bae1dSRodney W. Grimes #endif 93df8bae1dSRodney W. Grimes return (0); 94df8bae1dSRodney W. Grimes } 95df8bae1dSRodney W. Grimes 96d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 97ad7507e2SSteven Wallace struct getppid_args { 98ad7507e2SSteven Wallace int dummy; 99ad7507e2SSteven Wallace }; 100d2d3e875SBruce Evans #endif 101835a82eeSMatthew Dillon /* 102835a82eeSMatthew Dillon * MPSAFE 103835a82eeSMatthew Dillon */ 104df8bae1dSRodney W. Grimes /* ARGSUSED */ 10526f9a767SRodney W. Grimes int 1064c44ad8eSJohn Baldwin getppid(struct thread *td, struct getppid_args *uap) 107df8bae1dSRodney W. Grimes { 108b40ce416SJulian Elischer struct proc *p = td->td_proc; 109df8bae1dSRodney W. Grimes 110bae3a80bSJohn Baldwin PROC_LOCK(p); 111b40ce416SJulian Elischer td->td_retval[0] = p->p_pptr->p_pid; 112bae3a80bSJohn Baldwin PROC_UNLOCK(p); 113df8bae1dSRodney W. Grimes return (0); 114df8bae1dSRodney W. Grimes } 115df8bae1dSRodney W. Grimes 11636e9f877SMatthew Dillon /* 117eb725b4eSRobert Watson * Get process group ID; note that POSIX getpgrp takes no parameter. 11836e9f877SMatthew Dillon */ 119d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 120ad7507e2SSteven Wallace struct getpgrp_args { 121ad7507e2SSteven Wallace int dummy; 122ad7507e2SSteven Wallace }; 123d2d3e875SBruce Evans #endif 124835a82eeSMatthew Dillon /* 125835a82eeSMatthew Dillon * MPSAFE 126835a82eeSMatthew Dillon */ 12726f9a767SRodney W. Grimes int 1284c44ad8eSJohn Baldwin getpgrp(struct thread *td, struct getpgrp_args *uap) 129df8bae1dSRodney W. Grimes { 130b40ce416SJulian Elischer struct proc *p = td->td_proc; 131df8bae1dSRodney W. Grimes 132f591779bSSeigo Tanimura PROC_LOCK(p); 133b40ce416SJulian Elischer td->td_retval[0] = p->p_pgrp->pg_id; 134f591779bSSeigo Tanimura PROC_UNLOCK(p); 135df8bae1dSRodney W. Grimes return (0); 136df8bae1dSRodney W. Grimes } 137df8bae1dSRodney W. Grimes 1381a5018a0SPeter Wemm /* Get an arbitary pid's process group id */ 1391a5018a0SPeter Wemm #ifndef _SYS_SYSPROTO_H_ 1401a5018a0SPeter Wemm struct getpgid_args { 1411a5018a0SPeter Wemm pid_t pid; 1421a5018a0SPeter Wemm }; 1431a5018a0SPeter Wemm #endif 144835a82eeSMatthew Dillon /* 145835a82eeSMatthew Dillon * MPSAFE 146835a82eeSMatthew Dillon */ 1471a5018a0SPeter Wemm int 1484c44ad8eSJohn Baldwin getpgid(struct thread *td, struct getpgid_args *uap) 1491a5018a0SPeter Wemm { 150a70a2b74SJohn Baldwin struct proc *p; 151f2ae7368SJohn Baldwin int error; 15265de0c7aSDon Lewis 153f591779bSSeigo Tanimura if (uap->pid == 0) { 154a70a2b74SJohn Baldwin p = td->td_proc; 155f591779bSSeigo Tanimura PROC_LOCK(p); 156a70a2b74SJohn Baldwin } else { 157a70a2b74SJohn Baldwin p = pfind(uap->pid); 158a70a2b74SJohn Baldwin if (p == NULL) 159a70a2b74SJohn Baldwin return (ESRCH); 160a70a2b74SJohn Baldwin error = p_cansee(td, p); 161a70a2b74SJohn Baldwin if (error) { 162a70a2b74SJohn Baldwin PROC_UNLOCK(p); 163a70a2b74SJohn Baldwin return (error); 164a70a2b74SJohn Baldwin } 165a70a2b74SJohn Baldwin } 166b40ce416SJulian Elischer td->td_retval[0] = p->p_pgrp->pg_id; 167f591779bSSeigo Tanimura PROC_UNLOCK(p); 168a70a2b74SJohn Baldwin return (0); 1691a5018a0SPeter Wemm } 1701a5018a0SPeter Wemm 1711a5018a0SPeter Wemm /* 1721a5018a0SPeter Wemm * Get an arbitary pid's session id. 1731a5018a0SPeter Wemm */ 1741a5018a0SPeter Wemm #ifndef _SYS_SYSPROTO_H_ 1751a5018a0SPeter Wemm struct getsid_args { 1761a5018a0SPeter Wemm pid_t pid; 1771a5018a0SPeter Wemm }; 1781a5018a0SPeter Wemm #endif 179835a82eeSMatthew Dillon /* 180835a82eeSMatthew Dillon * MPSAFE 181835a82eeSMatthew Dillon */ 1821a5018a0SPeter Wemm int 1834c44ad8eSJohn Baldwin getsid(struct thread *td, struct getsid_args *uap) 1841a5018a0SPeter Wemm { 185a70a2b74SJohn Baldwin struct proc *p; 186eb725b4eSRobert Watson int error; 18765de0c7aSDon Lewis 188f591779bSSeigo Tanimura if (uap->pid == 0) { 189a70a2b74SJohn Baldwin p = td->td_proc; 190f591779bSSeigo Tanimura PROC_LOCK(p); 191a70a2b74SJohn Baldwin } else { 192a70a2b74SJohn Baldwin p = pfind(uap->pid); 193a70a2b74SJohn Baldwin if (p == NULL) 194a70a2b74SJohn Baldwin return (ESRCH); 195a70a2b74SJohn Baldwin error = p_cansee(td, p); 196a70a2b74SJohn Baldwin if (error) { 197a70a2b74SJohn Baldwin PROC_UNLOCK(p); 198a70a2b74SJohn Baldwin return (error); 199a70a2b74SJohn Baldwin } 200a70a2b74SJohn Baldwin } 201b40ce416SJulian Elischer td->td_retval[0] = p->p_session->s_sid; 202f591779bSSeigo Tanimura PROC_UNLOCK(p); 203a70a2b74SJohn Baldwin return (0); 2041a5018a0SPeter Wemm } 2051a5018a0SPeter Wemm 206d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 207ad7507e2SSteven Wallace struct getuid_args { 208ad7507e2SSteven Wallace int dummy; 209ad7507e2SSteven Wallace }; 210d2d3e875SBruce Evans #endif 211835a82eeSMatthew Dillon /* 212835a82eeSMatthew Dillon * MPSAFE 213835a82eeSMatthew Dillon */ 214df8bae1dSRodney W. Grimes /* ARGSUSED */ 21526f9a767SRodney W. Grimes int 2164c44ad8eSJohn Baldwin getuid(struct thread *td, struct getuid_args *uap) 217df8bae1dSRodney W. Grimes { 218df8bae1dSRodney W. Grimes 219d846883bSJohn Baldwin td->td_retval[0] = td->td_ucred->cr_ruid; 2201930e303SPoul-Henning Kamp #if defined(COMPAT_43) 221d846883bSJohn Baldwin td->td_retval[1] = td->td_ucred->cr_uid; 222df8bae1dSRodney W. Grimes #endif 223df8bae1dSRodney W. Grimes return (0); 224df8bae1dSRodney W. Grimes } 225df8bae1dSRodney W. Grimes 226d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 227ad7507e2SSteven Wallace struct geteuid_args { 228ad7507e2SSteven Wallace int dummy; 229ad7507e2SSteven Wallace }; 230d2d3e875SBruce Evans #endif 231eb725b4eSRobert Watson /* 232eb725b4eSRobert Watson * MPSAFE 233eb725b4eSRobert Watson */ 234df8bae1dSRodney W. Grimes /* ARGSUSED */ 23526f9a767SRodney W. Grimes int 2364c44ad8eSJohn Baldwin geteuid(struct thread *td, struct geteuid_args *uap) 237df8bae1dSRodney W. Grimes { 238d846883bSJohn Baldwin 239d846883bSJohn Baldwin td->td_retval[0] = td->td_ucred->cr_uid; 240df8bae1dSRodney W. Grimes return (0); 241df8bae1dSRodney W. Grimes } 242df8bae1dSRodney W. Grimes 243d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 244ad7507e2SSteven Wallace struct getgid_args { 245ad7507e2SSteven Wallace int dummy; 246ad7507e2SSteven Wallace }; 247d2d3e875SBruce Evans #endif 248835a82eeSMatthew Dillon /* 249835a82eeSMatthew Dillon * MPSAFE 250835a82eeSMatthew Dillon */ 251df8bae1dSRodney W. Grimes /* ARGSUSED */ 25226f9a767SRodney W. Grimes int 2534c44ad8eSJohn Baldwin getgid(struct thread *td, struct getgid_args *uap) 254df8bae1dSRodney W. Grimes { 255df8bae1dSRodney W. Grimes 256d846883bSJohn Baldwin td->td_retval[0] = td->td_ucred->cr_rgid; 2571930e303SPoul-Henning Kamp #if defined(COMPAT_43) 258d846883bSJohn Baldwin td->td_retval[1] = td->td_ucred->cr_groups[0]; 259df8bae1dSRodney W. Grimes #endif 260df8bae1dSRodney W. Grimes return (0); 261df8bae1dSRodney W. Grimes } 262df8bae1dSRodney W. Grimes 263df8bae1dSRodney W. Grimes /* 264df8bae1dSRodney W. Grimes * Get effective group ID. The "egid" is groups[0], and could be obtained 265df8bae1dSRodney W. Grimes * via getgroups. This syscall exists because it is somewhat painful to do 266df8bae1dSRodney W. Grimes * correctly in a library function. 267df8bae1dSRodney W. Grimes */ 268d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 269ad7507e2SSteven Wallace struct getegid_args { 270ad7507e2SSteven Wallace int dummy; 271ad7507e2SSteven Wallace }; 272d2d3e875SBruce Evans #endif 273835a82eeSMatthew Dillon /* 274835a82eeSMatthew Dillon * MPSAFE 275835a82eeSMatthew Dillon */ 276df8bae1dSRodney W. Grimes /* ARGSUSED */ 27726f9a767SRodney W. Grimes int 2784c44ad8eSJohn Baldwin getegid(struct thread *td, struct getegid_args *uap) 279df8bae1dSRodney W. Grimes { 280df8bae1dSRodney W. Grimes 281d846883bSJohn Baldwin td->td_retval[0] = td->td_ucred->cr_groups[0]; 282df8bae1dSRodney W. Grimes return (0); 283df8bae1dSRodney W. Grimes } 284df8bae1dSRodney W. Grimes 285d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 286df8bae1dSRodney W. Grimes struct getgroups_args { 287df8bae1dSRodney W. Grimes u_int gidsetsize; 288df8bae1dSRodney W. Grimes gid_t *gidset; 289df8bae1dSRodney W. Grimes }; 290d2d3e875SBruce Evans #endif 291835a82eeSMatthew Dillon /* 292835a82eeSMatthew Dillon * MPSAFE 293835a82eeSMatthew Dillon */ 29426f9a767SRodney W. Grimes int 2954c44ad8eSJohn Baldwin getgroups(struct thread *td, register struct getgroups_args *uap) 296df8bae1dSRodney W. Grimes { 297835a82eeSMatthew Dillon struct ucred *cred; 298b1fc0ec1SRobert Watson u_int ngrp; 299eb725b4eSRobert Watson int error; 300df8bae1dSRodney W. Grimes 301d846883bSJohn Baldwin cred = td->td_ucred; 302df8bae1dSRodney W. Grimes if ((ngrp = uap->gidsetsize) == 0) { 303b40ce416SJulian Elischer td->td_retval[0] = cred->cr_ngroups; 304d846883bSJohn Baldwin return (0); 305df8bae1dSRodney W. Grimes } 306d846883bSJohn Baldwin if (ngrp < cred->cr_ngroups) 307d846883bSJohn Baldwin return (EINVAL); 308b1fc0ec1SRobert Watson ngrp = cred->cr_ngroups; 3097f05b035SAlfred Perlstein error = copyout(cred->cr_groups, uap->gidset, ngrp * sizeof(gid_t)); 310d74ac681SMatthew Dillon if (error == 0) 311d846883bSJohn Baldwin td->td_retval[0] = ngrp; 312d74ac681SMatthew Dillon return (error); 313df8bae1dSRodney W. Grimes } 314df8bae1dSRodney W. Grimes 315d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 31682970b81SBruce Evans struct setsid_args { 317ad7507e2SSteven Wallace int dummy; 318ad7507e2SSteven Wallace }; 319d2d3e875SBruce Evans #endif 320835a82eeSMatthew Dillon /* 321835a82eeSMatthew Dillon * MPSAFE 322835a82eeSMatthew Dillon */ 323df8bae1dSRodney W. Grimes /* ARGSUSED */ 32426f9a767SRodney W. Grimes int 3254c44ad8eSJohn Baldwin setsid(register struct thread *td, struct setsid_args *uap) 326df8bae1dSRodney W. Grimes { 327f591779bSSeigo Tanimura struct pgrp *pgrp; 328835a82eeSMatthew Dillon int error; 329b40ce416SJulian Elischer struct proc *p = td->td_proc; 330f591779bSSeigo Tanimura struct pgrp *newpgrp; 331f591779bSSeigo Tanimura struct session *newsess; 332f591779bSSeigo Tanimura 333f591779bSSeigo Tanimura error = 0; 334f591779bSSeigo Tanimura pgrp = NULL; 335df8bae1dSRodney W. Grimes 336a163d034SWarner Losh MALLOC(newpgrp, struct pgrp *, sizeof(struct pgrp), M_PGRP, M_WAITOK | M_ZERO); 337a163d034SWarner Losh MALLOC(newsess, struct session *, sizeof(struct session), M_SESSION, M_WAITOK | M_ZERO); 338f591779bSSeigo Tanimura 339c8b1829dSJohn Baldwin sx_xlock(&proctree_lock); 340f591779bSSeigo Tanimura 341f591779bSSeigo Tanimura if (p->p_pgid == p->p_pid || (pgrp = pgfind(p->p_pid)) != NULL) { 342f591779bSSeigo Tanimura if (pgrp != NULL) 343f591779bSSeigo Tanimura PGRP_UNLOCK(pgrp); 344835a82eeSMatthew Dillon error = EPERM; 345f591779bSSeigo Tanimura } else { 346f591779bSSeigo Tanimura (void)enterpgrp(p, p->p_pid, newpgrp, newsess); 347b40ce416SJulian Elischer td->td_retval[0] = p->p_pid; 348c8b1829dSJohn Baldwin newpgrp = NULL; 349c8b1829dSJohn Baldwin newsess = NULL; 350df8bae1dSRodney W. Grimes } 351f591779bSSeigo Tanimura 352c8b1829dSJohn Baldwin sx_xunlock(&proctree_lock); 353f591779bSSeigo Tanimura 354c8b1829dSJohn Baldwin if (newpgrp != NULL) 355f591779bSSeigo Tanimura FREE(newpgrp, M_PGRP); 356c8b1829dSJohn Baldwin if (newsess != NULL) 357f591779bSSeigo Tanimura FREE(newsess, M_SESSION); 3581c2451c2SSeigo Tanimura 359c8b1829dSJohn Baldwin return (error); 360df8bae1dSRodney W. Grimes } 361df8bae1dSRodney W. Grimes 362df8bae1dSRodney W. Grimes /* 363df8bae1dSRodney W. Grimes * set process group (setpgid/old setpgrp) 364df8bae1dSRodney W. Grimes * 365df8bae1dSRodney W. Grimes * caller does setpgid(targpid, targpgid) 366df8bae1dSRodney W. Grimes * 367df8bae1dSRodney W. Grimes * pid must be caller or child of caller (ESRCH) 368df8bae1dSRodney W. Grimes * if a child 369df8bae1dSRodney W. Grimes * pid must be in same session (EPERM) 370df8bae1dSRodney W. Grimes * pid can't have done an exec (EACCES) 371df8bae1dSRodney W. Grimes * if pgid != pid 372df8bae1dSRodney W. Grimes * there must exist some pid in same session having pgid (EPERM) 373df8bae1dSRodney W. Grimes * pid must not be session leader (EPERM) 374df8bae1dSRodney W. Grimes */ 375d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 376df8bae1dSRodney W. Grimes struct setpgid_args { 377df8bae1dSRodney W. Grimes int pid; /* target process id */ 378df8bae1dSRodney W. Grimes int pgid; /* target pgrp id */ 379df8bae1dSRodney W. Grimes }; 380d2d3e875SBruce Evans #endif 381835a82eeSMatthew Dillon /* 382835a82eeSMatthew Dillon * MPSAFE 383835a82eeSMatthew Dillon */ 384df8bae1dSRodney W. Grimes /* ARGSUSED */ 38526f9a767SRodney W. Grimes int 3864c44ad8eSJohn Baldwin setpgid(struct thread *td, register struct setpgid_args *uap) 387df8bae1dSRodney W. Grimes { 388b40ce416SJulian Elischer struct proc *curp = td->td_proc; 389df8bae1dSRodney W. Grimes register struct proc *targp; /* target process */ 390df8bae1dSRodney W. Grimes register struct pgrp *pgrp; /* target pgrp */ 391eb9e5c1dSRobert Watson int error; 392f591779bSSeigo Tanimura struct pgrp *newpgrp; 393df8bae1dSRodney W. Grimes 39478f64bccSBruce Evans if (uap->pgid < 0) 39578f64bccSBruce Evans return (EINVAL); 396f591779bSSeigo Tanimura 397f591779bSSeigo Tanimura error = 0; 398f591779bSSeigo Tanimura 399a163d034SWarner Losh MALLOC(newpgrp, struct pgrp *, sizeof(struct pgrp), M_PGRP, M_WAITOK | M_ZERO); 400f591779bSSeigo Tanimura 401c8b1829dSJohn Baldwin sx_xlock(&proctree_lock); 402df8bae1dSRodney W. Grimes if (uap->pid != 0 && uap->pid != curp->p_pid) { 403f591779bSSeigo Tanimura if ((targp = pfind(uap->pid)) == NULL) { 404835a82eeSMatthew Dillon error = ESRCH; 405c8b1829dSJohn Baldwin goto done; 40633a9ed9dSJohn Baldwin } 407f591779bSSeigo Tanimura if (!inferior(targp)) { 408f591779bSSeigo Tanimura PROC_UNLOCK(targp); 4092f932587SSeigo Tanimura error = ESRCH; 410c8b1829dSJohn Baldwin goto done; 411f591779bSSeigo Tanimura } 412f44d9e24SJohn Baldwin if ((error = p_cansee(curthread, targp))) { 41333a9ed9dSJohn Baldwin PROC_UNLOCK(targp); 414c8b1829dSJohn Baldwin goto done; 41533a9ed9dSJohn Baldwin } 41633a9ed9dSJohn Baldwin if (targp->p_pgrp == NULL || 41733a9ed9dSJohn Baldwin targp->p_session != curp->p_session) { 41833a9ed9dSJohn Baldwin PROC_UNLOCK(targp); 419835a82eeSMatthew Dillon error = EPERM; 420c8b1829dSJohn Baldwin goto done; 42133a9ed9dSJohn Baldwin } 42233a9ed9dSJohn Baldwin if (targp->p_flag & P_EXEC) { 42333a9ed9dSJohn Baldwin PROC_UNLOCK(targp); 424835a82eeSMatthew Dillon error = EACCES; 425c8b1829dSJohn Baldwin goto done; 42633a9ed9dSJohn Baldwin } 42733a9ed9dSJohn Baldwin PROC_UNLOCK(targp); 428f591779bSSeigo Tanimura } else 429f591779bSSeigo Tanimura targp = curp; 430f591779bSSeigo Tanimura if (SESS_LEADER(targp)) { 431835a82eeSMatthew Dillon error = EPERM; 432c8b1829dSJohn Baldwin goto done; 43333a9ed9dSJohn Baldwin } 434eb725b4eSRobert Watson if (uap->pgid == 0) 435df8bae1dSRodney W. Grimes uap->pgid = targp->p_pid; 436a10d5f02SOlivier Houchard if ((pgrp = pgfind(uap->pgid)) == NULL) { 437f591779bSSeigo Tanimura if (uap->pgid == targp->p_pid) { 438a10d5f02SOlivier Houchard error = enterpgrp(targp, uap->pgid, newpgrp, 439a10d5f02SOlivier Houchard NULL); 440f591779bSSeigo Tanimura if (error == 0) 441f591779bSSeigo Tanimura newpgrp = NULL; 442a10d5f02SOlivier Houchard } else 443835a82eeSMatthew Dillon error = EPERM; 444a10d5f02SOlivier Houchard } else { 445f591779bSSeigo Tanimura if (pgrp == targp->p_pgrp) { 446f591779bSSeigo Tanimura PGRP_UNLOCK(pgrp); 447f591779bSSeigo Tanimura goto done; 44833a9ed9dSJohn Baldwin } 449a10d5f02SOlivier Houchard if (pgrp->pg_id != targp->p_pid && 450a10d5f02SOlivier Houchard pgrp->pg_session != curp->p_session) { 451a10d5f02SOlivier Houchard PGRP_UNLOCK(pgrp); 452a10d5f02SOlivier Houchard error = EPERM; 453a10d5f02SOlivier Houchard goto done; 454a10d5f02SOlivier Houchard } 455f591779bSSeigo Tanimura PGRP_UNLOCK(pgrp); 456f591779bSSeigo Tanimura error = enterthispgrp(targp, pgrp); 457f591779bSSeigo Tanimura } 458f591779bSSeigo Tanimura done: 459c8b1829dSJohn Baldwin sx_xunlock(&proctree_lock); 460c8b1829dSJohn Baldwin KASSERT((error == 0) || (newpgrp != NULL), 461c8b1829dSJohn Baldwin ("setpgid failed and newpgrp is NULL")); 4626041fa0aSSeigo Tanimura if (newpgrp != NULL) 463f591779bSSeigo Tanimura FREE(newpgrp, M_PGRP); 464835a82eeSMatthew Dillon return (error); 465df8bae1dSRodney W. Grimes } 466df8bae1dSRodney W. Grimes 467a08f4bf6SPeter Wemm /* 468a08f4bf6SPeter Wemm * Use the clause in B.4.2.2 that allows setuid/setgid to be 4.2/4.3BSD 4692fa72ea7SJeroen Ruigrok van der Werven * compatible. It says that setting the uid/gid to euid/egid is a special 470a08f4bf6SPeter Wemm * case of "appropriate privilege". Once the rules are expanded out, this 471a08f4bf6SPeter Wemm * basically means that setuid(nnn) sets all three id's, in all permitted 472a08f4bf6SPeter Wemm * cases unless _POSIX_SAVED_IDS is enabled. In that case, setuid(getuid()) 473a08f4bf6SPeter Wemm * does not set the saved id - this is dangerous for traditional BSD 474a08f4bf6SPeter Wemm * programs. For this reason, we *really* do not want to set 475a08f4bf6SPeter Wemm * _POSIX_SAVED_IDS and do not want to clear POSIX_APPENDIX_B_4_2_2. 476a08f4bf6SPeter Wemm */ 477a08f4bf6SPeter Wemm #define POSIX_APPENDIX_B_4_2_2 478a08f4bf6SPeter Wemm 479d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 480df8bae1dSRodney W. Grimes struct setuid_args { 481df8bae1dSRodney W. Grimes uid_t uid; 482df8bae1dSRodney W. Grimes }; 483d2d3e875SBruce Evans #endif 484835a82eeSMatthew Dillon /* 485835a82eeSMatthew Dillon * MPSAFE 486835a82eeSMatthew Dillon */ 487df8bae1dSRodney W. Grimes /* ARGSUSED */ 48826f9a767SRodney W. Grimes int 4894c44ad8eSJohn Baldwin setuid(struct thread *td, struct setuid_args *uap) 490df8bae1dSRodney W. Grimes { 491b40ce416SJulian Elischer struct proc *p = td->td_proc; 492b1fc0ec1SRobert Watson struct ucred *newcred, *oldcred; 493b1fc0ec1SRobert Watson uid_t uid; 4941419eacbSAlfred Perlstein struct uidinfo *uip; 495eb725b4eSRobert Watson int error; 496df8bae1dSRodney W. Grimes 49707f3485dSJohn Baldwin uid = uap->uid; 49807f3485dSJohn Baldwin newcred = crget(); 4991419eacbSAlfred Perlstein uip = uifind(uid); 50007f3485dSJohn Baldwin PROC_LOCK(p); 501f605567cSRobert Watson oldcred = p->p_ucred; 5025a92ee3cSRobert Watson 503a08f4bf6SPeter Wemm /* 504a08f4bf6SPeter Wemm * See if we have "permission" by POSIX 1003.1 rules. 505a08f4bf6SPeter Wemm * 506a08f4bf6SPeter Wemm * Note that setuid(geteuid()) is a special case of 507a08f4bf6SPeter Wemm * "appropriate privileges" in appendix B.4.2.2. We need 5082fa72ea7SJeroen Ruigrok van der Werven * to use this clause to be compatible with traditional BSD 509a08f4bf6SPeter Wemm * semantics. Basically, it means that "setuid(xx)" sets all 510a08f4bf6SPeter Wemm * three id's (assuming you have privs). 511a08f4bf6SPeter Wemm * 512a08f4bf6SPeter Wemm * Notes on the logic. We do things in three steps. 513a08f4bf6SPeter Wemm * 1: We determine if the euid is going to change, and do EPERM 514a08f4bf6SPeter Wemm * right away. We unconditionally change the euid later if this 515a08f4bf6SPeter Wemm * test is satisfied, simplifying that part of the logic. 516eb725b4eSRobert Watson * 2: We determine if the real and/or saved uids are going to 517a08f4bf6SPeter Wemm * change. Determined by compile options. 518a08f4bf6SPeter Wemm * 3: Change euid last. (after tests in #2 for "appropriate privs") 519a08f4bf6SPeter Wemm */ 520b1fc0ec1SRobert Watson if (uid != oldcred->cr_ruid && /* allow setuid(getuid()) */ 5213f246666SAndrey A. Chernov #ifdef _POSIX_SAVED_IDS 522b1fc0ec1SRobert Watson uid != oldcred->cr_svuid && /* allow setuid(saved gid) */ 523a08f4bf6SPeter Wemm #endif 524a08f4bf6SPeter Wemm #ifdef POSIX_APPENDIX_B_4_2_2 /* Use BSD-compat clause from B.4.2.2 */ 525b1fc0ec1SRobert Watson uid != oldcred->cr_uid && /* allow setuid(geteuid()) */ 5263f246666SAndrey A. Chernov #endif 52707f3485dSJohn Baldwin (error = suser_cred(oldcred, PRISON_ROOT)) != 0) { 52807f3485dSJohn Baldwin PROC_UNLOCK(p); 5291419eacbSAlfred Perlstein uifree(uip); 53007f3485dSJohn Baldwin crfree(newcred); 53107f3485dSJohn Baldwin return (error); 53207f3485dSJohn Baldwin } 533a08f4bf6SPeter Wemm 5341419eacbSAlfred Perlstein /* 5351419eacbSAlfred Perlstein * Copy credentials so other references do not see our changes. 5361419eacbSAlfred Perlstein */ 53707f3485dSJohn Baldwin crcopy(newcred, oldcred); 538a08f4bf6SPeter Wemm #ifdef _POSIX_SAVED_IDS 539df8bae1dSRodney W. Grimes /* 540a08f4bf6SPeter Wemm * Do we have "appropriate privileges" (are we root or uid == euid) 541a08f4bf6SPeter Wemm * If so, we are changing the real uid and/or saved uid. 542df8bae1dSRodney W. Grimes */ 5433f246666SAndrey A. Chernov if ( 544a08f4bf6SPeter Wemm #ifdef POSIX_APPENDIX_B_4_2_2 /* Use the clause from B.4.2.2 */ 545b1fc0ec1SRobert Watson uid == oldcred->cr_uid || 5463f246666SAndrey A. Chernov #endif 54744731cabSJohn Baldwin suser_cred(oldcred, PRISON_ROOT) == 0) /* we are using privs */ 548a08f4bf6SPeter Wemm #endif 549a08f4bf6SPeter Wemm { 550a08f4bf6SPeter Wemm /* 551f535380cSDon Lewis * Set the real uid and transfer proc count to new user. 552a08f4bf6SPeter Wemm */ 553b1fc0ec1SRobert Watson if (uid != oldcred->cr_ruid) { 5541419eacbSAlfred Perlstein change_ruid(newcred, uip); 555f535380cSDon Lewis setsugid(p); 556d3cdb93dSAndrey A. Chernov } 557a08f4bf6SPeter Wemm /* 558a08f4bf6SPeter Wemm * Set saved uid 559a08f4bf6SPeter Wemm * 560a08f4bf6SPeter Wemm * XXX always set saved uid even if not _POSIX_SAVED_IDS, as 561a08f4bf6SPeter Wemm * the security of seteuid() depends on it. B.4.2.2 says it 562a08f4bf6SPeter Wemm * is important that we should do this. 563a08f4bf6SPeter Wemm */ 564b1fc0ec1SRobert Watson if (uid != oldcred->cr_svuid) { 565b1fc0ec1SRobert Watson change_svuid(newcred, uid); 566d5f81602SSean Eric Fagan setsugid(p); 567a08f4bf6SPeter Wemm } 568a08f4bf6SPeter Wemm } 569a08f4bf6SPeter Wemm 570a08f4bf6SPeter Wemm /* 571a08f4bf6SPeter Wemm * In all permitted cases, we are changing the euid. 572a08f4bf6SPeter Wemm */ 573b1fc0ec1SRobert Watson if (uid != oldcred->cr_uid) { 5741419eacbSAlfred Perlstein change_euid(newcred, uip); 575d5f81602SSean Eric Fagan setsugid(p); 576a08f4bf6SPeter Wemm } 577b1fc0ec1SRobert Watson p->p_ucred = newcred; 57807f3485dSJohn Baldwin PROC_UNLOCK(p); 5791419eacbSAlfred Perlstein uifree(uip); 580b1fc0ec1SRobert Watson crfree(oldcred); 58107f3485dSJohn Baldwin return (0); 582df8bae1dSRodney W. Grimes } 583df8bae1dSRodney W. Grimes 584d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 585df8bae1dSRodney W. Grimes struct seteuid_args { 586df8bae1dSRodney W. Grimes uid_t euid; 587df8bae1dSRodney W. Grimes }; 588d2d3e875SBruce Evans #endif 589835a82eeSMatthew Dillon /* 590835a82eeSMatthew Dillon * MPSAFE 591835a82eeSMatthew Dillon */ 592df8bae1dSRodney W. Grimes /* ARGSUSED */ 59326f9a767SRodney W. Grimes int 5944c44ad8eSJohn Baldwin seteuid(struct thread *td, struct seteuid_args *uap) 595df8bae1dSRodney W. Grimes { 596b40ce416SJulian Elischer struct proc *p = td->td_proc; 597b1fc0ec1SRobert Watson struct ucred *newcred, *oldcred; 598b1fc0ec1SRobert Watson uid_t euid; 5991419eacbSAlfred Perlstein struct uidinfo *euip; 600eb725b4eSRobert Watson int error; 601df8bae1dSRodney W. Grimes 602df8bae1dSRodney W. Grimes euid = uap->euid; 60307f3485dSJohn Baldwin newcred = crget(); 6041419eacbSAlfred Perlstein euip = uifind(euid); 60507f3485dSJohn Baldwin PROC_LOCK(p); 606b1fc0ec1SRobert Watson oldcred = p->p_ucred; 607b1fc0ec1SRobert Watson if (euid != oldcred->cr_ruid && /* allow seteuid(getuid()) */ 608b1fc0ec1SRobert Watson euid != oldcred->cr_svuid && /* allow seteuid(saved uid) */ 60907f3485dSJohn Baldwin (error = suser_cred(oldcred, PRISON_ROOT)) != 0) { 61007f3485dSJohn Baldwin PROC_UNLOCK(p); 6111419eacbSAlfred Perlstein uifree(euip); 61207f3485dSJohn Baldwin crfree(newcred); 61307f3485dSJohn Baldwin return (error); 61407f3485dSJohn Baldwin } 615df8bae1dSRodney W. Grimes /* 616df8bae1dSRodney W. Grimes * Everything's okay, do it. Copy credentials so other references do 617df8bae1dSRodney W. Grimes * not see our changes. 618df8bae1dSRodney W. Grimes */ 61907f3485dSJohn Baldwin crcopy(newcred, oldcred); 620b1fc0ec1SRobert Watson if (oldcred->cr_uid != euid) { 6211419eacbSAlfred Perlstein change_euid(newcred, euip); 622d5f81602SSean Eric Fagan setsugid(p); 623229a15f0SPeter Wemm } 624b1fc0ec1SRobert Watson p->p_ucred = newcred; 62507f3485dSJohn Baldwin PROC_UNLOCK(p); 6261419eacbSAlfred Perlstein uifree(euip); 627b1fc0ec1SRobert Watson crfree(oldcred); 62807f3485dSJohn Baldwin return (0); 629df8bae1dSRodney W. Grimes } 630df8bae1dSRodney W. Grimes 631d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 632df8bae1dSRodney W. Grimes struct setgid_args { 633df8bae1dSRodney W. Grimes gid_t gid; 634df8bae1dSRodney W. Grimes }; 635d2d3e875SBruce Evans #endif 636835a82eeSMatthew Dillon /* 637835a82eeSMatthew Dillon * MPSAFE 638835a82eeSMatthew Dillon */ 639df8bae1dSRodney W. Grimes /* ARGSUSED */ 64026f9a767SRodney W. Grimes int 6414c44ad8eSJohn Baldwin setgid(struct thread *td, struct setgid_args *uap) 642df8bae1dSRodney W. Grimes { 643b40ce416SJulian Elischer struct proc *p = td->td_proc; 644b1fc0ec1SRobert Watson struct ucred *newcred, *oldcred; 645b1fc0ec1SRobert Watson gid_t gid; 646eb725b4eSRobert Watson int error; 647df8bae1dSRodney W. Grimes 648b1fc0ec1SRobert Watson gid = uap->gid; 64907f3485dSJohn Baldwin newcred = crget(); 65007f3485dSJohn Baldwin PROC_LOCK(p); 651b1fc0ec1SRobert Watson oldcred = p->p_ucred; 6525a92ee3cSRobert Watson 653a08f4bf6SPeter Wemm /* 654a08f4bf6SPeter Wemm * See if we have "permission" by POSIX 1003.1 rules. 655a08f4bf6SPeter Wemm * 656a08f4bf6SPeter Wemm * Note that setgid(getegid()) is a special case of 657a08f4bf6SPeter Wemm * "appropriate privileges" in appendix B.4.2.2. We need 6582fa72ea7SJeroen Ruigrok van der Werven * to use this clause to be compatible with traditional BSD 659a08f4bf6SPeter Wemm * semantics. Basically, it means that "setgid(xx)" sets all 660a08f4bf6SPeter Wemm * three id's (assuming you have privs). 661a08f4bf6SPeter Wemm * 662a08f4bf6SPeter Wemm * For notes on the logic here, see setuid() above. 663a08f4bf6SPeter Wemm */ 664b1fc0ec1SRobert Watson if (gid != oldcred->cr_rgid && /* allow setgid(getgid()) */ 6653f246666SAndrey A. Chernov #ifdef _POSIX_SAVED_IDS 666b1fc0ec1SRobert Watson gid != oldcred->cr_svgid && /* allow setgid(saved gid) */ 667a08f4bf6SPeter Wemm #endif 668a08f4bf6SPeter Wemm #ifdef POSIX_APPENDIX_B_4_2_2 /* Use BSD-compat clause from B.4.2.2 */ 669b1fc0ec1SRobert Watson gid != oldcred->cr_groups[0] && /* allow setgid(getegid()) */ 6703f246666SAndrey A. Chernov #endif 67107f3485dSJohn Baldwin (error = suser_cred(oldcred, PRISON_ROOT)) != 0) { 67207f3485dSJohn Baldwin PROC_UNLOCK(p); 67307f3485dSJohn Baldwin crfree(newcred); 67407f3485dSJohn Baldwin return (error); 67507f3485dSJohn Baldwin } 676a08f4bf6SPeter Wemm 67707f3485dSJohn Baldwin crcopy(newcred, oldcred); 678a08f4bf6SPeter Wemm #ifdef _POSIX_SAVED_IDS 679a08f4bf6SPeter Wemm /* 680a08f4bf6SPeter Wemm * Do we have "appropriate privileges" (are we root or gid == egid) 681a08f4bf6SPeter Wemm * If so, we are changing the real uid and saved gid. 682a08f4bf6SPeter Wemm */ 683a08f4bf6SPeter Wemm if ( 684a08f4bf6SPeter Wemm #ifdef POSIX_APPENDIX_B_4_2_2 /* use the clause from B.4.2.2 */ 685b1fc0ec1SRobert Watson gid == oldcred->cr_groups[0] || 686a08f4bf6SPeter Wemm #endif 68744731cabSJohn Baldwin suser_cred(oldcred, PRISON_ROOT) == 0) /* we are using privs */ 688a08f4bf6SPeter Wemm #endif 689a08f4bf6SPeter Wemm { 690a08f4bf6SPeter Wemm /* 691a08f4bf6SPeter Wemm * Set real gid 692a08f4bf6SPeter Wemm */ 693b1fc0ec1SRobert Watson if (oldcred->cr_rgid != gid) { 694b1fc0ec1SRobert Watson change_rgid(newcred, gid); 695d5f81602SSean Eric Fagan setsugid(p); 696a08f4bf6SPeter Wemm } 697a08f4bf6SPeter Wemm /* 698a08f4bf6SPeter Wemm * Set saved gid 699a08f4bf6SPeter Wemm * 700a08f4bf6SPeter Wemm * XXX always set saved gid even if not _POSIX_SAVED_IDS, as 701a08f4bf6SPeter Wemm * the security of setegid() depends on it. B.4.2.2 says it 702a08f4bf6SPeter Wemm * is important that we should do this. 703a08f4bf6SPeter Wemm */ 704b1fc0ec1SRobert Watson if (oldcred->cr_svgid != gid) { 705b1fc0ec1SRobert Watson change_svgid(newcred, gid); 706d5f81602SSean Eric Fagan setsugid(p); 707a08f4bf6SPeter Wemm } 708a08f4bf6SPeter Wemm } 709a08f4bf6SPeter Wemm /* 710a08f4bf6SPeter Wemm * In all cases permitted cases, we are changing the egid. 711a08f4bf6SPeter Wemm * Copy credentials so other references do not see our changes. 712a08f4bf6SPeter Wemm */ 713b1fc0ec1SRobert Watson if (oldcred->cr_groups[0] != gid) { 714b1fc0ec1SRobert Watson change_egid(newcred, gid); 715d5f81602SSean Eric Fagan setsugid(p); 716a08f4bf6SPeter Wemm } 717b1fc0ec1SRobert Watson p->p_ucred = newcred; 71807f3485dSJohn Baldwin PROC_UNLOCK(p); 719b1fc0ec1SRobert Watson crfree(oldcred); 72007f3485dSJohn Baldwin return (0); 721df8bae1dSRodney W. Grimes } 722df8bae1dSRodney W. Grimes 723d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 724df8bae1dSRodney W. Grimes struct setegid_args { 725df8bae1dSRodney W. Grimes gid_t egid; 726df8bae1dSRodney W. Grimes }; 727d2d3e875SBruce Evans #endif 728835a82eeSMatthew Dillon /* 729835a82eeSMatthew Dillon * MPSAFE 730835a82eeSMatthew Dillon */ 731df8bae1dSRodney W. Grimes /* ARGSUSED */ 73226f9a767SRodney W. Grimes int 7334c44ad8eSJohn Baldwin setegid(struct thread *td, struct setegid_args *uap) 734df8bae1dSRodney W. Grimes { 735b40ce416SJulian Elischer struct proc *p = td->td_proc; 736b1fc0ec1SRobert Watson struct ucred *newcred, *oldcred; 737b1fc0ec1SRobert Watson gid_t egid; 738eb725b4eSRobert Watson int error; 739df8bae1dSRodney W. Grimes 740df8bae1dSRodney W. Grimes egid = uap->egid; 74107f3485dSJohn Baldwin newcred = crget(); 74207f3485dSJohn Baldwin PROC_LOCK(p); 743b1fc0ec1SRobert Watson oldcred = p->p_ucred; 744b1fc0ec1SRobert Watson if (egid != oldcred->cr_rgid && /* allow setegid(getgid()) */ 745b1fc0ec1SRobert Watson egid != oldcred->cr_svgid && /* allow setegid(saved gid) */ 74607f3485dSJohn Baldwin (error = suser_cred(oldcred, PRISON_ROOT)) != 0) { 74707f3485dSJohn Baldwin PROC_UNLOCK(p); 74807f3485dSJohn Baldwin crfree(newcred); 74907f3485dSJohn Baldwin return (error); 75007f3485dSJohn Baldwin } 75107f3485dSJohn Baldwin crcopy(newcred, oldcred); 752b1fc0ec1SRobert Watson if (oldcred->cr_groups[0] != egid) { 753b1fc0ec1SRobert Watson change_egid(newcred, egid); 754d5f81602SSean Eric Fagan setsugid(p); 755229a15f0SPeter Wemm } 756b1fc0ec1SRobert Watson p->p_ucred = newcred; 75707f3485dSJohn Baldwin PROC_UNLOCK(p); 758b1fc0ec1SRobert Watson crfree(oldcred); 75907f3485dSJohn Baldwin return (0); 760df8bae1dSRodney W. Grimes } 761df8bae1dSRodney W. Grimes 762d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 763df8bae1dSRodney W. Grimes struct setgroups_args { 764df8bae1dSRodney W. Grimes u_int gidsetsize; 765df8bae1dSRodney W. Grimes gid_t *gidset; 766df8bae1dSRodney W. Grimes }; 767d2d3e875SBruce Evans #endif 768835a82eeSMatthew Dillon /* 769835a82eeSMatthew Dillon * MPSAFE 770835a82eeSMatthew Dillon */ 771df8bae1dSRodney W. Grimes /* ARGSUSED */ 77226f9a767SRodney W. Grimes int 7734c44ad8eSJohn Baldwin setgroups(struct thread *td, struct setgroups_args *uap) 774df8bae1dSRodney W. Grimes { 775b40ce416SJulian Elischer struct proc *p = td->td_proc; 77607f3485dSJohn Baldwin struct ucred *newcred, *tempcred, *oldcred; 777b1fc0ec1SRobert Watson u_int ngrp; 778df8bae1dSRodney W. Grimes int error; 779df8bae1dSRodney W. Grimes 7803956a170SDavid Greenman ngrp = uap->gidsetsize; 78107f3485dSJohn Baldwin if (ngrp > NGROUPS) 78207f3485dSJohn Baldwin return (EINVAL); 78307f3485dSJohn Baldwin tempcred = crget(); 7847f05b035SAlfred Perlstein error = copyin(uap->gidset, tempcred->cr_groups, ngrp * sizeof(gid_t)); 78507f3485dSJohn Baldwin if (error != 0) { 78607f3485dSJohn Baldwin crfree(tempcred); 78707f3485dSJohn Baldwin return (error); 788835a82eeSMatthew Dillon } 78907f3485dSJohn Baldwin newcred = crget(); 79007f3485dSJohn Baldwin PROC_LOCK(p); 79107f3485dSJohn Baldwin oldcred = p->p_ucred; 79207f3485dSJohn Baldwin error = suser_cred(oldcred, PRISON_ROOT); 79307f3485dSJohn Baldwin if (error) { 79407f3485dSJohn Baldwin PROC_UNLOCK(p); 79507f3485dSJohn Baldwin crfree(newcred); 79607f3485dSJohn Baldwin crfree(tempcred); 79707f3485dSJohn Baldwin return (error); 79807f3485dSJohn Baldwin } 79907f3485dSJohn Baldwin 8008a5d815aSPeter Wemm /* 8018a5d815aSPeter Wemm * XXX A little bit lazy here. We could test if anything has 8028a5d815aSPeter Wemm * changed before crcopy() and setting P_SUGID. 8038a5d815aSPeter Wemm */ 80407f3485dSJohn Baldwin crcopy(newcred, oldcred); 8058a5d815aSPeter Wemm if (ngrp < 1) { 8068a5d815aSPeter Wemm /* 8078a5d815aSPeter Wemm * setgroups(0, NULL) is a legitimate way of clearing the 8088a5d815aSPeter Wemm * groups vector on non-BSD systems (which generally do not 8098a5d815aSPeter Wemm * have the egid in the groups[0]). We risk security holes 8108a5d815aSPeter Wemm * when running non-BSD software if we do not do the same. 8118a5d815aSPeter Wemm */ 812b1fc0ec1SRobert Watson newcred->cr_ngroups = 1; 8138a5d815aSPeter Wemm } else { 81407f3485dSJohn Baldwin bcopy(tempcred->cr_groups, newcred->cr_groups, 81507f3485dSJohn Baldwin ngrp * sizeof(gid_t)); 816b1fc0ec1SRobert Watson newcred->cr_ngroups = ngrp; 8178a5d815aSPeter Wemm } 818d5f81602SSean Eric Fagan setsugid(p); 819b1fc0ec1SRobert Watson p->p_ucred = newcred; 82007f3485dSJohn Baldwin PROC_UNLOCK(p); 82107f3485dSJohn Baldwin crfree(tempcred); 822b1fc0ec1SRobert Watson crfree(oldcred); 82307f3485dSJohn Baldwin return (0); 824df8bae1dSRodney W. Grimes } 825df8bae1dSRodney W. Grimes 826d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 827df8bae1dSRodney W. Grimes struct setreuid_args { 82800999cd6SAndrey A. Chernov uid_t ruid; 82900999cd6SAndrey A. Chernov uid_t euid; 830df8bae1dSRodney W. Grimes }; 831d2d3e875SBruce Evans #endif 832835a82eeSMatthew Dillon /* 833835a82eeSMatthew Dillon * MPSAFE 834835a82eeSMatthew Dillon */ 835df8bae1dSRodney W. Grimes /* ARGSUSED */ 83626f9a767SRodney W. Grimes int 8374c44ad8eSJohn Baldwin setreuid(register struct thread *td, struct setreuid_args *uap) 838df8bae1dSRodney W. Grimes { 839b40ce416SJulian Elischer struct proc *p = td->td_proc; 840b1fc0ec1SRobert Watson struct ucred *newcred, *oldcred; 841eb725b4eSRobert Watson uid_t euid, ruid; 8421419eacbSAlfred Perlstein struct uidinfo *euip, *ruip; 843eb725b4eSRobert Watson int error; 844df8bae1dSRodney W. Grimes 84500999cd6SAndrey A. Chernov euid = uap->euid; 846eb725b4eSRobert Watson ruid = uap->ruid; 84707f3485dSJohn Baldwin newcred = crget(); 8481419eacbSAlfred Perlstein euip = uifind(euid); 8491419eacbSAlfred Perlstein ruip = uifind(ruid); 85007f3485dSJohn Baldwin PROC_LOCK(p); 851b1fc0ec1SRobert Watson oldcred = p->p_ucred; 852b1fc0ec1SRobert Watson if (((ruid != (uid_t)-1 && ruid != oldcred->cr_ruid && 853b1fc0ec1SRobert Watson ruid != oldcred->cr_svuid) || 854b1fc0ec1SRobert Watson (euid != (uid_t)-1 && euid != oldcred->cr_uid && 855b1fc0ec1SRobert Watson euid != oldcred->cr_ruid && euid != oldcred->cr_svuid)) && 85607f3485dSJohn Baldwin (error = suser_cred(oldcred, PRISON_ROOT)) != 0) { 85707f3485dSJohn Baldwin PROC_UNLOCK(p); 8581419eacbSAlfred Perlstein uifree(ruip); 8591419eacbSAlfred Perlstein uifree(euip); 86007f3485dSJohn Baldwin crfree(newcred); 86107f3485dSJohn Baldwin return (error); 86207f3485dSJohn Baldwin } 86307f3485dSJohn Baldwin crcopy(newcred, oldcred); 864b1fc0ec1SRobert Watson if (euid != (uid_t)-1 && oldcred->cr_uid != euid) { 8651419eacbSAlfred Perlstein change_euid(newcred, euip); 866d5f81602SSean Eric Fagan setsugid(p); 867a89a5370SPeter Wemm } 868b1fc0ec1SRobert Watson if (ruid != (uid_t)-1 && oldcred->cr_ruid != ruid) { 8691419eacbSAlfred Perlstein change_ruid(newcred, ruip); 870d5f81602SSean Eric Fagan setsugid(p); 87100999cd6SAndrey A. Chernov } 872b1fc0ec1SRobert Watson if ((ruid != (uid_t)-1 || newcred->cr_uid != newcred->cr_ruid) && 873b1fc0ec1SRobert Watson newcred->cr_svuid != newcred->cr_uid) { 874b1fc0ec1SRobert Watson change_svuid(newcred, newcred->cr_uid); 875d5f81602SSean Eric Fagan setsugid(p); 876a89a5370SPeter Wemm } 877b1fc0ec1SRobert Watson p->p_ucred = newcred; 87807f3485dSJohn Baldwin PROC_UNLOCK(p); 8791419eacbSAlfred Perlstein uifree(ruip); 8801419eacbSAlfred Perlstein uifree(euip); 881b1fc0ec1SRobert Watson crfree(oldcred); 88207f3485dSJohn Baldwin return (0); 883df8bae1dSRodney W. Grimes } 884df8bae1dSRodney W. Grimes 885d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 886df8bae1dSRodney W. Grimes struct setregid_args { 88700999cd6SAndrey A. Chernov gid_t rgid; 88800999cd6SAndrey A. Chernov gid_t egid; 889df8bae1dSRodney W. Grimes }; 890d2d3e875SBruce Evans #endif 891835a82eeSMatthew Dillon /* 892835a82eeSMatthew Dillon * MPSAFE 893835a82eeSMatthew Dillon */ 894df8bae1dSRodney W. Grimes /* ARGSUSED */ 89526f9a767SRodney W. Grimes int 8964c44ad8eSJohn Baldwin setregid(register struct thread *td, struct setregid_args *uap) 897df8bae1dSRodney W. Grimes { 898b40ce416SJulian Elischer struct proc *p = td->td_proc; 899b1fc0ec1SRobert Watson struct ucred *newcred, *oldcred; 900eb725b4eSRobert Watson gid_t egid, rgid; 901eb725b4eSRobert Watson int error; 902df8bae1dSRodney W. Grimes 90300999cd6SAndrey A. Chernov egid = uap->egid; 904eb725b4eSRobert Watson rgid = uap->rgid; 90507f3485dSJohn Baldwin newcred = crget(); 90607f3485dSJohn Baldwin PROC_LOCK(p); 907b1fc0ec1SRobert Watson oldcred = p->p_ucred; 908b1fc0ec1SRobert Watson if (((rgid != (gid_t)-1 && rgid != oldcred->cr_rgid && 909b1fc0ec1SRobert Watson rgid != oldcred->cr_svgid) || 910b1fc0ec1SRobert Watson (egid != (gid_t)-1 && egid != oldcred->cr_groups[0] && 911b1fc0ec1SRobert Watson egid != oldcred->cr_rgid && egid != oldcred->cr_svgid)) && 91207f3485dSJohn Baldwin (error = suser_cred(oldcred, PRISON_ROOT)) != 0) { 91307f3485dSJohn Baldwin PROC_UNLOCK(p); 91407f3485dSJohn Baldwin crfree(newcred); 91507f3485dSJohn Baldwin return (error); 91607f3485dSJohn Baldwin } 91707f3485dSJohn Baldwin 91807f3485dSJohn Baldwin crcopy(newcred, oldcred); 919b1fc0ec1SRobert Watson if (egid != (gid_t)-1 && oldcred->cr_groups[0] != egid) { 920b1fc0ec1SRobert Watson change_egid(newcred, egid); 921d5f81602SSean Eric Fagan setsugid(p); 922a89a5370SPeter Wemm } 923b1fc0ec1SRobert Watson if (rgid != (gid_t)-1 && oldcred->cr_rgid != rgid) { 924b1fc0ec1SRobert Watson change_rgid(newcred, rgid); 925d5f81602SSean Eric Fagan setsugid(p); 926a89a5370SPeter Wemm } 927b1fc0ec1SRobert Watson if ((rgid != (gid_t)-1 || newcred->cr_groups[0] != newcred->cr_rgid) && 928b1fc0ec1SRobert Watson newcred->cr_svgid != newcred->cr_groups[0]) { 929b1fc0ec1SRobert Watson change_svgid(newcred, newcred->cr_groups[0]); 930d5f81602SSean Eric Fagan setsugid(p); 931a89a5370SPeter Wemm } 9324589be70SRuslan Ermilov p->p_ucred = newcred; 93307f3485dSJohn Baldwin PROC_UNLOCK(p); 9344589be70SRuslan Ermilov crfree(oldcred); 93507f3485dSJohn Baldwin return (0); 936df8bae1dSRodney W. Grimes } 937df8bae1dSRodney W. Grimes 9388ccd6334SPeter Wemm /* 9398ccd6334SPeter Wemm * setresuid(ruid, euid, suid) is like setreuid except control over the 9408ccd6334SPeter Wemm * saved uid is explicit. 9418ccd6334SPeter Wemm */ 9428ccd6334SPeter Wemm 9438ccd6334SPeter Wemm #ifndef _SYS_SYSPROTO_H_ 9448ccd6334SPeter Wemm struct setresuid_args { 9458ccd6334SPeter Wemm uid_t ruid; 9468ccd6334SPeter Wemm uid_t euid; 9478ccd6334SPeter Wemm uid_t suid; 9488ccd6334SPeter Wemm }; 9498ccd6334SPeter Wemm #endif 950835a82eeSMatthew Dillon /* 951835a82eeSMatthew Dillon * MPSAFE 952835a82eeSMatthew Dillon */ 9538ccd6334SPeter Wemm /* ARGSUSED */ 9548ccd6334SPeter Wemm int 9554c44ad8eSJohn Baldwin setresuid(register struct thread *td, struct setresuid_args *uap) 9568ccd6334SPeter Wemm { 957b40ce416SJulian Elischer struct proc *p = td->td_proc; 958b1fc0ec1SRobert Watson struct ucred *newcred, *oldcred; 959eb725b4eSRobert Watson uid_t euid, ruid, suid; 9601419eacbSAlfred Perlstein struct uidinfo *euip, *ruip; 9618ccd6334SPeter Wemm int error; 9628ccd6334SPeter Wemm 9638ccd6334SPeter Wemm euid = uap->euid; 964eb725b4eSRobert Watson ruid = uap->ruid; 9658ccd6334SPeter Wemm suid = uap->suid; 96607f3485dSJohn Baldwin newcred = crget(); 9671419eacbSAlfred Perlstein euip = uifind(euid); 9681419eacbSAlfred Perlstein ruip = uifind(ruid); 96907f3485dSJohn Baldwin PROC_LOCK(p); 970b1fc0ec1SRobert Watson oldcred = p->p_ucred; 971b1fc0ec1SRobert Watson if (((ruid != (uid_t)-1 && ruid != oldcred->cr_ruid && 972b1fc0ec1SRobert Watson ruid != oldcred->cr_svuid && 973b1fc0ec1SRobert Watson ruid != oldcred->cr_uid) || 974b1fc0ec1SRobert Watson (euid != (uid_t)-1 && euid != oldcred->cr_ruid && 975b1fc0ec1SRobert Watson euid != oldcred->cr_svuid && 976b1fc0ec1SRobert Watson euid != oldcred->cr_uid) || 977b1fc0ec1SRobert Watson (suid != (uid_t)-1 && suid != oldcred->cr_ruid && 978b1fc0ec1SRobert Watson suid != oldcred->cr_svuid && 979b1fc0ec1SRobert Watson suid != oldcred->cr_uid)) && 98007f3485dSJohn Baldwin (error = suser_cred(oldcred, PRISON_ROOT)) != 0) { 98107f3485dSJohn Baldwin PROC_UNLOCK(p); 9821419eacbSAlfred Perlstein uifree(ruip); 9831419eacbSAlfred Perlstein uifree(euip); 98407f3485dSJohn Baldwin crfree(newcred); 98507f3485dSJohn Baldwin return (error); 98607f3485dSJohn Baldwin } 98707f3485dSJohn Baldwin 98807f3485dSJohn Baldwin crcopy(newcred, oldcred); 989b1fc0ec1SRobert Watson if (euid != (uid_t)-1 && oldcred->cr_uid != euid) { 9901419eacbSAlfred Perlstein change_euid(newcred, euip); 9918ccd6334SPeter Wemm setsugid(p); 9928ccd6334SPeter Wemm } 993b1fc0ec1SRobert Watson if (ruid != (uid_t)-1 && oldcred->cr_ruid != ruid) { 9941419eacbSAlfred Perlstein change_ruid(newcred, ruip); 9958ccd6334SPeter Wemm setsugid(p); 9968ccd6334SPeter Wemm } 997b1fc0ec1SRobert Watson if (suid != (uid_t)-1 && oldcred->cr_svuid != suid) { 998b1fc0ec1SRobert Watson change_svuid(newcred, suid); 9998ccd6334SPeter Wemm setsugid(p); 10008ccd6334SPeter Wemm } 1001b1fc0ec1SRobert Watson p->p_ucred = newcred; 100207f3485dSJohn Baldwin PROC_UNLOCK(p); 10031419eacbSAlfred Perlstein uifree(ruip); 10041419eacbSAlfred Perlstein uifree(euip); 1005b1fc0ec1SRobert Watson crfree(oldcred); 100607f3485dSJohn Baldwin return (0); 10078ccd6334SPeter Wemm } 10088ccd6334SPeter Wemm 10098ccd6334SPeter Wemm /* 10108ccd6334SPeter Wemm * setresgid(rgid, egid, sgid) is like setregid except control over the 10118ccd6334SPeter Wemm * saved gid is explicit. 10128ccd6334SPeter Wemm */ 10138ccd6334SPeter Wemm 10148ccd6334SPeter Wemm #ifndef _SYS_SYSPROTO_H_ 10158ccd6334SPeter Wemm struct setresgid_args { 10168ccd6334SPeter Wemm gid_t rgid; 10178ccd6334SPeter Wemm gid_t egid; 10188ccd6334SPeter Wemm gid_t sgid; 10198ccd6334SPeter Wemm }; 10208ccd6334SPeter Wemm #endif 1021835a82eeSMatthew Dillon /* 1022835a82eeSMatthew Dillon * MPSAFE 1023835a82eeSMatthew Dillon */ 10248ccd6334SPeter Wemm /* ARGSUSED */ 10258ccd6334SPeter Wemm int 10264c44ad8eSJohn Baldwin setresgid(register struct thread *td, struct setresgid_args *uap) 10278ccd6334SPeter Wemm { 1028b40ce416SJulian Elischer struct proc *p = td->td_proc; 1029b1fc0ec1SRobert Watson struct ucred *newcred, *oldcred; 1030eb725b4eSRobert Watson gid_t egid, rgid, sgid; 10318ccd6334SPeter Wemm int error; 10328ccd6334SPeter Wemm 10338ccd6334SPeter Wemm egid = uap->egid; 1034eb725b4eSRobert Watson rgid = uap->rgid; 10358ccd6334SPeter Wemm sgid = uap->sgid; 103607f3485dSJohn Baldwin newcred = crget(); 103707f3485dSJohn Baldwin PROC_LOCK(p); 1038b1fc0ec1SRobert Watson oldcred = p->p_ucred; 1039b1fc0ec1SRobert Watson if (((rgid != (gid_t)-1 && rgid != oldcred->cr_rgid && 1040b1fc0ec1SRobert Watson rgid != oldcred->cr_svgid && 1041b1fc0ec1SRobert Watson rgid != oldcred->cr_groups[0]) || 1042b1fc0ec1SRobert Watson (egid != (gid_t)-1 && egid != oldcred->cr_rgid && 1043b1fc0ec1SRobert Watson egid != oldcred->cr_svgid && 1044b1fc0ec1SRobert Watson egid != oldcred->cr_groups[0]) || 1045b1fc0ec1SRobert Watson (sgid != (gid_t)-1 && sgid != oldcred->cr_rgid && 1046b1fc0ec1SRobert Watson sgid != oldcred->cr_svgid && 1047b1fc0ec1SRobert Watson sgid != oldcred->cr_groups[0])) && 104807f3485dSJohn Baldwin (error = suser_cred(oldcred, PRISON_ROOT)) != 0) { 104907f3485dSJohn Baldwin PROC_UNLOCK(p); 105007f3485dSJohn Baldwin crfree(newcred); 105107f3485dSJohn Baldwin return (error); 105207f3485dSJohn Baldwin } 105307f3485dSJohn Baldwin 105407f3485dSJohn Baldwin crcopy(newcred, oldcred); 1055b1fc0ec1SRobert Watson if (egid != (gid_t)-1 && oldcred->cr_groups[0] != egid) { 1056b1fc0ec1SRobert Watson change_egid(newcred, egid); 10578ccd6334SPeter Wemm setsugid(p); 10588ccd6334SPeter Wemm } 1059b1fc0ec1SRobert Watson if (rgid != (gid_t)-1 && oldcred->cr_rgid != rgid) { 1060b1fc0ec1SRobert Watson change_rgid(newcred, rgid); 10618ccd6334SPeter Wemm setsugid(p); 10628ccd6334SPeter Wemm } 1063b1fc0ec1SRobert Watson if (sgid != (gid_t)-1 && oldcred->cr_svgid != sgid) { 1064b1fc0ec1SRobert Watson change_svgid(newcred, sgid); 10658ccd6334SPeter Wemm setsugid(p); 10668ccd6334SPeter Wemm } 1067b1fc0ec1SRobert Watson p->p_ucred = newcred; 106807f3485dSJohn Baldwin PROC_UNLOCK(p); 1069b1fc0ec1SRobert Watson crfree(oldcred); 107007f3485dSJohn Baldwin return (0); 10718ccd6334SPeter Wemm } 10728ccd6334SPeter Wemm 10738ccd6334SPeter Wemm #ifndef _SYS_SYSPROTO_H_ 10748ccd6334SPeter Wemm struct getresuid_args { 10758ccd6334SPeter Wemm uid_t *ruid; 10768ccd6334SPeter Wemm uid_t *euid; 10778ccd6334SPeter Wemm uid_t *suid; 10788ccd6334SPeter Wemm }; 10798ccd6334SPeter Wemm #endif 1080835a82eeSMatthew Dillon /* 1081835a82eeSMatthew Dillon * MPSAFE 1082835a82eeSMatthew Dillon */ 10838ccd6334SPeter Wemm /* ARGSUSED */ 10848ccd6334SPeter Wemm int 10854c44ad8eSJohn Baldwin getresuid(register struct thread *td, struct getresuid_args *uap) 10868ccd6334SPeter Wemm { 1087835a82eeSMatthew Dillon struct ucred *cred; 10888ccd6334SPeter Wemm int error1 = 0, error2 = 0, error3 = 0; 10898ccd6334SPeter Wemm 1090d74ac681SMatthew Dillon cred = td->td_ucred; 10918ccd6334SPeter Wemm if (uap->ruid) 10927f05b035SAlfred Perlstein error1 = copyout(&cred->cr_ruid, 10937f05b035SAlfred Perlstein uap->ruid, sizeof(cred->cr_ruid)); 10948ccd6334SPeter Wemm if (uap->euid) 10957f05b035SAlfred Perlstein error2 = copyout(&cred->cr_uid, 10967f05b035SAlfred Perlstein uap->euid, sizeof(cred->cr_uid)); 10978ccd6334SPeter Wemm if (uap->suid) 10987f05b035SAlfred Perlstein error3 = copyout(&cred->cr_svuid, 10997f05b035SAlfred Perlstein uap->suid, sizeof(cred->cr_svuid)); 1100eb725b4eSRobert Watson return (error1 ? error1 : error2 ? error2 : error3); 11018ccd6334SPeter Wemm } 11028ccd6334SPeter Wemm 11038ccd6334SPeter Wemm #ifndef _SYS_SYSPROTO_H_ 11048ccd6334SPeter Wemm struct getresgid_args { 11058ccd6334SPeter Wemm gid_t *rgid; 11068ccd6334SPeter Wemm gid_t *egid; 11078ccd6334SPeter Wemm gid_t *sgid; 11088ccd6334SPeter Wemm }; 11098ccd6334SPeter Wemm #endif 1110835a82eeSMatthew Dillon /* 1111835a82eeSMatthew Dillon * MPSAFE 1112835a82eeSMatthew Dillon */ 11138ccd6334SPeter Wemm /* ARGSUSED */ 11148ccd6334SPeter Wemm int 11154c44ad8eSJohn Baldwin getresgid(register struct thread *td, struct getresgid_args *uap) 11168ccd6334SPeter Wemm { 1117835a82eeSMatthew Dillon struct ucred *cred; 11188ccd6334SPeter Wemm int error1 = 0, error2 = 0, error3 = 0; 11198ccd6334SPeter Wemm 1120d74ac681SMatthew Dillon cred = td->td_ucred; 11218ccd6334SPeter Wemm if (uap->rgid) 11227f05b035SAlfred Perlstein error1 = copyout(&cred->cr_rgid, 11237f05b035SAlfred Perlstein uap->rgid, sizeof(cred->cr_rgid)); 11248ccd6334SPeter Wemm if (uap->egid) 11257f05b035SAlfred Perlstein error2 = copyout(&cred->cr_groups[0], 11267f05b035SAlfred Perlstein uap->egid, sizeof(cred->cr_groups[0])); 11278ccd6334SPeter Wemm if (uap->sgid) 11287f05b035SAlfred Perlstein error3 = copyout(&cred->cr_svgid, 11297f05b035SAlfred Perlstein uap->sgid, sizeof(cred->cr_svgid)); 1130eb725b4eSRobert Watson return (error1 ? error1 : error2 ? error2 : error3); 11318ccd6334SPeter Wemm } 11328ccd6334SPeter Wemm 1133b67cbc65SPeter Wemm #ifndef _SYS_SYSPROTO_H_ 1134b67cbc65SPeter Wemm struct issetugid_args { 1135b67cbc65SPeter Wemm int dummy; 1136b67cbc65SPeter Wemm }; 1137b67cbc65SPeter Wemm #endif 1138eb725b4eSRobert Watson /* 11398bccf703SJohn Baldwin * MPSAFE 1140eb725b4eSRobert Watson */ 1141b67cbc65SPeter Wemm /* ARGSUSED */ 1142b67cbc65SPeter Wemm int 11434c44ad8eSJohn Baldwin issetugid(register struct thread *td, struct issetugid_args *uap) 1144b67cbc65SPeter Wemm { 1145b40ce416SJulian Elischer struct proc *p = td->td_proc; 1146b40ce416SJulian Elischer 1147b67cbc65SPeter Wemm /* 1148b67cbc65SPeter Wemm * Note: OpenBSD sets a P_SUGIDEXEC flag set at execve() time, 1149b67cbc65SPeter Wemm * we use P_SUGID because we consider changing the owners as 1150b67cbc65SPeter Wemm * "tainting" as well. 1151b67cbc65SPeter Wemm * This is significant for procs that start as root and "become" 1152b67cbc65SPeter Wemm * a user without an exec - programs cannot know *everything* 1153b67cbc65SPeter Wemm * that libc *might* have put in their data segment. 1154b67cbc65SPeter Wemm */ 1155f591779bSSeigo Tanimura PROC_LOCK(p); 1156b40ce416SJulian Elischer td->td_retval[0] = (p->p_flag & P_SUGID) ? 1 : 0; 1157f591779bSSeigo Tanimura PROC_UNLOCK(p); 1158b67cbc65SPeter Wemm return (0); 1159b67cbc65SPeter Wemm } 1160b67cbc65SPeter Wemm 1161835a82eeSMatthew Dillon /* 1162835a82eeSMatthew Dillon * MPSAFE 1163835a82eeSMatthew Dillon */ 1164130d0157SRobert Watson int 11654c44ad8eSJohn Baldwin __setugid(struct thread *td, struct __setugid_args *uap) 1166130d0157SRobert Watson { 1167130d0157SRobert Watson #ifdef REGRESSION 116807f3485dSJohn Baldwin struct proc *p; 1169835a82eeSMatthew Dillon 117007f3485dSJohn Baldwin p = td->td_proc; 1171130d0157SRobert Watson switch (uap->flag) { 1172130d0157SRobert Watson case 0: 117307f3485dSJohn Baldwin PROC_LOCK(p); 117407f3485dSJohn Baldwin p->p_flag &= ~P_SUGID; 117507f3485dSJohn Baldwin PROC_UNLOCK(p); 117607f3485dSJohn Baldwin return (0); 117707f3485dSJohn Baldwin case 1: 117807f3485dSJohn Baldwin PROC_LOCK(p); 117907f3485dSJohn Baldwin p->p_flag |= P_SUGID; 118007f3485dSJohn Baldwin PROC_UNLOCK(p); 118107f3485dSJohn Baldwin return (0); 118207f3485dSJohn Baldwin default: 118307f3485dSJohn Baldwin return (EINVAL); 118407f3485dSJohn Baldwin } 1185130d0157SRobert Watson #else /* !REGRESSION */ 1186eb725b4eSRobert Watson 1187130d0157SRobert Watson return (ENOSYS); 1188eb725b4eSRobert Watson #endif /* REGRESSION */ 1189130d0157SRobert Watson } 1190130d0157SRobert Watson 1191df8bae1dSRodney W. Grimes /* 1192df8bae1dSRodney W. Grimes * Check if gid is a member of the group set. 1193d74ac681SMatthew Dillon * 1194d74ac681SMatthew Dillon * MPSAFE (cred must be held) 1195df8bae1dSRodney W. Grimes */ 119626f9a767SRodney W. Grimes int 11974c44ad8eSJohn Baldwin groupmember(gid_t gid, struct ucred *cred) 1198df8bae1dSRodney W. Grimes { 1199df8bae1dSRodney W. Grimes register gid_t *gp; 1200df8bae1dSRodney W. Grimes gid_t *egp; 1201df8bae1dSRodney W. Grimes 1202df8bae1dSRodney W. Grimes egp = &(cred->cr_groups[cred->cr_ngroups]); 1203df8bae1dSRodney W. Grimes for (gp = cred->cr_groups; gp < egp; gp++) 1204df8bae1dSRodney W. Grimes if (*gp == gid) 1205df8bae1dSRodney W. Grimes return (1); 1206df8bae1dSRodney W. Grimes return (0); 1207df8bae1dSRodney W. Grimes } 1208df8bae1dSRodney W. Grimes 12093b243b72SRobert Watson /* 1210d0615c64SAndrew R. Reiter * `suser_enabled' (which can be set by the security.suser_enabled 12117fd6a959SRobert Watson * sysctl) determines whether the system 'super-user' policy is in effect. 12127fd6a959SRobert Watson * If it is nonzero, an effective uid of 0 connotes special privilege, 12137fd6a959SRobert Watson * overriding many mandatory and discretionary protections. If it is zero, 12147fd6a959SRobert Watson * uid 0 is offered no special privilege in the kernel security policy. 12157fd6a959SRobert Watson * Setting it to zero may seriously impact the functionality of many 12167fd6a959SRobert Watson * existing userland programs, and should not be done without careful 12177fd6a959SRobert Watson * consideration of the consequences. 12183b243b72SRobert Watson */ 121993f4fd1cSRobert Watson int suser_enabled = 1; 1220d0615c64SAndrew R. Reiter SYSCTL_INT(_security_bsd, OID_AUTO, suser_enabled, CTLFLAG_RW, 122193f4fd1cSRobert Watson &suser_enabled, 0, "processes with uid 0 have privilege"); 1222d0615c64SAndrew R. Reiter TUNABLE_INT("security.bsd.suser_enabled", &suser_enabled); 1223579f4eb4SRobert Watson 1224df8bae1dSRodney W. Grimes /* 12257fd6a959SRobert Watson * Test whether the specified credentials imply "super-user" privilege. 122624283cc0SColin Percival * Return 0 or EPERM. 1227df8bae1dSRodney W. Grimes */ 122826f9a767SRodney W. Grimes int 122944731cabSJohn Baldwin suser_cred(struct ucred *cred, int flag) 1230f711d546SPoul-Henning Kamp { 1231eb725b4eSRobert Watson 123293f4fd1cSRobert Watson if (!suser_enabled) 123303095547SRobert Watson return (EPERM); 123424283cc0SColin Percival if (((flag & SUSER_RUID) ? cred->cr_ruid : cred->cr_uid) != 0) 123575c13541SPoul-Henning Kamp return (EPERM); 123691421ba2SRobert Watson if (jailed(cred) && !(flag & PRISON_ROOT)) 123775c13541SPoul-Henning Kamp return (EPERM); 123875c13541SPoul-Henning Kamp return (0); 123975c13541SPoul-Henning Kamp } 1240df8bae1dSRodney W. Grimes 12413ca719f1SRobert Watson /* 124244731cabSJohn Baldwin * Shortcut to hide contents of struct td and struct proc from the 124344731cabSJohn Baldwin * caller, promoting binary compatibility. 124444731cabSJohn Baldwin */ 124544731cabSJohn Baldwin int 124644731cabSJohn Baldwin suser(struct thread *td) 124744731cabSJohn Baldwin { 124844731cabSJohn Baldwin 1249df04411aSRobert Watson #ifdef INVARIANTS 1250df04411aSRobert Watson if (td != curthread) { 1251df04411aSRobert Watson printf("suser: thread %p (%d %s) != curthread %p (%d %s)\n", 1252df04411aSRobert Watson td, td->td_proc->p_pid, td->td_proc->p_comm, 1253df04411aSRobert Watson curthread, curthread->td_proc->p_pid, 1254df04411aSRobert Watson curthread->td_proc->p_comm); 1255df04411aSRobert Watson #ifdef KDB 1256df04411aSRobert Watson kdb_backtrace(); 1257df04411aSRobert Watson #endif 1258df04411aSRobert Watson } 1259df04411aSRobert Watson #endif 126044731cabSJohn Baldwin return (suser_cred(td->td_ucred, 0)); 126144731cabSJohn Baldwin } 126244731cabSJohn Baldwin 126344731cabSJohn Baldwin /* 1264eb725b4eSRobert Watson * Test the active securelevel against a given level. securelevel_gt() 1265eb725b4eSRobert Watson * implements (securelevel > level). securelevel_ge() implements 1266eb725b4eSRobert Watson * (securelevel >= level). Note that the logic is inverted -- these 1267eb725b4eSRobert Watson * functions return EPERM on "success" and 0 on "failure". 12683ca719f1SRobert Watson * 1269d74ac681SMatthew Dillon * MPSAFE 12703ca719f1SRobert Watson */ 12713ca719f1SRobert Watson int 12723ca719f1SRobert Watson securelevel_gt(struct ucred *cr, int level) 12733ca719f1SRobert Watson { 1274eb725b4eSRobert Watson int active_securelevel; 12753ca719f1SRobert Watson 1276eb725b4eSRobert Watson active_securelevel = securelevel; 127770499328SJohn Baldwin KASSERT(cr != NULL, ("securelevel_gt: null cr")); 127801137630SRobert Watson if (cr->cr_prison != NULL) { 127901137630SRobert Watson mtx_lock(&cr->cr_prison->pr_mtx); 1280eb725b4eSRobert Watson active_securelevel = imax(cr->cr_prison->pr_securelevel, 1281eb725b4eSRobert Watson active_securelevel); 128201137630SRobert Watson mtx_unlock(&cr->cr_prison->pr_mtx); 128301137630SRobert Watson } 1284eb725b4eSRobert Watson return (active_securelevel > level ? EPERM : 0); 12853ca719f1SRobert Watson } 12863ca719f1SRobert Watson 12873ca719f1SRobert Watson int 12883ca719f1SRobert Watson securelevel_ge(struct ucred *cr, int level) 12893ca719f1SRobert Watson { 1290eb725b4eSRobert Watson int active_securelevel; 12913ca719f1SRobert Watson 1292eb725b4eSRobert Watson active_securelevel = securelevel; 129370499328SJohn Baldwin KASSERT(cr != NULL, ("securelevel_ge: null cr")); 129401137630SRobert Watson if (cr->cr_prison != NULL) { 129501137630SRobert Watson mtx_lock(&cr->cr_prison->pr_mtx); 1296eb725b4eSRobert Watson active_securelevel = imax(cr->cr_prison->pr_securelevel, 1297eb725b4eSRobert Watson active_securelevel); 129801137630SRobert Watson mtx_unlock(&cr->cr_prison->pr_mtx); 129901137630SRobert Watson } 1300eb725b4eSRobert Watson return (active_securelevel >= level ? EPERM : 0); 13013ca719f1SRobert Watson } 13023ca719f1SRobert Watson 13038a7d8cc6SRobert Watson /* 1304e409590dSRobert Watson * 'see_other_uids' determines whether or not visibility of processes 1305eb725b4eSRobert Watson * and sockets with credentials holding different real uids is possible 130648713bdcSRobert Watson * using a variety of system MIBs. 1307eb725b4eSRobert Watson * XXX: data declarations should be together near the beginning of the file. 13088a7d8cc6SRobert Watson */ 1309e409590dSRobert Watson static int see_other_uids = 1; 1310d0615c64SAndrew R. Reiter SYSCTL_INT(_security_bsd, OID_AUTO, see_other_uids, CTLFLAG_RW, 1311eb725b4eSRobert Watson &see_other_uids, 0, 13128a7d8cc6SRobert Watson "Unprivileged processes may see subjects/objects with different real uid"); 13138a7d8cc6SRobert Watson 13147fd6a959SRobert Watson /*- 13151b350b45SRobert Watson * Determine if u1 "can see" the subject specified by u2, according to the 13161b350b45SRobert Watson * 'see_other_uids' policy. 13171b350b45SRobert Watson * Returns: 0 for permitted, ESRCH otherwise 13181b350b45SRobert Watson * Locks: none 13191b350b45SRobert Watson * References: *u1 and *u2 must not change during the call 13201b350b45SRobert Watson * u1 may equal u2, in which case only one reference is required 13211b350b45SRobert Watson */ 13221b350b45SRobert Watson static int 13231b350b45SRobert Watson cr_seeotheruids(struct ucred *u1, struct ucred *u2) 13241b350b45SRobert Watson { 13251b350b45SRobert Watson 13261b350b45SRobert Watson if (!see_other_uids && u1->cr_ruid != u2->cr_ruid) { 132744731cabSJohn Baldwin if (suser_cred(u1, PRISON_ROOT) != 0) 13281b350b45SRobert Watson return (ESRCH); 13291b350b45SRobert Watson } 13301b350b45SRobert Watson return (0); 13311b350b45SRobert Watson } 13321b350b45SRobert Watson 133364d19c2eSRobert Watson /* 133464d19c2eSRobert Watson * 'see_other_gids' determines whether or not visibility of processes 133564d19c2eSRobert Watson * and sockets with credentials holding different real gids is possible 133664d19c2eSRobert Watson * using a variety of system MIBs. 133764d19c2eSRobert Watson * XXX: data declarations should be together near the beginning of the file. 133864d19c2eSRobert Watson */ 133964d19c2eSRobert Watson static int see_other_gids = 1; 134064d19c2eSRobert Watson SYSCTL_INT(_security_bsd, OID_AUTO, see_other_gids, CTLFLAG_RW, 134164d19c2eSRobert Watson &see_other_gids, 0, 134264d19c2eSRobert Watson "Unprivileged processes may see subjects/objects with different real gid"); 134364d19c2eSRobert Watson 134464d19c2eSRobert Watson /* 134564d19c2eSRobert Watson * Determine if u1 can "see" the subject specified by u2, according to the 134664d19c2eSRobert Watson * 'see_other_gids' policy. 134764d19c2eSRobert Watson * Returns: 0 for permitted, ESRCH otherwise 134864d19c2eSRobert Watson * Locks: none 134964d19c2eSRobert Watson * References: *u1 and *u2 must not change during the call 135064d19c2eSRobert Watson * u1 may equal u2, in which case only one reference is required 135164d19c2eSRobert Watson */ 135264d19c2eSRobert Watson static int 135364d19c2eSRobert Watson cr_seeothergids(struct ucred *u1, struct ucred *u2) 135464d19c2eSRobert Watson { 135564d19c2eSRobert Watson int i, match; 135664d19c2eSRobert Watson 135764d19c2eSRobert Watson if (!see_other_gids) { 135864d19c2eSRobert Watson match = 0; 135964d19c2eSRobert Watson for (i = 0; i < u1->cr_ngroups; i++) { 136064d19c2eSRobert Watson if (groupmember(u1->cr_groups[i], u2)) 136164d19c2eSRobert Watson match = 1; 136264d19c2eSRobert Watson if (match) 136364d19c2eSRobert Watson break; 136464d19c2eSRobert Watson } 136564d19c2eSRobert Watson if (!match) { 136664d19c2eSRobert Watson if (suser_cred(u1, PRISON_ROOT) != 0) 136764d19c2eSRobert Watson return (ESRCH); 136864d19c2eSRobert Watson } 136964d19c2eSRobert Watson } 137064d19c2eSRobert Watson return (0); 137164d19c2eSRobert Watson } 137264d19c2eSRobert Watson 13731b350b45SRobert Watson /*- 13747fd6a959SRobert Watson * Determine if u1 "can see" the subject specified by u2. 1375ed639720SRobert Watson * Returns: 0 for permitted, an errno value otherwise 1376ed639720SRobert Watson * Locks: none 1377eb725b4eSRobert Watson * References: *u1 and *u2 must not change during the call 1378ed639720SRobert Watson * u1 may equal u2, in which case only one reference is required 1379ed639720SRobert Watson */ 1380ed639720SRobert Watson int 138194088977SRobert Watson cr_cansee(struct ucred *u1, struct ucred *u2) 1382a9e0361bSPoul-Henning Kamp { 138391421ba2SRobert Watson int error; 1384a9e0361bSPoul-Henning Kamp 1385ed639720SRobert Watson if ((error = prison_check(u1, u2))) 138691421ba2SRobert Watson return (error); 13878a1d977dSRobert Watson #ifdef MAC 13888a1d977dSRobert Watson if ((error = mac_check_cred_visible(u1, u2))) 13898a1d977dSRobert Watson return (error); 13908a1d977dSRobert Watson #endif 13911b350b45SRobert Watson if ((error = cr_seeotheruids(u1, u2))) 13921b350b45SRobert Watson return (error); 139364d19c2eSRobert Watson if ((error = cr_seeothergids(u1, u2))) 139464d19c2eSRobert Watson return (error); 1395387d2c03SRobert Watson return (0); 1396387d2c03SRobert Watson } 1397387d2c03SRobert Watson 13987fd6a959SRobert Watson /*- 1399f44d9e24SJohn Baldwin * Determine if td "can see" the subject specified by p. 14003b243b72SRobert Watson * Returns: 0 for permitted, an errno value otherwise 1401f44d9e24SJohn Baldwin * Locks: Sufficient locks to protect p->p_ucred must be held. td really 1402f44d9e24SJohn Baldwin * should be curthread. 1403f44d9e24SJohn Baldwin * References: td and p must be valid for the lifetime of the call 14043b243b72SRobert Watson */ 1405a0f75161SRobert Watson int 1406f44d9e24SJohn Baldwin p_cansee(struct thread *td, struct proc *p) 1407ed639720SRobert Watson { 1408ed639720SRobert Watson 140994088977SRobert Watson /* Wrap cr_cansee() for all functionality. */ 1410f44d9e24SJohn Baldwin KASSERT(td == curthread, ("%s: td not curthread", __func__)); 1411f44d9e24SJohn Baldwin PROC_LOCK_ASSERT(p, MA_OWNED); 1412f44d9e24SJohn Baldwin return (cr_cansee(td->td_ucred, p->p_ucred)); 1413ed639720SRobert Watson } 1414ed639720SRobert Watson 141562c45ef4SRobert Watson /* 141662c45ef4SRobert Watson * 'conservative_signals' prevents the delivery of a broad class of 141762c45ef4SRobert Watson * signals by unprivileged processes to processes that have changed their 141862c45ef4SRobert Watson * credentials since the last invocation of execve(). This can prevent 141962c45ef4SRobert Watson * the leakage of cached information or retained privileges as a result 142062c45ef4SRobert Watson * of a common class of signal-related vulnerabilities. However, this 142162c45ef4SRobert Watson * may interfere with some applications that expect to be able to 142262c45ef4SRobert Watson * deliver these signals to peer processes after having given up 142362c45ef4SRobert Watson * privilege. 142462c45ef4SRobert Watson */ 142562c45ef4SRobert Watson static int conservative_signals = 1; 142662c45ef4SRobert Watson SYSCTL_INT(_security_bsd, OID_AUTO, conservative_signals, CTLFLAG_RW, 142762c45ef4SRobert Watson &conservative_signals, 0, "Unprivileged processes prevented from " 142862c45ef4SRobert Watson "sending certain signals to processes whose credentials have changed"); 14297fd6a959SRobert Watson /*- 1430c83f8015SRobert Watson * Determine whether cred may deliver the specified signal to proc. 1431c83f8015SRobert Watson * Returns: 0 for permitted, an errno value otherwise. 1432c83f8015SRobert Watson * Locks: A lock must be held for proc. 1433c83f8015SRobert Watson * References: cred and proc must be valid for the lifetime of the call. 14344c5eb9c3SRobert Watson */ 14354c5eb9c3SRobert Watson int 1436c83f8015SRobert Watson cr_cansignal(struct ucred *cred, struct proc *proc, int signum) 1437387d2c03SRobert Watson { 143891421ba2SRobert Watson int error; 1439387d2c03SRobert Watson 1440f44d9e24SJohn Baldwin PROC_LOCK_ASSERT(proc, MA_OWNED); 14414c5eb9c3SRobert Watson /* 1442c83f8015SRobert Watson * Jail semantics limit the scope of signalling to proc in the 1443c83f8015SRobert Watson * same jail as cred, if cred is in jail. 14444c5eb9c3SRobert Watson */ 1445c83f8015SRobert Watson error = prison_check(cred, proc->p_ucred); 1446c83f8015SRobert Watson if (error) 144791421ba2SRobert Watson return (error); 14488a1d977dSRobert Watson #ifdef MAC 14498a1d977dSRobert Watson if ((error = mac_check_proc_signal(cred, proc, signum))) 14508a1d977dSRobert Watson return (error); 14518a1d977dSRobert Watson #endif 145264d19c2eSRobert Watson if ((error = cr_seeotheruids(cred, proc->p_ucred))) 145364d19c2eSRobert Watson return (error); 145464d19c2eSRobert Watson if ((error = cr_seeothergids(cred, proc->p_ucred))) 14551b350b45SRobert Watson return (error); 1456387d2c03SRobert Watson 1457387d2c03SRobert Watson /* 14583b243b72SRobert Watson * UNIX signal semantics depend on the status of the P_SUGID 14593b243b72SRobert Watson * bit on the target process. If the bit is set, then additional 14603b243b72SRobert Watson * restrictions are placed on the set of available signals. 14614c5eb9c3SRobert Watson */ 146262c45ef4SRobert Watson if (conservative_signals && (proc->p_flag & P_SUGID)) { 14634c5eb9c3SRobert Watson switch (signum) { 14644c5eb9c3SRobert Watson case 0: 14654c5eb9c3SRobert Watson case SIGKILL: 14664c5eb9c3SRobert Watson case SIGINT: 14674c5eb9c3SRobert Watson case SIGTERM: 146862c45ef4SRobert Watson case SIGALRM: 14694c5eb9c3SRobert Watson case SIGSTOP: 14704c5eb9c3SRobert Watson case SIGTTIN: 14714c5eb9c3SRobert Watson case SIGTTOU: 14724c5eb9c3SRobert Watson case SIGTSTP: 14734c5eb9c3SRobert Watson case SIGHUP: 14744c5eb9c3SRobert Watson case SIGUSR1: 14754c5eb9c3SRobert Watson case SIGUSR2: 14767fd6a959SRobert Watson /* 14777fd6a959SRobert Watson * Generally, permit job and terminal control 14787fd6a959SRobert Watson * signals. 14797fd6a959SRobert Watson */ 14804c5eb9c3SRobert Watson break; 14814c5eb9c3SRobert Watson default: 1482c83f8015SRobert Watson /* Not permitted without privilege. */ 148344731cabSJohn Baldwin error = suser_cred(cred, PRISON_ROOT); 14844c5eb9c3SRobert Watson if (error) 14854c5eb9c3SRobert Watson return (error); 14864c5eb9c3SRobert Watson } 1487e9e7ff5bSRobert Watson } 1488e9e7ff5bSRobert Watson 14894c5eb9c3SRobert Watson /* 14903b243b72SRobert Watson * Generally, the target credential's ruid or svuid must match the 1491e9e7ff5bSRobert Watson * subject credential's ruid or euid. 14924c5eb9c3SRobert Watson */ 1493c83f8015SRobert Watson if (cred->cr_ruid != proc->p_ucred->cr_ruid && 1494c83f8015SRobert Watson cred->cr_ruid != proc->p_ucred->cr_svuid && 1495c83f8015SRobert Watson cred->cr_uid != proc->p_ucred->cr_ruid && 1496c83f8015SRobert Watson cred->cr_uid != proc->p_ucred->cr_svuid) { 1497c83f8015SRobert Watson /* Not permitted without privilege. */ 149844731cabSJohn Baldwin error = suser_cred(cred, PRISON_ROOT); 14994c5eb9c3SRobert Watson if (error) 15004c5eb9c3SRobert Watson return (error); 15014c5eb9c3SRobert Watson } 1502387d2c03SRobert Watson 1503387d2c03SRobert Watson return (0); 1504387d2c03SRobert Watson } 1505a9e0361bSPoul-Henning Kamp 1506c83f8015SRobert Watson 1507c83f8015SRobert Watson /*- 1508f44d9e24SJohn Baldwin * Determine whether td may deliver the specified signal to p. 1509c83f8015SRobert Watson * Returns: 0 for permitted, an errno value otherwise 1510f44d9e24SJohn Baldwin * Locks: Sufficient locks to protect various components of td and p 1511f44d9e24SJohn Baldwin * must be held. td must be curthread, and a lock must be 1512f44d9e24SJohn Baldwin * held for p. 1513f44d9e24SJohn Baldwin * References: td and p must be valid for the lifetime of the call 1514c83f8015SRobert Watson */ 1515c83f8015SRobert Watson int 1516f44d9e24SJohn Baldwin p_cansignal(struct thread *td, struct proc *p, int signum) 1517c83f8015SRobert Watson { 1518c83f8015SRobert Watson 1519f44d9e24SJohn Baldwin KASSERT(td == curthread, ("%s: td not curthread", __func__)); 1520f44d9e24SJohn Baldwin PROC_LOCK_ASSERT(p, MA_OWNED); 1521f44d9e24SJohn Baldwin if (td->td_proc == p) 1522c83f8015SRobert Watson return (0); 1523c83f8015SRobert Watson 1524c83f8015SRobert Watson /* 1525c83f8015SRobert Watson * UNIX signalling semantics require that processes in the same 1526c83f8015SRobert Watson * session always be able to deliver SIGCONT to one another, 1527c83f8015SRobert Watson * overriding the remaining protections. 1528c83f8015SRobert Watson */ 1529f44d9e24SJohn Baldwin /* XXX: This will require an additional lock of some sort. */ 1530f44d9e24SJohn Baldwin if (signum == SIGCONT && td->td_proc->p_session == p->p_session) 1531c83f8015SRobert Watson return (0); 1532c83f8015SRobert Watson 1533f44d9e24SJohn Baldwin return (cr_cansignal(td->td_ucred, p, signum)); 1534c83f8015SRobert Watson } 1535c83f8015SRobert Watson 15367fd6a959SRobert Watson /*- 1537f44d9e24SJohn Baldwin * Determine whether td may reschedule p. 15387fd6a959SRobert Watson * Returns: 0 for permitted, an errno value otherwise 1539f44d9e24SJohn Baldwin * Locks: Sufficient locks to protect various components of td and p 1540f44d9e24SJohn Baldwin * must be held. td must be curthread, and a lock must 1541f44d9e24SJohn Baldwin * be held for p. 1542f44d9e24SJohn Baldwin * References: td and p must be valid for the lifetime of the call 15433b243b72SRobert Watson */ 1544a0f75161SRobert Watson int 1545f44d9e24SJohn Baldwin p_cansched(struct thread *td, struct proc *p) 1546387d2c03SRobert Watson { 154791421ba2SRobert Watson int error; 1548387d2c03SRobert Watson 1549f44d9e24SJohn Baldwin KASSERT(td == curthread, ("%s: td not curthread", __func__)); 1550f44d9e24SJohn Baldwin PROC_LOCK_ASSERT(p, MA_OWNED); 1551f44d9e24SJohn Baldwin if (td->td_proc == p) 1552387d2c03SRobert Watson return (0); 1553f44d9e24SJohn Baldwin if ((error = prison_check(td->td_ucred, p->p_ucred))) 155491421ba2SRobert Watson return (error); 15558a1d977dSRobert Watson #ifdef MAC 15568a1d977dSRobert Watson if ((error = mac_check_proc_sched(td->td_ucred, p))) 15578a1d977dSRobert Watson return (error); 15588a1d977dSRobert Watson #endif 1559f44d9e24SJohn Baldwin if ((error = cr_seeotheruids(td->td_ucred, p->p_ucred))) 15601b350b45SRobert Watson return (error); 156164d19c2eSRobert Watson if ((error = cr_seeothergids(td->td_ucred, p->p_ucred))) 156264d19c2eSRobert Watson return (error); 1563f44d9e24SJohn Baldwin if (td->td_ucred->cr_ruid == p->p_ucred->cr_ruid) 1564387d2c03SRobert Watson return (0); 1565f44d9e24SJohn Baldwin if (td->td_ucred->cr_uid == p->p_ucred->cr_ruid) 1566387d2c03SRobert Watson return (0); 1567f44d9e24SJohn Baldwin if (suser_cred(td->td_ucred, PRISON_ROOT) == 0) 1568387d2c03SRobert Watson return (0); 1569387d2c03SRobert Watson 1570387d2c03SRobert Watson #ifdef CAPABILITIES 1571f44d9e24SJohn Baldwin if (!cap_check(NULL, td, CAP_SYS_NICE, PRISON_ROOT)) 1572387d2c03SRobert Watson return (0); 1573387d2c03SRobert Watson #endif 1574387d2c03SRobert Watson 1575387d2c03SRobert Watson return (EPERM); 1576387d2c03SRobert Watson } 1577387d2c03SRobert Watson 15783b243b72SRobert Watson /* 15795d476e73SRobert Watson * The 'unprivileged_proc_debug' flag may be used to disable a variety of 15805d476e73SRobert Watson * unprivileged inter-process debugging services, including some procfs 15815d476e73SRobert Watson * functionality, ptrace(), and ktrace(). In the past, inter-process 15825d476e73SRobert Watson * debugging has been involved in a variety of security problems, and sites 15835d476e73SRobert Watson * not requiring the service might choose to disable it when hardening 15845d476e73SRobert Watson * systems. 15853b243b72SRobert Watson * 15863b243b72SRobert Watson * XXX: Should modifying and reading this variable require locking? 1587eb725b4eSRobert Watson * XXX: data declarations should be together near the beginning of the file. 15883b243b72SRobert Watson */ 1589e409590dSRobert Watson static int unprivileged_proc_debug = 1; 1590d0615c64SAndrew R. Reiter SYSCTL_INT(_security_bsd, OID_AUTO, unprivileged_proc_debug, CTLFLAG_RW, 1591eb725b4eSRobert Watson &unprivileged_proc_debug, 0, 15920ef5652eSRobert Watson "Unprivileged processes may use process debugging facilities"); 15930ef5652eSRobert Watson 15947fd6a959SRobert Watson /*- 1595f44d9e24SJohn Baldwin * Determine whether td may debug p. 15967fd6a959SRobert Watson * Returns: 0 for permitted, an errno value otherwise 1597f44d9e24SJohn Baldwin * Locks: Sufficient locks to protect various components of td and p 1598f44d9e24SJohn Baldwin * must be held. td must be curthread, and a lock must 1599f44d9e24SJohn Baldwin * be held for p. 1600f44d9e24SJohn Baldwin * References: td and p must be valid for the lifetime of the call 16013b243b72SRobert Watson */ 1602a0f75161SRobert Watson int 1603f44d9e24SJohn Baldwin p_candebug(struct thread *td, struct proc *p) 1604387d2c03SRobert Watson { 1605eb725b4eSRobert Watson int credentialchanged, error, grpsubset, i, uidsubset; 1606387d2c03SRobert Watson 1607f44d9e24SJohn Baldwin KASSERT(td == curthread, ("%s: td not curthread", __func__)); 1608f44d9e24SJohn Baldwin PROC_LOCK_ASSERT(p, MA_OWNED); 1609e409590dSRobert Watson if (!unprivileged_proc_debug) { 1610f44d9e24SJohn Baldwin error = suser_cred(td->td_ucred, PRISON_ROOT); 161132d18604SRobert Watson if (error) 161232d18604SRobert Watson return (error); 161332d18604SRobert Watson } 1614f44d9e24SJohn Baldwin if (td->td_proc == p) 161523fad5b6SDag-Erling Smørgrav return (0); 1616f44d9e24SJohn Baldwin if ((error = prison_check(td->td_ucred, p->p_ucred))) 161791421ba2SRobert Watson return (error); 16188a1d977dSRobert Watson #ifdef MAC 16198a1d977dSRobert Watson if ((error = mac_check_proc_debug(td->td_ucred, p))) 16208a1d977dSRobert Watson return (error); 16218a1d977dSRobert Watson #endif 1622f44d9e24SJohn Baldwin if ((error = cr_seeotheruids(td->td_ucred, p->p_ucred))) 16231b350b45SRobert Watson return (error); 162464d19c2eSRobert Watson if ((error = cr_seeothergids(td->td_ucred, p->p_ucred))) 162564d19c2eSRobert Watson return (error); 1626387d2c03SRobert Watson 16277fd6a959SRobert Watson /* 1628f44d9e24SJohn Baldwin * Is p's group set a subset of td's effective group set? This 1629f44d9e24SJohn Baldwin * includes p's egid, group access list, rgid, and svgid. 16307fd6a959SRobert Watson */ 1631db42a33dSRobert Watson grpsubset = 1; 1632f44d9e24SJohn Baldwin for (i = 0; i < p->p_ucred->cr_ngroups; i++) { 1633f44d9e24SJohn Baldwin if (!groupmember(p->p_ucred->cr_groups[i], td->td_ucred)) { 1634db42a33dSRobert Watson grpsubset = 0; 1635db42a33dSRobert Watson break; 1636db42a33dSRobert Watson } 1637db42a33dSRobert Watson } 1638db42a33dSRobert Watson grpsubset = grpsubset && 1639f44d9e24SJohn Baldwin groupmember(p->p_ucred->cr_rgid, td->td_ucred) && 1640f44d9e24SJohn Baldwin groupmember(p->p_ucred->cr_svgid, td->td_ucred); 1641db42a33dSRobert Watson 1642db42a33dSRobert Watson /* 1643f44d9e24SJohn Baldwin * Are the uids present in p's credential equal to td's 1644f44d9e24SJohn Baldwin * effective uid? This includes p's euid, svuid, and ruid. 1645db42a33dSRobert Watson */ 1646f44d9e24SJohn Baldwin uidsubset = (td->td_ucred->cr_uid == p->p_ucred->cr_uid && 1647f44d9e24SJohn Baldwin td->td_ucred->cr_uid == p->p_ucred->cr_svuid && 1648f44d9e24SJohn Baldwin td->td_ucred->cr_uid == p->p_ucred->cr_ruid); 1649db42a33dSRobert Watson 1650db42a33dSRobert Watson /* 1651db42a33dSRobert Watson * Has the credential of the process changed since the last exec()? 1652db42a33dSRobert Watson */ 1653f44d9e24SJohn Baldwin credentialchanged = (p->p_flag & P_SUGID); 1654db42a33dSRobert Watson 1655db42a33dSRobert Watson /* 1656f44d9e24SJohn Baldwin * If p's gids aren't a subset, or the uids aren't a subset, 1657db42a33dSRobert Watson * or the credential has changed, require appropriate privilege 1658f44d9e24SJohn Baldwin * for td to debug p. For POSIX.1e capabilities, this will 1659db42a33dSRobert Watson * require CAP_SYS_PTRACE. 1660db42a33dSRobert Watson */ 1661db42a33dSRobert Watson if (!grpsubset || !uidsubset || credentialchanged) { 1662f44d9e24SJohn Baldwin error = suser_cred(td->td_ucred, PRISON_ROOT); 166332d18604SRobert Watson if (error) 1664387d2c03SRobert Watson return (error); 16657fd6a959SRobert Watson } 1666387d2c03SRobert Watson 1667eb725b4eSRobert Watson /* Can't trace init when securelevel > 0. */ 1668f44d9e24SJohn Baldwin if (p == initproc) { 1669f44d9e24SJohn Baldwin error = securelevel_gt(td->td_ucred, 0); 16703ca719f1SRobert Watson if (error) 16713ca719f1SRobert Watson return (error); 16723ca719f1SRobert Watson } 1673387d2c03SRobert Watson 16745fab7614SRobert Watson /* 16755fab7614SRobert Watson * Can't trace a process that's currently exec'ing. 16765fab7614SRobert Watson * XXX: Note, this is not a security policy decision, it's a 16775fab7614SRobert Watson * basic correctness/functionality decision. Therefore, this check 16785fab7614SRobert Watson * should be moved to the caller's of p_candebug(). 16795fab7614SRobert Watson */ 1680f44d9e24SJohn Baldwin if ((p->p_flag & P_INEXEC) != 0) 16819ca45e81SDag-Erling Smørgrav return (EAGAIN); 16829ca45e81SDag-Erling Smørgrav 1683387d2c03SRobert Watson return (0); 1684387d2c03SRobert Watson } 1685387d2c03SRobert Watson 168629dc1288SRobert Watson /*- 168729dc1288SRobert Watson * Determine whether the subject represented by cred can "see" a socket. 168829dc1288SRobert Watson * Returns: 0 for permitted, ENOENT otherwise. 168929dc1288SRobert Watson */ 169029dc1288SRobert Watson int 169129dc1288SRobert Watson cr_canseesocket(struct ucred *cred, struct socket *so) 169229dc1288SRobert Watson { 169329dc1288SRobert Watson int error; 169429dc1288SRobert Watson 169529dc1288SRobert Watson error = prison_check(cred, so->so_cred); 169629dc1288SRobert Watson if (error) 169729dc1288SRobert Watson return (ENOENT); 16988a1d977dSRobert Watson #ifdef MAC 1699310e7cebSRobert Watson SOCK_LOCK(so); 17008a1d977dSRobert Watson error = mac_check_socket_visible(cred, so); 1701310e7cebSRobert Watson SOCK_UNLOCK(so); 17028a1d977dSRobert Watson if (error) 17038a1d977dSRobert Watson return (error); 17048a1d977dSRobert Watson #endif 170529dc1288SRobert Watson if (cr_seeotheruids(cred, so->so_cred)) 170629dc1288SRobert Watson return (ENOENT); 170764d19c2eSRobert Watson if (cr_seeothergids(cred, so->so_cred)) 170864d19c2eSRobert Watson return (ENOENT); 170929dc1288SRobert Watson 171029dc1288SRobert Watson return (0); 171129dc1288SRobert Watson } 171229dc1288SRobert Watson 1713a9e0361bSPoul-Henning Kamp /* 1714df8bae1dSRodney W. Grimes * Allocate a zeroed cred structure. 17152bceb0f2SRobert Watson * MPSAFE 1716df8bae1dSRodney W. Grimes */ 1717df8bae1dSRodney W. Grimes struct ucred * 17184c44ad8eSJohn Baldwin crget(void) 1719df8bae1dSRodney W. Grimes { 1720df8bae1dSRodney W. Grimes register struct ucred *cr; 1721df8bae1dSRodney W. Grimes 1722a163d034SWarner Losh MALLOC(cr, struct ucred *, sizeof(*cr), M_CRED, M_WAITOK | M_ZERO); 1723df8bae1dSRodney W. Grimes cr->cr_ref = 1; 1724857d9c60SDon Lewis cr->cr_mtxp = mtx_pool_find(mtxpool_sleep, cr); 172540244964SRobert Watson #ifdef MAC 172640244964SRobert Watson mac_init_cred(cr); 172740244964SRobert Watson #endif 1728df8bae1dSRodney W. Grimes return (cr); 1729df8bae1dSRodney W. Grimes } 1730df8bae1dSRodney W. Grimes 1731df8bae1dSRodney W. Grimes /* 17327fd6a959SRobert Watson * Claim another reference to a ucred structure. 17332bceb0f2SRobert Watson * MPSAFE 17345c3f70d7SAlfred Perlstein */ 1735bd78ceceSJohn Baldwin struct ucred * 17364c44ad8eSJohn Baldwin crhold(struct ucred *cr) 17375c3f70d7SAlfred Perlstein { 17385c3f70d7SAlfred Perlstein 1739e1bca29fSMatthew Dillon mtx_lock(cr->cr_mtxp); 17405c3f70d7SAlfred Perlstein cr->cr_ref++; 1741e1bca29fSMatthew Dillon mtx_unlock(cr->cr_mtxp); 1742bd78ceceSJohn Baldwin return (cr); 17435c3f70d7SAlfred Perlstein } 17445c3f70d7SAlfred Perlstein 17455c3f70d7SAlfred Perlstein /* 1746df8bae1dSRodney W. Grimes * Free a cred structure. 1747df8bae1dSRodney W. Grimes * Throws away space when ref count gets to 0. 17482bceb0f2SRobert Watson * MPSAFE 1749df8bae1dSRodney W. Grimes */ 175026f9a767SRodney W. Grimes void 17514c44ad8eSJohn Baldwin crfree(struct ucred *cr) 1752df8bae1dSRodney W. Grimes { 1753e1bca29fSMatthew Dillon struct mtx *mtxp = cr->cr_mtxp; 17541e5d626aSAlfred Perlstein 1755e1bca29fSMatthew Dillon mtx_lock(mtxp); 1756e04670b7SAlfred Perlstein KASSERT(cr->cr_ref > 0, ("bad ucred refcount: %d", cr->cr_ref)); 1757f535380cSDon Lewis if (--cr->cr_ref == 0) { 1758646e29ccSRobert Watson mtx_unlock(mtxp); 1759f535380cSDon Lewis /* 1760f535380cSDon Lewis * Some callers of crget(), such as nfs_statfs(), 1761f535380cSDon Lewis * allocate a temporary credential, but don't 1762f535380cSDon Lewis * allocate a uidinfo structure. 1763f535380cSDon Lewis */ 1764f535380cSDon Lewis if (cr->cr_uidinfo != NULL) 1765f535380cSDon Lewis uifree(cr->cr_uidinfo); 1766823c224eSRobert Watson if (cr->cr_ruidinfo != NULL) 1767823c224eSRobert Watson uifree(cr->cr_ruidinfo); 176891421ba2SRobert Watson /* 176991421ba2SRobert Watson * Free a prison, if any. 177091421ba2SRobert Watson */ 177191421ba2SRobert Watson if (jailed(cr)) 177291421ba2SRobert Watson prison_free(cr->cr_prison); 177340244964SRobert Watson #ifdef MAC 177440244964SRobert Watson mac_destroy_cred(cr); 177540244964SRobert Watson #endif 17767f05b035SAlfred Perlstein FREE(cr, M_CRED); 1777e1bca29fSMatthew Dillon } else { 1778e1bca29fSMatthew Dillon mtx_unlock(mtxp); 1779e1bca29fSMatthew Dillon } 1780df8bae1dSRodney W. Grimes } 1781df8bae1dSRodney W. Grimes 1782df8bae1dSRodney W. Grimes /* 1783bd78ceceSJohn Baldwin * Check to see if this ucred is shared. 17842bceb0f2SRobert Watson * MPSAFE 1785df8bae1dSRodney W. Grimes */ 1786bd78ceceSJohn Baldwin int 17874c44ad8eSJohn Baldwin crshared(struct ucred *cr) 1788df8bae1dSRodney W. Grimes { 1789bd78ceceSJohn Baldwin int shared; 1790df8bae1dSRodney W. Grimes 1791e1bca29fSMatthew Dillon mtx_lock(cr->cr_mtxp); 1792bd78ceceSJohn Baldwin shared = (cr->cr_ref > 1); 1793e1bca29fSMatthew Dillon mtx_unlock(cr->cr_mtxp); 1794bd78ceceSJohn Baldwin return (shared); 17951e5d626aSAlfred Perlstein } 1796bd78ceceSJohn Baldwin 1797bd78ceceSJohn Baldwin /* 1798bd78ceceSJohn Baldwin * Copy a ucred's contents from a template. Does not block. 17992bceb0f2SRobert Watson * MPSAFE 1800bd78ceceSJohn Baldwin */ 1801bd78ceceSJohn Baldwin void 18024c44ad8eSJohn Baldwin crcopy(struct ucred *dest, struct ucred *src) 1803bd78ceceSJohn Baldwin { 1804bd78ceceSJohn Baldwin 1805bd78ceceSJohn Baldwin KASSERT(crshared(dest) == 0, ("crcopy of shared ucred")); 1806bd78ceceSJohn Baldwin bcopy(&src->cr_startcopy, &dest->cr_startcopy, 1807bd78ceceSJohn Baldwin (unsigned)((caddr_t)&src->cr_endcopy - 1808bd78ceceSJohn Baldwin (caddr_t)&src->cr_startcopy)); 1809bd78ceceSJohn Baldwin uihold(dest->cr_uidinfo); 1810bd78ceceSJohn Baldwin uihold(dest->cr_ruidinfo); 1811bd78ceceSJohn Baldwin if (jailed(dest)) 1812bd78ceceSJohn Baldwin prison_hold(dest->cr_prison); 181340244964SRobert Watson #ifdef MAC 181456d9e932SRobert Watson mac_copy_cred(src, dest); 181540244964SRobert Watson #endif 1816df8bae1dSRodney W. Grimes } 1817df8bae1dSRodney W. Grimes 1818df8bae1dSRodney W. Grimes /* 1819df8bae1dSRodney W. Grimes * Dup cred struct to a new held one. 18202bceb0f2SRobert Watson * MPSAFE 1821df8bae1dSRodney W. Grimes */ 1822df8bae1dSRodney W. Grimes struct ucred * 18234c44ad8eSJohn Baldwin crdup(struct ucred *cr) 1824df8bae1dSRodney W. Grimes { 1825df8bae1dSRodney W. Grimes struct ucred *newcr; 1826df8bae1dSRodney W. Grimes 1827bd78ceceSJohn Baldwin newcr = crget(); 1828bd78ceceSJohn Baldwin crcopy(newcr, cr); 1829df8bae1dSRodney W. Grimes return (newcr); 1830df8bae1dSRodney W. Grimes } 1831df8bae1dSRodney W. Grimes 1832aaa1c771SJonathan Mini #ifdef DIAGNOSTIC 1833aaa1c771SJonathan Mini void 1834aaa1c771SJonathan Mini cred_free_thread(struct thread *td) 1835aaa1c771SJonathan Mini { 1836aaa1c771SJonathan Mini struct ucred *cred; 1837aaa1c771SJonathan Mini 1838aaa1c771SJonathan Mini cred = td->td_ucred; 1839aaa1c771SJonathan Mini td->td_ucred = NULL; 1840aaa1c771SJonathan Mini if (cred != NULL) 1841aaa1c771SJonathan Mini crfree(cred); 1842aaa1c771SJonathan Mini } 1843aaa1c771SJonathan Mini #endif 1844aaa1c771SJonathan Mini 1845df8bae1dSRodney W. Grimes /* 184676183f34SDima Dorfman * Fill in a struct xucred based on a struct ucred. 18472bceb0f2SRobert Watson * MPSAFE 184876183f34SDima Dorfman */ 184976183f34SDima Dorfman void 18504c44ad8eSJohn Baldwin cru2x(struct ucred *cr, struct xucred *xcr) 185176183f34SDima Dorfman { 185276183f34SDima Dorfman 185376183f34SDima Dorfman bzero(xcr, sizeof(*xcr)); 185476183f34SDima Dorfman xcr->cr_version = XUCRED_VERSION; 185576183f34SDima Dorfman xcr->cr_uid = cr->cr_uid; 185676183f34SDima Dorfman xcr->cr_ngroups = cr->cr_ngroups; 185776183f34SDima Dorfman bcopy(cr->cr_groups, xcr->cr_groups, sizeof(cr->cr_groups)); 185876183f34SDima Dorfman } 185976183f34SDima Dorfman 186076183f34SDima Dorfman /* 18612eb927e2SJulian Elischer * small routine to swap a thread's current ucred for the correct one 18622eb927e2SJulian Elischer * taken from the process. 18632bceb0f2SRobert Watson * MPSAFE 18642eb927e2SJulian Elischer */ 18652eb927e2SJulian Elischer void 18662eb927e2SJulian Elischer cred_update_thread(struct thread *td) 18672eb927e2SJulian Elischer { 18682eb927e2SJulian Elischer struct proc *p; 186965e3406dSJohn Baldwin struct ucred *cred; 18702eb927e2SJulian Elischer 18712eb927e2SJulian Elischer p = td->td_proc; 187265e3406dSJohn Baldwin cred = td->td_ucred; 18732eb927e2SJulian Elischer PROC_LOCK(p); 18742eb927e2SJulian Elischer td->td_ucred = crhold(p->p_ucred); 18752eb927e2SJulian Elischer PROC_UNLOCK(p); 187665e3406dSJohn Baldwin if (cred != NULL) 187765e3406dSJohn Baldwin crfree(cred); 18782eb927e2SJulian Elischer } 18792eb927e2SJulian Elischer 18802eb927e2SJulian Elischer /* 1881df8bae1dSRodney W. Grimes * Get login name, if available. 1882df8bae1dSRodney W. Grimes */ 1883d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 1884df8bae1dSRodney W. Grimes struct getlogin_args { 1885df8bae1dSRodney W. Grimes char *namebuf; 1886df8bae1dSRodney W. Grimes u_int namelen; 1887df8bae1dSRodney W. Grimes }; 1888d2d3e875SBruce Evans #endif 1889835a82eeSMatthew Dillon /* 1890835a82eeSMatthew Dillon * MPSAFE 1891835a82eeSMatthew Dillon */ 1892df8bae1dSRodney W. Grimes /* ARGSUSED */ 189326f9a767SRodney W. Grimes int 18944c44ad8eSJohn Baldwin getlogin(struct thread *td, struct getlogin_args *uap) 1895df8bae1dSRodney W. Grimes { 1896835a82eeSMatthew Dillon int error; 1897f591779bSSeigo Tanimura char login[MAXLOGNAME]; 1898b40ce416SJulian Elischer struct proc *p = td->td_proc; 1899df8bae1dSRodney W. Grimes 190030cf3ac4SAndrey A. Chernov if (uap->namelen > MAXLOGNAME) 190153490b76SAndrey A. Chernov uap->namelen = MAXLOGNAME; 1902f591779bSSeigo Tanimura PROC_LOCK(p); 1903f591779bSSeigo Tanimura SESS_LOCK(p->p_session); 1904f591779bSSeigo Tanimura bcopy(p->p_session->s_login, login, uap->namelen); 1905f591779bSSeigo Tanimura SESS_UNLOCK(p->p_session); 1906f591779bSSeigo Tanimura PROC_UNLOCK(p); 19077f05b035SAlfred Perlstein error = copyout(login, uap->namebuf, uap->namelen); 1908835a82eeSMatthew Dillon return(error); 1909df8bae1dSRodney W. Grimes } 1910df8bae1dSRodney W. Grimes 1911df8bae1dSRodney W. Grimes /* 1912df8bae1dSRodney W. Grimes * Set login name. 1913df8bae1dSRodney W. Grimes */ 1914d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 1915df8bae1dSRodney W. Grimes struct setlogin_args { 1916df8bae1dSRodney W. Grimes char *namebuf; 1917df8bae1dSRodney W. Grimes }; 1918d2d3e875SBruce Evans #endif 1919835a82eeSMatthew Dillon /* 1920835a82eeSMatthew Dillon * MPSAFE 1921835a82eeSMatthew Dillon */ 1922df8bae1dSRodney W. Grimes /* ARGSUSED */ 192326f9a767SRodney W. Grimes int 19244c44ad8eSJohn Baldwin setlogin(struct thread *td, struct setlogin_args *uap) 1925df8bae1dSRodney W. Grimes { 1926b40ce416SJulian Elischer struct proc *p = td->td_proc; 1927df8bae1dSRodney W. Grimes int error; 1928964ca0caSAndrey A. Chernov char logintmp[MAXLOGNAME]; 1929df8bae1dSRodney W. Grimes 193007f3485dSJohn Baldwin error = suser_cred(td->td_ucred, PRISON_ROOT); 193107f3485dSJohn Baldwin if (error) 193207f3485dSJohn Baldwin return (error); 19337f05b035SAlfred Perlstein error = copyinstr(uap->namebuf, logintmp, sizeof(logintmp), NULL); 1934eb725b4eSRobert Watson if (error == ENAMETOOLONG) 1935df8bae1dSRodney W. Grimes error = EINVAL; 1936f591779bSSeigo Tanimura else if (!error) { 1937f591779bSSeigo Tanimura PROC_LOCK(p); 1938f591779bSSeigo Tanimura SESS_LOCK(p->p_session); 1939f591779bSSeigo Tanimura (void) memcpy(p->p_session->s_login, logintmp, 1940964ca0caSAndrey A. Chernov sizeof(logintmp)); 1941f591779bSSeigo Tanimura SESS_UNLOCK(p->p_session); 1942f591779bSSeigo Tanimura PROC_UNLOCK(p); 1943f591779bSSeigo Tanimura } 1944df8bae1dSRodney W. Grimes return (error); 1945df8bae1dSRodney W. Grimes } 1946d5f81602SSean Eric Fagan 1947d5f81602SSean Eric Fagan void 19484c44ad8eSJohn Baldwin setsugid(struct proc *p) 1949d5f81602SSean Eric Fagan { 1950f2102dadSAlfred Perlstein 1951f2102dadSAlfred Perlstein PROC_LOCK_ASSERT(p, MA_OWNED); 1952d5f81602SSean Eric Fagan p->p_flag |= P_SUGID; 195389361835SSean Eric Fagan if (!(p->p_pfsflags & PF_ISUGID)) 1954d5f81602SSean Eric Fagan p->p_stops = 0; 1955d5f81602SSean Eric Fagan } 1956f535380cSDon Lewis 19577fd6a959SRobert Watson /*- 19587fd6a959SRobert Watson * Change a process's effective uid. 1959b1fc0ec1SRobert Watson * Side effects: newcred->cr_uid and newcred->cr_uidinfo will be modified. 1960b1fc0ec1SRobert Watson * References: newcred must be an exclusive credential reference for the 1961b1fc0ec1SRobert Watson * duration of the call. 1962f535380cSDon Lewis */ 1963f535380cSDon Lewis void 19641419eacbSAlfred Perlstein change_euid(struct ucred *newcred, struct uidinfo *euip) 1965f535380cSDon Lewis { 1966f535380cSDon Lewis 19671419eacbSAlfred Perlstein newcred->cr_uid = euip->ui_uid; 19681419eacbSAlfred Perlstein uihold(euip); 1969b1fc0ec1SRobert Watson uifree(newcred->cr_uidinfo); 19701419eacbSAlfred Perlstein newcred->cr_uidinfo = euip; 1971f535380cSDon Lewis } 1972f535380cSDon Lewis 19737fd6a959SRobert Watson /*- 19747fd6a959SRobert Watson * Change a process's effective gid. 1975b1fc0ec1SRobert Watson * Side effects: newcred->cr_gid will be modified. 1976b1fc0ec1SRobert Watson * References: newcred must be an exclusive credential reference for the 1977b1fc0ec1SRobert Watson * duration of the call. 1978f535380cSDon Lewis */ 1979810bfc8eSAndrew Gallatin void 19804c44ad8eSJohn Baldwin change_egid(struct ucred *newcred, gid_t egid) 1981b1fc0ec1SRobert Watson { 1982b1fc0ec1SRobert Watson 1983b1fc0ec1SRobert Watson newcred->cr_groups[0] = egid; 1984b1fc0ec1SRobert Watson } 1985b1fc0ec1SRobert Watson 19867fd6a959SRobert Watson /*- 19877fd6a959SRobert Watson * Change a process's real uid. 1988b1fc0ec1SRobert Watson * Side effects: newcred->cr_ruid will be updated, newcred->cr_ruidinfo 1989b1fc0ec1SRobert Watson * will be updated, and the old and new cr_ruidinfo proc 1990b1fc0ec1SRobert Watson * counts will be updated. 1991b1fc0ec1SRobert Watson * References: newcred must be an exclusive credential reference for the 1992b1fc0ec1SRobert Watson * duration of the call. 1993b1fc0ec1SRobert Watson */ 1994b1fc0ec1SRobert Watson void 19951419eacbSAlfred Perlstein change_ruid(struct ucred *newcred, struct uidinfo *ruip) 1996f535380cSDon Lewis { 1997f535380cSDon Lewis 1998b1fc0ec1SRobert Watson (void)chgproccnt(newcred->cr_ruidinfo, -1, 0); 19991419eacbSAlfred Perlstein newcred->cr_ruid = ruip->ui_uid; 20001419eacbSAlfred Perlstein uihold(ruip); 2001b1fc0ec1SRobert Watson uifree(newcred->cr_ruidinfo); 20021419eacbSAlfred Perlstein newcred->cr_ruidinfo = ruip; 2003b1fc0ec1SRobert Watson (void)chgproccnt(newcred->cr_ruidinfo, 1, 0); 2004b1fc0ec1SRobert Watson } 2005b1fc0ec1SRobert Watson 20067fd6a959SRobert Watson /*- 20077fd6a959SRobert Watson * Change a process's real gid. 2008b1fc0ec1SRobert Watson * Side effects: newcred->cr_rgid will be updated. 2009b1fc0ec1SRobert Watson * References: newcred must be an exclusive credential reference for the 2010b1fc0ec1SRobert Watson * duration of the call. 2011b1fc0ec1SRobert Watson */ 2012b1fc0ec1SRobert Watson void 20134c44ad8eSJohn Baldwin change_rgid(struct ucred *newcred, gid_t rgid) 2014b1fc0ec1SRobert Watson { 2015b1fc0ec1SRobert Watson 2016b1fc0ec1SRobert Watson newcred->cr_rgid = rgid; 2017b1fc0ec1SRobert Watson } 2018b1fc0ec1SRobert Watson 20197fd6a959SRobert Watson /*- 20207fd6a959SRobert Watson * Change a process's saved uid. 2021b1fc0ec1SRobert Watson * Side effects: newcred->cr_svuid will be updated. 2022b1fc0ec1SRobert Watson * References: newcred must be an exclusive credential reference for the 2023b1fc0ec1SRobert Watson * duration of the call. 2024b1fc0ec1SRobert Watson */ 2025b1fc0ec1SRobert Watson void 20264c44ad8eSJohn Baldwin change_svuid(struct ucred *newcred, uid_t svuid) 2027b1fc0ec1SRobert Watson { 2028b1fc0ec1SRobert Watson 2029b1fc0ec1SRobert Watson newcred->cr_svuid = svuid; 2030b1fc0ec1SRobert Watson } 2031b1fc0ec1SRobert Watson 20327fd6a959SRobert Watson /*- 20337fd6a959SRobert Watson * Change a process's saved gid. 2034b1fc0ec1SRobert Watson * Side effects: newcred->cr_svgid will be updated. 2035b1fc0ec1SRobert Watson * References: newcred must be an exclusive credential reference for the 2036b1fc0ec1SRobert Watson * duration of the call. 2037b1fc0ec1SRobert Watson */ 2038b1fc0ec1SRobert Watson void 20394c44ad8eSJohn Baldwin change_svgid(struct ucred *newcred, gid_t svgid) 2040b1fc0ec1SRobert Watson { 2041b1fc0ec1SRobert Watson 2042b1fc0ec1SRobert Watson newcred->cr_svgid = svgid; 2043f535380cSDon Lewis } 2044