19454b2d8SWarner Losh /*- 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 } 41271a057bcSRobert Watson if ((error = p_cansee(td, 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 52756f21b9dSColin Percival (error = suser_cred(oldcred, SUSER_ALLOWJAIL)) != 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 54756f21b9dSColin Percival suser_cred(oldcred, SUSER_ALLOWJAIL) == 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) */ 60956f21b9dSColin Percival (error = suser_cred(oldcred, SUSER_ALLOWJAIL)) != 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 67156f21b9dSColin Percival (error = suser_cred(oldcred, SUSER_ALLOWJAIL)) != 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 68756f21b9dSColin Percival suser_cred(oldcred, SUSER_ALLOWJAIL) == 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) */ 74656f21b9dSColin Percival (error = suser_cred(oldcred, SUSER_ALLOWJAIL)) != 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; 79256f21b9dSColin Percival error = suser_cred(oldcred, SUSER_ALLOWJAIL); 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)) && 85656f21b9dSColin Percival (error = suser_cred(oldcred, SUSER_ALLOWJAIL)) != 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)) && 91256f21b9dSColin Percival (error = suser_cred(oldcred, SUSER_ALLOWJAIL)) != 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)) && 98056f21b9dSColin Percival (error = suser_cred(oldcred, SUSER_ALLOWJAIL)) != 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])) && 104856f21b9dSColin Percival (error = suser_cred(oldcred, SUSER_ALLOWJAIL)) != 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); 123656f21b9dSColin Percival if (jailed(cred) && !(flag & SUSER_ALLOWJAIL)) 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")); 1278471135a3SRobert Watson if (cr->cr_prison != NULL) 1279eb725b4eSRobert Watson active_securelevel = imax(cr->cr_prison->pr_securelevel, 1280eb725b4eSRobert Watson active_securelevel); 1281eb725b4eSRobert Watson return (active_securelevel > level ? EPERM : 0); 12823ca719f1SRobert Watson } 12833ca719f1SRobert Watson 12843ca719f1SRobert Watson int 12853ca719f1SRobert Watson securelevel_ge(struct ucred *cr, int level) 12863ca719f1SRobert Watson { 1287eb725b4eSRobert Watson int active_securelevel; 12883ca719f1SRobert Watson 1289eb725b4eSRobert Watson active_securelevel = securelevel; 129070499328SJohn Baldwin KASSERT(cr != NULL, ("securelevel_ge: null cr")); 1291471135a3SRobert Watson if (cr->cr_prison != NULL) 1292eb725b4eSRobert Watson active_securelevel = imax(cr->cr_prison->pr_securelevel, 1293eb725b4eSRobert Watson active_securelevel); 1294eb725b4eSRobert Watson return (active_securelevel >= level ? EPERM : 0); 12953ca719f1SRobert Watson } 12963ca719f1SRobert Watson 12978a7d8cc6SRobert Watson /* 1298e409590dSRobert Watson * 'see_other_uids' determines whether or not visibility of processes 1299eb725b4eSRobert Watson * and sockets with credentials holding different real uids is possible 130048713bdcSRobert Watson * using a variety of system MIBs. 1301eb725b4eSRobert Watson * XXX: data declarations should be together near the beginning of the file. 13028a7d8cc6SRobert Watson */ 1303e409590dSRobert Watson static int see_other_uids = 1; 1304d0615c64SAndrew R. Reiter SYSCTL_INT(_security_bsd, OID_AUTO, see_other_uids, CTLFLAG_RW, 1305eb725b4eSRobert Watson &see_other_uids, 0, 13068a7d8cc6SRobert Watson "Unprivileged processes may see subjects/objects with different real uid"); 13078a7d8cc6SRobert Watson 13087fd6a959SRobert Watson /*- 13091b350b45SRobert Watson * Determine if u1 "can see" the subject specified by u2, according to the 13101b350b45SRobert Watson * 'see_other_uids' policy. 13111b350b45SRobert Watson * Returns: 0 for permitted, ESRCH otherwise 13121b350b45SRobert Watson * Locks: none 13131b350b45SRobert Watson * References: *u1 and *u2 must not change during the call 13141b350b45SRobert Watson * u1 may equal u2, in which case only one reference is required 13151b350b45SRobert Watson */ 13161b350b45SRobert Watson static int 13171b350b45SRobert Watson cr_seeotheruids(struct ucred *u1, struct ucred *u2) 13181b350b45SRobert Watson { 13191b350b45SRobert Watson 13201b350b45SRobert Watson if (!see_other_uids && u1->cr_ruid != u2->cr_ruid) { 132156f21b9dSColin Percival if (suser_cred(u1, SUSER_ALLOWJAIL) != 0) 13221b350b45SRobert Watson return (ESRCH); 13231b350b45SRobert Watson } 13241b350b45SRobert Watson return (0); 13251b350b45SRobert Watson } 13261b350b45SRobert Watson 132764d19c2eSRobert Watson /* 132864d19c2eSRobert Watson * 'see_other_gids' determines whether or not visibility of processes 132964d19c2eSRobert Watson * and sockets with credentials holding different real gids is possible 133064d19c2eSRobert Watson * using a variety of system MIBs. 133164d19c2eSRobert Watson * XXX: data declarations should be together near the beginning of the file. 133264d19c2eSRobert Watson */ 133364d19c2eSRobert Watson static int see_other_gids = 1; 133464d19c2eSRobert Watson SYSCTL_INT(_security_bsd, OID_AUTO, see_other_gids, CTLFLAG_RW, 133564d19c2eSRobert Watson &see_other_gids, 0, 133664d19c2eSRobert Watson "Unprivileged processes may see subjects/objects with different real gid"); 133764d19c2eSRobert Watson 133864d19c2eSRobert Watson /* 133964d19c2eSRobert Watson * Determine if u1 can "see" the subject specified by u2, according to the 134064d19c2eSRobert Watson * 'see_other_gids' policy. 134164d19c2eSRobert Watson * Returns: 0 for permitted, ESRCH otherwise 134264d19c2eSRobert Watson * Locks: none 134364d19c2eSRobert Watson * References: *u1 and *u2 must not change during the call 134464d19c2eSRobert Watson * u1 may equal u2, in which case only one reference is required 134564d19c2eSRobert Watson */ 134664d19c2eSRobert Watson static int 134764d19c2eSRobert Watson cr_seeothergids(struct ucred *u1, struct ucred *u2) 134864d19c2eSRobert Watson { 134964d19c2eSRobert Watson int i, match; 135064d19c2eSRobert Watson 135164d19c2eSRobert Watson if (!see_other_gids) { 135264d19c2eSRobert Watson match = 0; 135364d19c2eSRobert Watson for (i = 0; i < u1->cr_ngroups; i++) { 135464d19c2eSRobert Watson if (groupmember(u1->cr_groups[i], u2)) 135564d19c2eSRobert Watson match = 1; 135664d19c2eSRobert Watson if (match) 135764d19c2eSRobert Watson break; 135864d19c2eSRobert Watson } 135964d19c2eSRobert Watson if (!match) { 136056f21b9dSColin Percival if (suser_cred(u1, SUSER_ALLOWJAIL) != 0) 136164d19c2eSRobert Watson return (ESRCH); 136264d19c2eSRobert Watson } 136364d19c2eSRobert Watson } 136464d19c2eSRobert Watson return (0); 136564d19c2eSRobert Watson } 136664d19c2eSRobert Watson 13671b350b45SRobert Watson /*- 13687fd6a959SRobert Watson * Determine if u1 "can see" the subject specified by u2. 1369ed639720SRobert Watson * Returns: 0 for permitted, an errno value otherwise 1370ed639720SRobert Watson * Locks: none 1371eb725b4eSRobert Watson * References: *u1 and *u2 must not change during the call 1372ed639720SRobert Watson * u1 may equal u2, in which case only one reference is required 1373ed639720SRobert Watson */ 1374ed639720SRobert Watson int 137594088977SRobert Watson cr_cansee(struct ucred *u1, struct ucred *u2) 1376a9e0361bSPoul-Henning Kamp { 137791421ba2SRobert Watson int error; 1378a9e0361bSPoul-Henning Kamp 1379ed639720SRobert Watson if ((error = prison_check(u1, u2))) 138091421ba2SRobert Watson return (error); 13818a1d977dSRobert Watson #ifdef MAC 13828a1d977dSRobert Watson if ((error = mac_check_cred_visible(u1, u2))) 13838a1d977dSRobert Watson return (error); 13848a1d977dSRobert Watson #endif 13851b350b45SRobert Watson if ((error = cr_seeotheruids(u1, u2))) 13861b350b45SRobert Watson return (error); 138764d19c2eSRobert Watson if ((error = cr_seeothergids(u1, u2))) 138864d19c2eSRobert Watson return (error); 1389387d2c03SRobert Watson return (0); 1390387d2c03SRobert Watson } 1391387d2c03SRobert Watson 13927fd6a959SRobert Watson /*- 1393f44d9e24SJohn Baldwin * Determine if td "can see" the subject specified by p. 13943b243b72SRobert Watson * Returns: 0 for permitted, an errno value otherwise 1395f44d9e24SJohn Baldwin * Locks: Sufficient locks to protect p->p_ucred must be held. td really 1396f44d9e24SJohn Baldwin * should be curthread. 1397f44d9e24SJohn Baldwin * References: td and p must be valid for the lifetime of the call 13983b243b72SRobert Watson */ 1399a0f75161SRobert Watson int 1400f44d9e24SJohn Baldwin p_cansee(struct thread *td, struct proc *p) 1401ed639720SRobert Watson { 1402ed639720SRobert Watson 140394088977SRobert Watson /* Wrap cr_cansee() for all functionality. */ 1404f44d9e24SJohn Baldwin KASSERT(td == curthread, ("%s: td not curthread", __func__)); 1405f44d9e24SJohn Baldwin PROC_LOCK_ASSERT(p, MA_OWNED); 1406f44d9e24SJohn Baldwin return (cr_cansee(td->td_ucred, p->p_ucred)); 1407ed639720SRobert Watson } 1408ed639720SRobert Watson 140962c45ef4SRobert Watson /* 141062c45ef4SRobert Watson * 'conservative_signals' prevents the delivery of a broad class of 141162c45ef4SRobert Watson * signals by unprivileged processes to processes that have changed their 141262c45ef4SRobert Watson * credentials since the last invocation of execve(). This can prevent 141362c45ef4SRobert Watson * the leakage of cached information or retained privileges as a result 141462c45ef4SRobert Watson * of a common class of signal-related vulnerabilities. However, this 141562c45ef4SRobert Watson * may interfere with some applications that expect to be able to 141662c45ef4SRobert Watson * deliver these signals to peer processes after having given up 141762c45ef4SRobert Watson * privilege. 141862c45ef4SRobert Watson */ 141962c45ef4SRobert Watson static int conservative_signals = 1; 142062c45ef4SRobert Watson SYSCTL_INT(_security_bsd, OID_AUTO, conservative_signals, CTLFLAG_RW, 142162c45ef4SRobert Watson &conservative_signals, 0, "Unprivileged processes prevented from " 142262c45ef4SRobert Watson "sending certain signals to processes whose credentials have changed"); 14237fd6a959SRobert Watson /*- 1424c83f8015SRobert Watson * Determine whether cred may deliver the specified signal to proc. 1425c83f8015SRobert Watson * Returns: 0 for permitted, an errno value otherwise. 1426c83f8015SRobert Watson * Locks: A lock must be held for proc. 1427c83f8015SRobert Watson * References: cred and proc must be valid for the lifetime of the call. 14284c5eb9c3SRobert Watson */ 14294c5eb9c3SRobert Watson int 14301a88a252SMaxim Sobolev cr_cansignal(struct ucred *cred, struct proc *proc, int signum) 1431387d2c03SRobert Watson { 143291421ba2SRobert Watson int error; 1433387d2c03SRobert Watson 1434f44d9e24SJohn Baldwin PROC_LOCK_ASSERT(proc, MA_OWNED); 14354c5eb9c3SRobert Watson /* 1436c83f8015SRobert Watson * Jail semantics limit the scope of signalling to proc in the 1437c83f8015SRobert Watson * same jail as cred, if cred is in jail. 14384c5eb9c3SRobert Watson */ 1439c83f8015SRobert Watson error = prison_check(cred, proc->p_ucred); 1440c83f8015SRobert Watson if (error) 144191421ba2SRobert Watson return (error); 14428a1d977dSRobert Watson #ifdef MAC 14438a1d977dSRobert Watson if ((error = mac_check_proc_signal(cred, proc, signum))) 14448a1d977dSRobert Watson return (error); 14458a1d977dSRobert Watson #endif 144664d19c2eSRobert Watson if ((error = cr_seeotheruids(cred, proc->p_ucred))) 144764d19c2eSRobert Watson return (error); 144864d19c2eSRobert Watson if ((error = cr_seeothergids(cred, proc->p_ucred))) 14491b350b45SRobert Watson return (error); 1450387d2c03SRobert Watson 1451387d2c03SRobert Watson /* 14523b243b72SRobert Watson * UNIX signal semantics depend on the status of the P_SUGID 14533b243b72SRobert Watson * bit on the target process. If the bit is set, then additional 14543b243b72SRobert Watson * restrictions are placed on the set of available signals. 14554c5eb9c3SRobert Watson */ 14561a88a252SMaxim Sobolev if (conservative_signals && (proc->p_flag & P_SUGID)) { 14574c5eb9c3SRobert Watson switch (signum) { 14584c5eb9c3SRobert Watson case 0: 14594c5eb9c3SRobert Watson case SIGKILL: 14604c5eb9c3SRobert Watson case SIGINT: 14614c5eb9c3SRobert Watson case SIGTERM: 146262c45ef4SRobert Watson case SIGALRM: 14634c5eb9c3SRobert Watson case SIGSTOP: 14644c5eb9c3SRobert Watson case SIGTTIN: 14654c5eb9c3SRobert Watson case SIGTTOU: 14664c5eb9c3SRobert Watson case SIGTSTP: 14674c5eb9c3SRobert Watson case SIGHUP: 14684c5eb9c3SRobert Watson case SIGUSR1: 14694c5eb9c3SRobert Watson case SIGUSR2: 14707fd6a959SRobert Watson /* 14717fd6a959SRobert Watson * Generally, permit job and terminal control 14727fd6a959SRobert Watson * signals. 14737fd6a959SRobert Watson */ 14744c5eb9c3SRobert Watson break; 14754c5eb9c3SRobert Watson default: 1476c83f8015SRobert Watson /* Not permitted without privilege. */ 147756f21b9dSColin Percival error = suser_cred(cred, SUSER_ALLOWJAIL); 14784c5eb9c3SRobert Watson if (error) 14794c5eb9c3SRobert Watson return (error); 14804c5eb9c3SRobert Watson } 1481e9e7ff5bSRobert Watson } 1482e9e7ff5bSRobert Watson 14834c5eb9c3SRobert Watson /* 14843b243b72SRobert Watson * Generally, the target credential's ruid or svuid must match the 1485e9e7ff5bSRobert Watson * subject credential's ruid or euid. 14864c5eb9c3SRobert Watson */ 1487c83f8015SRobert Watson if (cred->cr_ruid != proc->p_ucred->cr_ruid && 1488c83f8015SRobert Watson cred->cr_ruid != proc->p_ucred->cr_svuid && 1489c83f8015SRobert Watson cred->cr_uid != proc->p_ucred->cr_ruid && 1490c83f8015SRobert Watson cred->cr_uid != proc->p_ucred->cr_svuid) { 1491c83f8015SRobert Watson /* Not permitted without privilege. */ 149256f21b9dSColin Percival error = suser_cred(cred, SUSER_ALLOWJAIL); 14934c5eb9c3SRobert Watson if (error) 14944c5eb9c3SRobert Watson return (error); 14954c5eb9c3SRobert Watson } 1496387d2c03SRobert Watson 1497387d2c03SRobert Watson return (0); 1498387d2c03SRobert Watson } 1499a9e0361bSPoul-Henning Kamp 1500c83f8015SRobert Watson 1501c83f8015SRobert Watson /*- 1502f44d9e24SJohn Baldwin * Determine whether td may deliver the specified signal to p. 1503c83f8015SRobert Watson * Returns: 0 for permitted, an errno value otherwise 1504f44d9e24SJohn Baldwin * Locks: Sufficient locks to protect various components of td and p 1505f44d9e24SJohn Baldwin * must be held. td must be curthread, and a lock must be 1506f44d9e24SJohn Baldwin * held for p. 1507f44d9e24SJohn Baldwin * References: td and p must be valid for the lifetime of the call 1508c83f8015SRobert Watson */ 1509c83f8015SRobert Watson int 15101a88a252SMaxim Sobolev p_cansignal(struct thread *td, struct proc *p, int signum) 1511c83f8015SRobert Watson { 1512c83f8015SRobert Watson 1513f44d9e24SJohn Baldwin KASSERT(td == curthread, ("%s: td not curthread", __func__)); 1514f44d9e24SJohn Baldwin PROC_LOCK_ASSERT(p, MA_OWNED); 1515f44d9e24SJohn Baldwin if (td->td_proc == p) 1516c83f8015SRobert Watson return (0); 1517c83f8015SRobert Watson 1518c83f8015SRobert Watson /* 1519c83f8015SRobert Watson * UNIX signalling semantics require that processes in the same 1520c83f8015SRobert Watson * session always be able to deliver SIGCONT to one another, 1521c83f8015SRobert Watson * overriding the remaining protections. 1522c83f8015SRobert Watson */ 1523f44d9e24SJohn Baldwin /* XXX: This will require an additional lock of some sort. */ 1524f44d9e24SJohn Baldwin if (signum == SIGCONT && td->td_proc->p_session == p->p_session) 1525c83f8015SRobert Watson return (0); 15264b178336SMaxim Sobolev /* 15274b178336SMaxim Sobolev * Some compat layers use SIGTHR for communications between 15284b178336SMaxim Sobolev * different kernel threads of the same process, so that 15294b178336SMaxim Sobolev * they are expecting that it's always possible to deliver 15304b178336SMaxim Sobolev * it, even for suid applications where cr_cansignal() can 15314b178336SMaxim Sobolev * deny such ability for security consideration. It should be 15324b178336SMaxim Sobolev * pretty safe to do since the only way to create two processes 15334b178336SMaxim Sobolev * with the same p_leader is via rfork(2). 15344b178336SMaxim Sobolev */ 15354b178336SMaxim Sobolev if (signum == SIGTHR && td->td_proc->p_leader != NULL && 15364b178336SMaxim Sobolev td->td_proc->p_leader == p->p_leader) 15374b178336SMaxim Sobolev return (0); 1538c83f8015SRobert Watson 15391a88a252SMaxim Sobolev return (cr_cansignal(td->td_ucred, p, signum)); 1540c83f8015SRobert Watson } 1541c83f8015SRobert Watson 15427fd6a959SRobert Watson /*- 1543f44d9e24SJohn Baldwin * Determine whether td may reschedule p. 15447fd6a959SRobert Watson * Returns: 0 for permitted, an errno value otherwise 1545f44d9e24SJohn Baldwin * Locks: Sufficient locks to protect various components of td and p 1546f44d9e24SJohn Baldwin * must be held. td must be curthread, and a lock must 1547f44d9e24SJohn Baldwin * be held for p. 1548f44d9e24SJohn Baldwin * References: td and p must be valid for the lifetime of the call 15493b243b72SRobert Watson */ 1550a0f75161SRobert Watson int 1551f44d9e24SJohn Baldwin p_cansched(struct thread *td, struct proc *p) 1552387d2c03SRobert Watson { 155391421ba2SRobert Watson int error; 1554387d2c03SRobert Watson 1555f44d9e24SJohn Baldwin KASSERT(td == curthread, ("%s: td not curthread", __func__)); 1556f44d9e24SJohn Baldwin PROC_LOCK_ASSERT(p, MA_OWNED); 1557f44d9e24SJohn Baldwin if (td->td_proc == p) 1558387d2c03SRobert Watson return (0); 1559f44d9e24SJohn Baldwin if ((error = prison_check(td->td_ucred, p->p_ucred))) 156091421ba2SRobert Watson return (error); 15618a1d977dSRobert Watson #ifdef MAC 15628a1d977dSRobert Watson if ((error = mac_check_proc_sched(td->td_ucred, p))) 15638a1d977dSRobert Watson return (error); 15648a1d977dSRobert Watson #endif 1565f44d9e24SJohn Baldwin if ((error = cr_seeotheruids(td->td_ucred, p->p_ucred))) 15661b350b45SRobert Watson return (error); 156764d19c2eSRobert Watson if ((error = cr_seeothergids(td->td_ucred, p->p_ucred))) 156864d19c2eSRobert Watson return (error); 1569f44d9e24SJohn Baldwin if (td->td_ucred->cr_ruid == p->p_ucred->cr_ruid) 1570387d2c03SRobert Watson return (0); 1571f44d9e24SJohn Baldwin if (td->td_ucred->cr_uid == p->p_ucred->cr_ruid) 1572387d2c03SRobert Watson return (0); 157356f21b9dSColin Percival if (suser_cred(td->td_ucred, SUSER_ALLOWJAIL) == 0) 1574387d2c03SRobert Watson return (0); 1575387d2c03SRobert Watson 1576387d2c03SRobert Watson #ifdef CAPABILITIES 157756f21b9dSColin Percival if (!cap_check(NULL, td, CAP_SYS_NICE, SUSER_ALLOWJAIL)) 1578387d2c03SRobert Watson return (0); 1579387d2c03SRobert Watson #endif 1580387d2c03SRobert Watson 1581387d2c03SRobert Watson return (EPERM); 1582387d2c03SRobert Watson } 1583387d2c03SRobert Watson 15843b243b72SRobert Watson /* 15855d476e73SRobert Watson * The 'unprivileged_proc_debug' flag may be used to disable a variety of 15865d476e73SRobert Watson * unprivileged inter-process debugging services, including some procfs 15875d476e73SRobert Watson * functionality, ptrace(), and ktrace(). In the past, inter-process 15885d476e73SRobert Watson * debugging has been involved in a variety of security problems, and sites 15895d476e73SRobert Watson * not requiring the service might choose to disable it when hardening 15905d476e73SRobert Watson * systems. 15913b243b72SRobert Watson * 15923b243b72SRobert Watson * XXX: Should modifying and reading this variable require locking? 1593eb725b4eSRobert Watson * XXX: data declarations should be together near the beginning of the file. 15943b243b72SRobert Watson */ 1595e409590dSRobert Watson static int unprivileged_proc_debug = 1; 1596d0615c64SAndrew R. Reiter SYSCTL_INT(_security_bsd, OID_AUTO, unprivileged_proc_debug, CTLFLAG_RW, 1597eb725b4eSRobert Watson &unprivileged_proc_debug, 0, 15980ef5652eSRobert Watson "Unprivileged processes may use process debugging facilities"); 15990ef5652eSRobert Watson 16007fd6a959SRobert Watson /*- 1601f44d9e24SJohn Baldwin * Determine whether td may debug p. 16027fd6a959SRobert Watson * Returns: 0 for permitted, an errno value otherwise 1603f44d9e24SJohn Baldwin * Locks: Sufficient locks to protect various components of td and p 1604f44d9e24SJohn Baldwin * must be held. td must be curthread, and a lock must 1605f44d9e24SJohn Baldwin * be held for p. 1606f44d9e24SJohn Baldwin * References: td and p must be valid for the lifetime of the call 16073b243b72SRobert Watson */ 1608a0f75161SRobert Watson int 1609f44d9e24SJohn Baldwin p_candebug(struct thread *td, struct proc *p) 1610387d2c03SRobert Watson { 1611eb725b4eSRobert Watson int credentialchanged, error, grpsubset, i, uidsubset; 1612387d2c03SRobert Watson 1613f44d9e24SJohn Baldwin KASSERT(td == curthread, ("%s: td not curthread", __func__)); 1614f44d9e24SJohn Baldwin PROC_LOCK_ASSERT(p, MA_OWNED); 1615e409590dSRobert Watson if (!unprivileged_proc_debug) { 161656f21b9dSColin Percival error = suser_cred(td->td_ucred, SUSER_ALLOWJAIL); 161732d18604SRobert Watson if (error) 161832d18604SRobert Watson return (error); 161932d18604SRobert Watson } 1620f44d9e24SJohn Baldwin if (td->td_proc == p) 162123fad5b6SDag-Erling Smørgrav return (0); 1622f44d9e24SJohn Baldwin if ((error = prison_check(td->td_ucred, p->p_ucred))) 162391421ba2SRobert Watson return (error); 16248a1d977dSRobert Watson #ifdef MAC 16258a1d977dSRobert Watson if ((error = mac_check_proc_debug(td->td_ucred, p))) 16268a1d977dSRobert Watson return (error); 16278a1d977dSRobert Watson #endif 1628f44d9e24SJohn Baldwin if ((error = cr_seeotheruids(td->td_ucred, p->p_ucred))) 16291b350b45SRobert Watson return (error); 163064d19c2eSRobert Watson if ((error = cr_seeothergids(td->td_ucred, p->p_ucred))) 163164d19c2eSRobert Watson return (error); 1632387d2c03SRobert Watson 16337fd6a959SRobert Watson /* 1634f44d9e24SJohn Baldwin * Is p's group set a subset of td's effective group set? This 1635f44d9e24SJohn Baldwin * includes p's egid, group access list, rgid, and svgid. 16367fd6a959SRobert Watson */ 1637db42a33dSRobert Watson grpsubset = 1; 1638f44d9e24SJohn Baldwin for (i = 0; i < p->p_ucred->cr_ngroups; i++) { 1639f44d9e24SJohn Baldwin if (!groupmember(p->p_ucred->cr_groups[i], td->td_ucred)) { 1640db42a33dSRobert Watson grpsubset = 0; 1641db42a33dSRobert Watson break; 1642db42a33dSRobert Watson } 1643db42a33dSRobert Watson } 1644db42a33dSRobert Watson grpsubset = grpsubset && 1645f44d9e24SJohn Baldwin groupmember(p->p_ucred->cr_rgid, td->td_ucred) && 1646f44d9e24SJohn Baldwin groupmember(p->p_ucred->cr_svgid, td->td_ucred); 1647db42a33dSRobert Watson 1648db42a33dSRobert Watson /* 1649f44d9e24SJohn Baldwin * Are the uids present in p's credential equal to td's 1650f44d9e24SJohn Baldwin * effective uid? This includes p's euid, svuid, and ruid. 1651db42a33dSRobert Watson */ 1652f44d9e24SJohn Baldwin uidsubset = (td->td_ucred->cr_uid == p->p_ucred->cr_uid && 1653f44d9e24SJohn Baldwin td->td_ucred->cr_uid == p->p_ucred->cr_svuid && 1654f44d9e24SJohn Baldwin td->td_ucred->cr_uid == p->p_ucred->cr_ruid); 1655db42a33dSRobert Watson 1656db42a33dSRobert Watson /* 1657db42a33dSRobert Watson * Has the credential of the process changed since the last exec()? 1658db42a33dSRobert Watson */ 1659f44d9e24SJohn Baldwin credentialchanged = (p->p_flag & P_SUGID); 1660db42a33dSRobert Watson 1661db42a33dSRobert Watson /* 1662f44d9e24SJohn Baldwin * If p's gids aren't a subset, or the uids aren't a subset, 1663db42a33dSRobert Watson * or the credential has changed, require appropriate privilege 1664f44d9e24SJohn Baldwin * for td to debug p. For POSIX.1e capabilities, this will 1665db42a33dSRobert Watson * require CAP_SYS_PTRACE. 1666db42a33dSRobert Watson */ 1667db42a33dSRobert Watson if (!grpsubset || !uidsubset || credentialchanged) { 166856f21b9dSColin Percival error = suser_cred(td->td_ucred, SUSER_ALLOWJAIL); 166932d18604SRobert Watson if (error) 1670387d2c03SRobert Watson return (error); 16717fd6a959SRobert Watson } 1672387d2c03SRobert Watson 1673eb725b4eSRobert Watson /* Can't trace init when securelevel > 0. */ 1674f44d9e24SJohn Baldwin if (p == initproc) { 1675f44d9e24SJohn Baldwin error = securelevel_gt(td->td_ucred, 0); 16763ca719f1SRobert Watson if (error) 16773ca719f1SRobert Watson return (error); 16783ca719f1SRobert Watson } 1679387d2c03SRobert Watson 16805fab7614SRobert Watson /* 16815fab7614SRobert Watson * Can't trace a process that's currently exec'ing. 16825fab7614SRobert Watson * XXX: Note, this is not a security policy decision, it's a 16835fab7614SRobert Watson * basic correctness/functionality decision. Therefore, this check 16845fab7614SRobert Watson * should be moved to the caller's of p_candebug(). 16855fab7614SRobert Watson */ 1686f44d9e24SJohn Baldwin if ((p->p_flag & P_INEXEC) != 0) 16879ca45e81SDag-Erling Smørgrav return (EAGAIN); 16889ca45e81SDag-Erling Smørgrav 1689387d2c03SRobert Watson return (0); 1690387d2c03SRobert Watson } 1691387d2c03SRobert Watson 169229dc1288SRobert Watson /*- 169329dc1288SRobert Watson * Determine whether the subject represented by cred can "see" a socket. 169429dc1288SRobert Watson * Returns: 0 for permitted, ENOENT otherwise. 169529dc1288SRobert Watson */ 169629dc1288SRobert Watson int 169729dc1288SRobert Watson cr_canseesocket(struct ucred *cred, struct socket *so) 169829dc1288SRobert Watson { 169929dc1288SRobert Watson int error; 170029dc1288SRobert Watson 170129dc1288SRobert Watson error = prison_check(cred, so->so_cred); 170229dc1288SRobert Watson if (error) 170329dc1288SRobert Watson return (ENOENT); 17048a1d977dSRobert Watson #ifdef MAC 1705310e7cebSRobert Watson SOCK_LOCK(so); 17068a1d977dSRobert Watson error = mac_check_socket_visible(cred, so); 1707310e7cebSRobert Watson SOCK_UNLOCK(so); 17088a1d977dSRobert Watson if (error) 17098a1d977dSRobert Watson return (error); 17108a1d977dSRobert Watson #endif 171129dc1288SRobert Watson if (cr_seeotheruids(cred, so->so_cred)) 171229dc1288SRobert Watson return (ENOENT); 171364d19c2eSRobert Watson if (cr_seeothergids(cred, so->so_cred)) 171464d19c2eSRobert Watson return (ENOENT); 171529dc1288SRobert Watson 171629dc1288SRobert Watson return (0); 171729dc1288SRobert Watson } 171829dc1288SRobert Watson 1719a9e0361bSPoul-Henning Kamp /* 1720df8bae1dSRodney W. Grimes * Allocate a zeroed cred structure. 17212bceb0f2SRobert Watson * MPSAFE 1722df8bae1dSRodney W. Grimes */ 1723df8bae1dSRodney W. Grimes struct ucred * 17244c44ad8eSJohn Baldwin crget(void) 1725df8bae1dSRodney W. Grimes { 1726df8bae1dSRodney W. Grimes register struct ucred *cr; 1727df8bae1dSRodney W. Grimes 1728a163d034SWarner Losh MALLOC(cr, struct ucred *, sizeof(*cr), M_CRED, M_WAITOK | M_ZERO); 1729df8bae1dSRodney W. Grimes cr->cr_ref = 1; 1730857d9c60SDon Lewis cr->cr_mtxp = mtx_pool_find(mtxpool_sleep, cr); 173140244964SRobert Watson #ifdef MAC 173240244964SRobert Watson mac_init_cred(cr); 173340244964SRobert Watson #endif 1734df8bae1dSRodney W. Grimes return (cr); 1735df8bae1dSRodney W. Grimes } 1736df8bae1dSRodney W. Grimes 1737df8bae1dSRodney W. Grimes /* 17387fd6a959SRobert Watson * Claim another reference to a ucred structure. 17392bceb0f2SRobert Watson * MPSAFE 17405c3f70d7SAlfred Perlstein */ 1741bd78ceceSJohn Baldwin struct ucred * 17424c44ad8eSJohn Baldwin crhold(struct ucred *cr) 17435c3f70d7SAlfred Perlstein { 17445c3f70d7SAlfred Perlstein 1745e1bca29fSMatthew Dillon mtx_lock(cr->cr_mtxp); 17465c3f70d7SAlfred Perlstein cr->cr_ref++; 1747e1bca29fSMatthew Dillon mtx_unlock(cr->cr_mtxp); 1748bd78ceceSJohn Baldwin return (cr); 17495c3f70d7SAlfred Perlstein } 17505c3f70d7SAlfred Perlstein 17515c3f70d7SAlfred Perlstein /* 1752df8bae1dSRodney W. Grimes * Free a cred structure. 1753df8bae1dSRodney W. Grimes * Throws away space when ref count gets to 0. 17542bceb0f2SRobert Watson * MPSAFE 1755df8bae1dSRodney W. Grimes */ 175626f9a767SRodney W. Grimes void 17574c44ad8eSJohn Baldwin crfree(struct ucred *cr) 1758df8bae1dSRodney W. Grimes { 1759e1bca29fSMatthew Dillon struct mtx *mtxp = cr->cr_mtxp; 17601e5d626aSAlfred Perlstein 1761e1bca29fSMatthew Dillon mtx_lock(mtxp); 1762e04670b7SAlfred Perlstein KASSERT(cr->cr_ref > 0, ("bad ucred refcount: %d", cr->cr_ref)); 1763f535380cSDon Lewis if (--cr->cr_ref == 0) { 1764646e29ccSRobert Watson mtx_unlock(mtxp); 1765f535380cSDon Lewis /* 1766f535380cSDon Lewis * Some callers of crget(), such as nfs_statfs(), 1767f535380cSDon Lewis * allocate a temporary credential, but don't 1768f535380cSDon Lewis * allocate a uidinfo structure. 1769f535380cSDon Lewis */ 1770f535380cSDon Lewis if (cr->cr_uidinfo != NULL) 1771f535380cSDon Lewis uifree(cr->cr_uidinfo); 1772823c224eSRobert Watson if (cr->cr_ruidinfo != NULL) 1773823c224eSRobert Watson uifree(cr->cr_ruidinfo); 177491421ba2SRobert Watson /* 177591421ba2SRobert Watson * Free a prison, if any. 177691421ba2SRobert Watson */ 177791421ba2SRobert Watson if (jailed(cr)) 177891421ba2SRobert Watson prison_free(cr->cr_prison); 177940244964SRobert Watson #ifdef MAC 178040244964SRobert Watson mac_destroy_cred(cr); 178140244964SRobert Watson #endif 17827f05b035SAlfred Perlstein FREE(cr, M_CRED); 1783e1bca29fSMatthew Dillon } else { 1784e1bca29fSMatthew Dillon mtx_unlock(mtxp); 1785e1bca29fSMatthew Dillon } 1786df8bae1dSRodney W. Grimes } 1787df8bae1dSRodney W. Grimes 1788df8bae1dSRodney W. Grimes /* 1789bd78ceceSJohn Baldwin * Check to see if this ucred is shared. 17902bceb0f2SRobert Watson * MPSAFE 1791df8bae1dSRodney W. Grimes */ 1792bd78ceceSJohn Baldwin int 17934c44ad8eSJohn Baldwin crshared(struct ucred *cr) 1794df8bae1dSRodney W. Grimes { 1795bd78ceceSJohn Baldwin int shared; 1796df8bae1dSRodney W. Grimes 1797e1bca29fSMatthew Dillon mtx_lock(cr->cr_mtxp); 1798bd78ceceSJohn Baldwin shared = (cr->cr_ref > 1); 1799e1bca29fSMatthew Dillon mtx_unlock(cr->cr_mtxp); 1800bd78ceceSJohn Baldwin return (shared); 18011e5d626aSAlfred Perlstein } 1802bd78ceceSJohn Baldwin 1803bd78ceceSJohn Baldwin /* 1804bd78ceceSJohn Baldwin * Copy a ucred's contents from a template. Does not block. 18052bceb0f2SRobert Watson * MPSAFE 1806bd78ceceSJohn Baldwin */ 1807bd78ceceSJohn Baldwin void 18084c44ad8eSJohn Baldwin crcopy(struct ucred *dest, struct ucred *src) 1809bd78ceceSJohn Baldwin { 1810bd78ceceSJohn Baldwin 1811bd78ceceSJohn Baldwin KASSERT(crshared(dest) == 0, ("crcopy of shared ucred")); 1812bd78ceceSJohn Baldwin bcopy(&src->cr_startcopy, &dest->cr_startcopy, 1813bd78ceceSJohn Baldwin (unsigned)((caddr_t)&src->cr_endcopy - 1814bd78ceceSJohn Baldwin (caddr_t)&src->cr_startcopy)); 1815bd78ceceSJohn Baldwin uihold(dest->cr_uidinfo); 1816bd78ceceSJohn Baldwin uihold(dest->cr_ruidinfo); 1817bd78ceceSJohn Baldwin if (jailed(dest)) 1818bd78ceceSJohn Baldwin prison_hold(dest->cr_prison); 181940244964SRobert Watson #ifdef MAC 182056d9e932SRobert Watson mac_copy_cred(src, dest); 182140244964SRobert Watson #endif 1822df8bae1dSRodney W. Grimes } 1823df8bae1dSRodney W. Grimes 1824df8bae1dSRodney W. Grimes /* 1825df8bae1dSRodney W. Grimes * Dup cred struct to a new held one. 18262bceb0f2SRobert Watson * MPSAFE 1827df8bae1dSRodney W. Grimes */ 1828df8bae1dSRodney W. Grimes struct ucred * 18294c44ad8eSJohn Baldwin crdup(struct ucred *cr) 1830df8bae1dSRodney W. Grimes { 1831df8bae1dSRodney W. Grimes struct ucred *newcr; 1832df8bae1dSRodney W. Grimes 1833bd78ceceSJohn Baldwin newcr = crget(); 1834bd78ceceSJohn Baldwin crcopy(newcr, cr); 1835df8bae1dSRodney W. Grimes return (newcr); 1836df8bae1dSRodney W. Grimes } 1837df8bae1dSRodney W. Grimes 1838df8bae1dSRodney W. Grimes /* 183976183f34SDima Dorfman * Fill in a struct xucred based on a struct ucred. 18402bceb0f2SRobert Watson * MPSAFE 184176183f34SDima Dorfman */ 184276183f34SDima Dorfman void 18434c44ad8eSJohn Baldwin cru2x(struct ucred *cr, struct xucred *xcr) 184476183f34SDima Dorfman { 184576183f34SDima Dorfman 184676183f34SDima Dorfman bzero(xcr, sizeof(*xcr)); 184776183f34SDima Dorfman xcr->cr_version = XUCRED_VERSION; 184876183f34SDima Dorfman xcr->cr_uid = cr->cr_uid; 184976183f34SDima Dorfman xcr->cr_ngroups = cr->cr_ngroups; 185076183f34SDima Dorfman bcopy(cr->cr_groups, xcr->cr_groups, sizeof(cr->cr_groups)); 185176183f34SDima Dorfman } 185276183f34SDima Dorfman 185376183f34SDima Dorfman /* 18542eb927e2SJulian Elischer * small routine to swap a thread's current ucred for the correct one 18552eb927e2SJulian Elischer * taken from the process. 18562bceb0f2SRobert Watson * MPSAFE 18572eb927e2SJulian Elischer */ 18582eb927e2SJulian Elischer void 18592eb927e2SJulian Elischer cred_update_thread(struct thread *td) 18602eb927e2SJulian Elischer { 18612eb927e2SJulian Elischer struct proc *p; 186265e3406dSJohn Baldwin struct ucred *cred; 18632eb927e2SJulian Elischer 18642eb927e2SJulian Elischer p = td->td_proc; 186565e3406dSJohn Baldwin cred = td->td_ucred; 18662eb927e2SJulian Elischer PROC_LOCK(p); 18672eb927e2SJulian Elischer td->td_ucred = crhold(p->p_ucred); 18682eb927e2SJulian Elischer PROC_UNLOCK(p); 186965e3406dSJohn Baldwin if (cred != NULL) 187065e3406dSJohn Baldwin crfree(cred); 18712eb927e2SJulian Elischer } 18722eb927e2SJulian Elischer 18732eb927e2SJulian Elischer /* 1874df8bae1dSRodney W. Grimes * Get login name, if available. 1875df8bae1dSRodney W. Grimes */ 1876d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 1877df8bae1dSRodney W. Grimes struct getlogin_args { 1878df8bae1dSRodney W. Grimes char *namebuf; 1879df8bae1dSRodney W. Grimes u_int namelen; 1880df8bae1dSRodney W. Grimes }; 1881d2d3e875SBruce Evans #endif 1882835a82eeSMatthew Dillon /* 1883835a82eeSMatthew Dillon * MPSAFE 1884835a82eeSMatthew Dillon */ 1885df8bae1dSRodney W. Grimes /* ARGSUSED */ 188626f9a767SRodney W. Grimes int 18874c44ad8eSJohn Baldwin getlogin(struct thread *td, struct getlogin_args *uap) 1888df8bae1dSRodney W. Grimes { 1889835a82eeSMatthew Dillon int error; 1890f591779bSSeigo Tanimura char login[MAXLOGNAME]; 1891b40ce416SJulian Elischer struct proc *p = td->td_proc; 1892df8bae1dSRodney W. Grimes 189330cf3ac4SAndrey A. Chernov if (uap->namelen > MAXLOGNAME) 189453490b76SAndrey A. Chernov uap->namelen = MAXLOGNAME; 1895f591779bSSeigo Tanimura PROC_LOCK(p); 1896f591779bSSeigo Tanimura SESS_LOCK(p->p_session); 1897f591779bSSeigo Tanimura bcopy(p->p_session->s_login, login, uap->namelen); 1898f591779bSSeigo Tanimura SESS_UNLOCK(p->p_session); 1899f591779bSSeigo Tanimura PROC_UNLOCK(p); 19007f05b035SAlfred Perlstein error = copyout(login, uap->namebuf, uap->namelen); 1901835a82eeSMatthew Dillon return(error); 1902df8bae1dSRodney W. Grimes } 1903df8bae1dSRodney W. Grimes 1904df8bae1dSRodney W. Grimes /* 1905df8bae1dSRodney W. Grimes * Set login name. 1906df8bae1dSRodney W. Grimes */ 1907d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 1908df8bae1dSRodney W. Grimes struct setlogin_args { 1909df8bae1dSRodney W. Grimes char *namebuf; 1910df8bae1dSRodney W. Grimes }; 1911d2d3e875SBruce Evans #endif 1912835a82eeSMatthew Dillon /* 1913835a82eeSMatthew Dillon * MPSAFE 1914835a82eeSMatthew Dillon */ 1915df8bae1dSRodney W. Grimes /* ARGSUSED */ 191626f9a767SRodney W. Grimes int 19174c44ad8eSJohn Baldwin setlogin(struct thread *td, struct setlogin_args *uap) 1918df8bae1dSRodney W. Grimes { 1919b40ce416SJulian Elischer struct proc *p = td->td_proc; 1920df8bae1dSRodney W. Grimes int error; 1921964ca0caSAndrey A. Chernov char logintmp[MAXLOGNAME]; 1922df8bae1dSRodney W. Grimes 192356f21b9dSColin Percival error = suser_cred(td->td_ucred, SUSER_ALLOWJAIL); 192407f3485dSJohn Baldwin if (error) 192507f3485dSJohn Baldwin return (error); 19267f05b035SAlfred Perlstein error = copyinstr(uap->namebuf, logintmp, sizeof(logintmp), NULL); 1927eb725b4eSRobert Watson if (error == ENAMETOOLONG) 1928df8bae1dSRodney W. Grimes error = EINVAL; 1929f591779bSSeigo Tanimura else if (!error) { 1930f591779bSSeigo Tanimura PROC_LOCK(p); 1931f591779bSSeigo Tanimura SESS_LOCK(p->p_session); 1932f591779bSSeigo Tanimura (void) memcpy(p->p_session->s_login, logintmp, 1933964ca0caSAndrey A. Chernov sizeof(logintmp)); 1934f591779bSSeigo Tanimura SESS_UNLOCK(p->p_session); 1935f591779bSSeigo Tanimura PROC_UNLOCK(p); 1936f591779bSSeigo Tanimura } 1937df8bae1dSRodney W. Grimes return (error); 1938df8bae1dSRodney W. Grimes } 1939d5f81602SSean Eric Fagan 1940d5f81602SSean Eric Fagan void 19414c44ad8eSJohn Baldwin setsugid(struct proc *p) 1942d5f81602SSean Eric Fagan { 1943f2102dadSAlfred Perlstein 1944f2102dadSAlfred Perlstein PROC_LOCK_ASSERT(p, MA_OWNED); 1945d5f81602SSean Eric Fagan p->p_flag |= P_SUGID; 194689361835SSean Eric Fagan if (!(p->p_pfsflags & PF_ISUGID)) 1947d5f81602SSean Eric Fagan p->p_stops = 0; 1948d5f81602SSean Eric Fagan } 1949f535380cSDon Lewis 19507fd6a959SRobert Watson /*- 19517fd6a959SRobert Watson * Change a process's effective uid. 1952b1fc0ec1SRobert Watson * Side effects: newcred->cr_uid and newcred->cr_uidinfo will be modified. 1953b1fc0ec1SRobert Watson * References: newcred must be an exclusive credential reference for the 1954b1fc0ec1SRobert Watson * duration of the call. 1955f535380cSDon Lewis */ 1956f535380cSDon Lewis void 19571419eacbSAlfred Perlstein change_euid(struct ucred *newcred, struct uidinfo *euip) 1958f535380cSDon Lewis { 1959f535380cSDon Lewis 19601419eacbSAlfred Perlstein newcred->cr_uid = euip->ui_uid; 19611419eacbSAlfred Perlstein uihold(euip); 1962b1fc0ec1SRobert Watson uifree(newcred->cr_uidinfo); 19631419eacbSAlfred Perlstein newcred->cr_uidinfo = euip; 1964f535380cSDon Lewis } 1965f535380cSDon Lewis 19667fd6a959SRobert Watson /*- 19677fd6a959SRobert Watson * Change a process's effective gid. 1968b1fc0ec1SRobert Watson * Side effects: newcred->cr_gid will be modified. 1969b1fc0ec1SRobert Watson * References: newcred must be an exclusive credential reference for the 1970b1fc0ec1SRobert Watson * duration of the call. 1971f535380cSDon Lewis */ 1972810bfc8eSAndrew Gallatin void 19734c44ad8eSJohn Baldwin change_egid(struct ucred *newcred, gid_t egid) 1974b1fc0ec1SRobert Watson { 1975b1fc0ec1SRobert Watson 1976b1fc0ec1SRobert Watson newcred->cr_groups[0] = egid; 1977b1fc0ec1SRobert Watson } 1978b1fc0ec1SRobert Watson 19797fd6a959SRobert Watson /*- 19807fd6a959SRobert Watson * Change a process's real uid. 1981b1fc0ec1SRobert Watson * Side effects: newcred->cr_ruid will be updated, newcred->cr_ruidinfo 1982b1fc0ec1SRobert Watson * will be updated, and the old and new cr_ruidinfo proc 1983b1fc0ec1SRobert Watson * counts will be updated. 1984b1fc0ec1SRobert Watson * References: newcred must be an exclusive credential reference for the 1985b1fc0ec1SRobert Watson * duration of the call. 1986b1fc0ec1SRobert Watson */ 1987b1fc0ec1SRobert Watson void 19881419eacbSAlfred Perlstein change_ruid(struct ucred *newcred, struct uidinfo *ruip) 1989f535380cSDon Lewis { 1990f535380cSDon Lewis 1991b1fc0ec1SRobert Watson (void)chgproccnt(newcred->cr_ruidinfo, -1, 0); 19921419eacbSAlfred Perlstein newcred->cr_ruid = ruip->ui_uid; 19931419eacbSAlfred Perlstein uihold(ruip); 1994b1fc0ec1SRobert Watson uifree(newcred->cr_ruidinfo); 19951419eacbSAlfred Perlstein newcred->cr_ruidinfo = ruip; 1996b1fc0ec1SRobert Watson (void)chgproccnt(newcred->cr_ruidinfo, 1, 0); 1997b1fc0ec1SRobert Watson } 1998b1fc0ec1SRobert Watson 19997fd6a959SRobert Watson /*- 20007fd6a959SRobert Watson * Change a process's real gid. 2001b1fc0ec1SRobert Watson * Side effects: newcred->cr_rgid will be updated. 2002b1fc0ec1SRobert Watson * References: newcred must be an exclusive credential reference for the 2003b1fc0ec1SRobert Watson * duration of the call. 2004b1fc0ec1SRobert Watson */ 2005b1fc0ec1SRobert Watson void 20064c44ad8eSJohn Baldwin change_rgid(struct ucred *newcred, gid_t rgid) 2007b1fc0ec1SRobert Watson { 2008b1fc0ec1SRobert Watson 2009b1fc0ec1SRobert Watson newcred->cr_rgid = rgid; 2010b1fc0ec1SRobert Watson } 2011b1fc0ec1SRobert Watson 20127fd6a959SRobert Watson /*- 20137fd6a959SRobert Watson * Change a process's saved uid. 2014b1fc0ec1SRobert Watson * Side effects: newcred->cr_svuid will be updated. 2015b1fc0ec1SRobert Watson * References: newcred must be an exclusive credential reference for the 2016b1fc0ec1SRobert Watson * duration of the call. 2017b1fc0ec1SRobert Watson */ 2018b1fc0ec1SRobert Watson void 20194c44ad8eSJohn Baldwin change_svuid(struct ucred *newcred, uid_t svuid) 2020b1fc0ec1SRobert Watson { 2021b1fc0ec1SRobert Watson 2022b1fc0ec1SRobert Watson newcred->cr_svuid = svuid; 2023b1fc0ec1SRobert Watson } 2024b1fc0ec1SRobert Watson 20257fd6a959SRobert Watson /*- 20267fd6a959SRobert Watson * Change a process's saved gid. 2027b1fc0ec1SRobert Watson * Side effects: newcred->cr_svgid will be updated. 2028b1fc0ec1SRobert Watson * References: newcred must be an exclusive credential reference for the 2029b1fc0ec1SRobert Watson * duration of the call. 2030b1fc0ec1SRobert Watson */ 2031b1fc0ec1SRobert Watson void 20324c44ad8eSJohn Baldwin change_svgid(struct ucred *newcred, gid_t svgid) 2033b1fc0ec1SRobert Watson { 2034b1fc0ec1SRobert Watson 2035b1fc0ec1SRobert Watson newcred->cr_svgid = svgid; 2036f535380cSDon Lewis } 2037