1df8bae1dSRodney W. Grimes /* 2df8bae1dSRodney W. Grimes * Copyright (c) 1982, 1986, 1989, 1990, 1991, 1993 3df8bae1dSRodney W. Grimes * The Regents of the University of California. All rights reserved. 43b243b72SRobert Watson * Copyright (c) 2000, 2001 Robert N. M. Watson. All rights reserved. 5df8bae1dSRodney W. Grimes * (c) UNIX System Laboratories, Inc. 6df8bae1dSRodney W. Grimes * All or some portions of this file are derived from material licensed 7df8bae1dSRodney W. Grimes * to the University of California by American Telephone and Telegraph 8df8bae1dSRodney W. Grimes * Co. or Unix System Laboratories, Inc. and are reproduced herein with 9df8bae1dSRodney W. Grimes * the permission of UNIX System Laboratories, Inc. 10df8bae1dSRodney W. Grimes * 11df8bae1dSRodney W. Grimes * Redistribution and use in source and binary forms, with or without 12df8bae1dSRodney W. Grimes * modification, are permitted provided that the following conditions 13df8bae1dSRodney W. Grimes * are met: 14df8bae1dSRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 15df8bae1dSRodney W. Grimes * notice, this list of conditions and the following disclaimer. 16df8bae1dSRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 17df8bae1dSRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 18df8bae1dSRodney W. Grimes * documentation and/or other materials provided with the distribution. 19df8bae1dSRodney W. Grimes * 3. All advertising materials mentioning features or use of this software 20df8bae1dSRodney W. Grimes * must display the following acknowledgement: 21df8bae1dSRodney W. Grimes * This product includes software developed by the University of 22df8bae1dSRodney W. Grimes * California, Berkeley and its contributors. 23df8bae1dSRodney W. Grimes * 4. Neither the name of the University nor the names of its contributors 24df8bae1dSRodney W. Grimes * may be used to endorse or promote products derived from this software 25df8bae1dSRodney W. Grimes * without specific prior written permission. 26df8bae1dSRodney W. Grimes * 27df8bae1dSRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 28df8bae1dSRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 29df8bae1dSRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 30df8bae1dSRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 31df8bae1dSRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 32df8bae1dSRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 33df8bae1dSRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 34df8bae1dSRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 35df8bae1dSRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 36df8bae1dSRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 37df8bae1dSRodney W. Grimes * SUCH DAMAGE. 38df8bae1dSRodney W. Grimes * 39df8bae1dSRodney W. Grimes * @(#)kern_prot.c 8.6 (Berkeley) 1/21/94 40c3aac50fSPeter Wemm * $FreeBSD$ 41df8bae1dSRodney W. Grimes */ 42df8bae1dSRodney W. Grimes 43df8bae1dSRodney W. Grimes /* 44df8bae1dSRodney W. Grimes * System calls related to processes and protection 45df8bae1dSRodney W. Grimes */ 46df8bae1dSRodney W. Grimes 475591b823SEivind Eklund #include "opt_compat.h" 48130d0157SRobert Watson #include "opt_global.h" 495591b823SEivind Eklund 50df8bae1dSRodney W. Grimes #include <sys/param.h> 51df8bae1dSRodney W. Grimes #include <sys/systm.h> 52fb919e4dSMark Murray #include <sys/acct.h> 531c5bb3eaSPeter Wemm #include <sys/kernel.h> 5498f03f90SJake Burkholder #include <sys/lock.h> 55fb919e4dSMark Murray #include <sys/mutex.h> 56df8bae1dSRodney W. Grimes #include <sys/proc.h> 57fb919e4dSMark Murray #include <sys/sysproto.h> 58df8bae1dSRodney W. Grimes #include <sys/malloc.h> 59d5f81602SSean Eric Fagan #include <sys/pioctl.h> 60f535380cSDon Lewis #include <sys/resourcevar.h> 61579f4eb4SRobert Watson #include <sys/sysctl.h> 6291421ba2SRobert Watson #include <sys/jail.h> 63df8bae1dSRodney W. Grimes 64a1c995b6SPoul-Henning Kamp static MALLOC_DEFINE(M_CRED, "cred", "credentials"); 65a1c995b6SPoul-Henning Kamp 660ef5652eSRobert Watson SYSCTL_NODE(_kern, OID_AUTO, security, CTLFLAG_RW, 0, 670ef5652eSRobert Watson "Kernel security policy"); 680ef5652eSRobert Watson 69d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 70ad7507e2SSteven Wallace struct getpid_args { 71df8bae1dSRodney W. Grimes int dummy; 72df8bae1dSRodney W. Grimes }; 73d2d3e875SBruce Evans #endif 74df8bae1dSRodney W. Grimes 7536e9f877SMatthew Dillon /* 76835a82eeSMatthew Dillon * getpid 7736e9f877SMatthew Dillon */ 7898f03f90SJake Burkholder 79835a82eeSMatthew Dillon /* 80835a82eeSMatthew Dillon * MPSAFE 81835a82eeSMatthew Dillon */ 82df8bae1dSRodney W. Grimes /* ARGSUSED */ 8326f9a767SRodney W. Grimes int 84b40ce416SJulian Elischer getpid(td, uap) 85b40ce416SJulian Elischer struct thread *td; 86ad7507e2SSteven Wallace struct getpid_args *uap; 87df8bae1dSRodney W. Grimes { 88b40ce416SJulian Elischer struct proc *p = td->td_proc; 89d23f5958SMatthew Dillon int s; 90df8bae1dSRodney W. Grimes 91d23f5958SMatthew Dillon s = mtx_lock_giant(kern_giant_proc); 92b40ce416SJulian Elischer td->td_retval[0] = p->p_pid; 93df8bae1dSRodney W. Grimes #if defined(COMPAT_43) || defined(COMPAT_SUNOS) 94bae3a80bSJohn Baldwin PROC_LOCK(p); 95b40ce416SJulian Elischer td->td_retval[1] = p->p_pptr->p_pid; 96bae3a80bSJohn Baldwin PROC_UNLOCK(p); 97df8bae1dSRodney W. Grimes #endif 98d23f5958SMatthew Dillon mtx_unlock_giant(s); 99df8bae1dSRodney W. Grimes return (0); 100df8bae1dSRodney W. Grimes } 101df8bae1dSRodney W. Grimes 10298f03f90SJake Burkholder /* 103835a82eeSMatthew Dillon * getppid 10498f03f90SJake Burkholder */ 10598f03f90SJake Burkholder 106d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 107ad7507e2SSteven Wallace struct getppid_args { 108ad7507e2SSteven Wallace int dummy; 109ad7507e2SSteven Wallace }; 110d2d3e875SBruce Evans #endif 111835a82eeSMatthew Dillon /* 112835a82eeSMatthew Dillon * MPSAFE 113835a82eeSMatthew Dillon */ 114df8bae1dSRodney W. Grimes /* ARGSUSED */ 11526f9a767SRodney W. Grimes int 116b40ce416SJulian Elischer getppid(td, uap) 117b40ce416SJulian Elischer struct thread *td; 118ad7507e2SSteven Wallace struct getppid_args *uap; 119df8bae1dSRodney W. Grimes { 120b40ce416SJulian Elischer struct proc *p = td->td_proc; 121d23f5958SMatthew Dillon int s; 122df8bae1dSRodney W. Grimes 123d23f5958SMatthew Dillon s = mtx_lock_giant(kern_giant_proc); 124bae3a80bSJohn Baldwin PROC_LOCK(p); 125b40ce416SJulian Elischer td->td_retval[0] = p->p_pptr->p_pid; 126bae3a80bSJohn Baldwin PROC_UNLOCK(p); 127d23f5958SMatthew Dillon mtx_unlock_giant(s); 128df8bae1dSRodney W. Grimes return (0); 129df8bae1dSRodney W. Grimes } 130df8bae1dSRodney W. Grimes 13136e9f877SMatthew Dillon /* 13236e9f877SMatthew Dillon * Get process group ID; note that POSIX getpgrp takes no parameter 13336e9f877SMatthew Dillon * 13436e9f877SMatthew Dillon * MP SAFE 13536e9f877SMatthew Dillon */ 136d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 137ad7507e2SSteven Wallace struct getpgrp_args { 138ad7507e2SSteven Wallace int dummy; 139ad7507e2SSteven Wallace }; 140d2d3e875SBruce Evans #endif 141835a82eeSMatthew Dillon /* 142835a82eeSMatthew Dillon * MPSAFE 143835a82eeSMatthew Dillon */ 14426f9a767SRodney W. Grimes int 145b40ce416SJulian Elischer getpgrp(td, uap) 146b40ce416SJulian Elischer struct thread *td; 147ad7507e2SSteven Wallace struct getpgrp_args *uap; 148df8bae1dSRodney W. Grimes { 149b40ce416SJulian Elischer struct proc *p = td->td_proc; 150df8bae1dSRodney W. Grimes 151835a82eeSMatthew Dillon mtx_lock(&Giant); 152b40ce416SJulian Elischer td->td_retval[0] = p->p_pgrp->pg_id; 153835a82eeSMatthew Dillon mtx_unlock(&Giant); 154df8bae1dSRodney W. Grimes return (0); 155df8bae1dSRodney W. Grimes } 156df8bae1dSRodney W. Grimes 1571a5018a0SPeter Wemm /* Get an arbitary pid's process group id */ 1581a5018a0SPeter Wemm #ifndef _SYS_SYSPROTO_H_ 1591a5018a0SPeter Wemm struct getpgid_args { 1601a5018a0SPeter Wemm pid_t pid; 1611a5018a0SPeter Wemm }; 1621a5018a0SPeter Wemm #endif 1631a5018a0SPeter Wemm 164835a82eeSMatthew Dillon /* 165835a82eeSMatthew Dillon * MPSAFE 166835a82eeSMatthew Dillon */ 1671a5018a0SPeter Wemm int 168b40ce416SJulian Elischer getpgid(td, uap) 169b40ce416SJulian Elischer struct thread *td; 1701a5018a0SPeter Wemm struct getpgid_args *uap; 1711a5018a0SPeter Wemm { 172b40ce416SJulian Elischer struct proc *p = td->td_proc; 17365de0c7aSDon Lewis struct proc *pt; 174835a82eeSMatthew Dillon int error = 0; 175d23f5958SMatthew Dillon int s; 17665de0c7aSDon Lewis 177d23f5958SMatthew Dillon s = mtx_lock_giant(kern_giant_proc); 1781a5018a0SPeter Wemm if (uap->pid == 0) 179b40ce416SJulian Elischer td->td_retval[0] = p->p_pgrp->pg_id; 1806a90c862SJohn Baldwin else if ((pt = pfind(uap->pid)) == NULL) 181835a82eeSMatthew Dillon error = ESRCH; 1826a90c862SJohn Baldwin else { 1836a90c862SJohn Baldwin error = p_cansee(p, pt); 1846a90c862SJohn Baldwin if (error == 0) 185b40ce416SJulian Elischer td->td_retval[0] = pt->p_pgrp->pg_id; 18633a9ed9dSJohn Baldwin PROC_UNLOCK(pt); 18733a9ed9dSJohn Baldwin } 188d23f5958SMatthew Dillon mtx_unlock_giant(s); 189835a82eeSMatthew Dillon return (error); 1901a5018a0SPeter Wemm } 1911a5018a0SPeter Wemm 1921a5018a0SPeter Wemm /* 1931a5018a0SPeter Wemm * Get an arbitary pid's session id. 1941a5018a0SPeter Wemm */ 1951a5018a0SPeter Wemm #ifndef _SYS_SYSPROTO_H_ 1961a5018a0SPeter Wemm struct getsid_args { 1971a5018a0SPeter Wemm pid_t pid; 1981a5018a0SPeter Wemm }; 1991a5018a0SPeter Wemm #endif 2001a5018a0SPeter Wemm 201835a82eeSMatthew Dillon /* 202835a82eeSMatthew Dillon * MPSAFE 203835a82eeSMatthew Dillon */ 2041a5018a0SPeter Wemm int 205b40ce416SJulian Elischer getsid(td, uap) 206b40ce416SJulian Elischer struct thread *td; 2071a5018a0SPeter Wemm struct getsid_args *uap; 2081a5018a0SPeter Wemm { 209b40ce416SJulian Elischer struct proc *p = td->td_proc; 21065de0c7aSDon Lewis struct proc *pt; 211835a82eeSMatthew Dillon int error = 0; 21265de0c7aSDon Lewis 213835a82eeSMatthew Dillon mtx_lock(&Giant); 2146a90c862SJohn Baldwin if (uap->pid == 0) 215b40ce416SJulian Elischer td->td_retval[0] = p->p_session->s_sid; 2166a90c862SJohn Baldwin else if ((pt = pfind(uap->pid)) == NULL) 217835a82eeSMatthew Dillon error = ESRCH; 2186a90c862SJohn Baldwin else { 2196a90c862SJohn Baldwin error = p_cansee(p, pt); 2206a90c862SJohn Baldwin if (error == 0) 221b40ce416SJulian Elischer td->td_retval[0] = pt->p_session->s_sid; 22233a9ed9dSJohn Baldwin PROC_UNLOCK(pt); 22333a9ed9dSJohn Baldwin } 224835a82eeSMatthew Dillon mtx_unlock(&Giant); 225835a82eeSMatthew Dillon return (error); 2261a5018a0SPeter Wemm } 2271a5018a0SPeter Wemm 2281a5018a0SPeter Wemm 2297c8fdcbdSMatthew Dillon /* 2307c8fdcbdSMatthew Dillon * getuid() - MP SAFE 2317c8fdcbdSMatthew Dillon */ 232d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 233ad7507e2SSteven Wallace struct getuid_args { 234ad7507e2SSteven Wallace int dummy; 235ad7507e2SSteven Wallace }; 236d2d3e875SBruce Evans #endif 237ad7507e2SSteven Wallace 238835a82eeSMatthew Dillon /* 239835a82eeSMatthew Dillon * MPSAFE 240835a82eeSMatthew Dillon */ 241df8bae1dSRodney W. Grimes /* ARGSUSED */ 24226f9a767SRodney W. Grimes int 243b40ce416SJulian Elischer getuid(td, uap) 244b40ce416SJulian Elischer struct thread *td; 245ad7507e2SSteven Wallace struct getuid_args *uap; 246df8bae1dSRodney W. Grimes { 247b40ce416SJulian Elischer struct proc *p = td->td_proc; 248df8bae1dSRodney W. Grimes 249835a82eeSMatthew Dillon mtx_lock(&Giant); 250b40ce416SJulian Elischer td->td_retval[0] = p->p_ucred->cr_ruid; 251df8bae1dSRodney W. Grimes #if defined(COMPAT_43) || defined(COMPAT_SUNOS) 252b40ce416SJulian Elischer td->td_retval[1] = p->p_ucred->cr_uid; 253df8bae1dSRodney W. Grimes #endif 254835a82eeSMatthew Dillon mtx_unlock(&Giant); 255df8bae1dSRodney W. Grimes return (0); 256df8bae1dSRodney W. Grimes } 257df8bae1dSRodney W. Grimes 2587c8fdcbdSMatthew Dillon /* 2597c8fdcbdSMatthew Dillon * geteuid() - MP SAFE 2607c8fdcbdSMatthew Dillon */ 261d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 262ad7507e2SSteven Wallace struct geteuid_args { 263ad7507e2SSteven Wallace int dummy; 264ad7507e2SSteven Wallace }; 265d2d3e875SBruce Evans #endif 266ad7507e2SSteven Wallace 267df8bae1dSRodney W. Grimes /* ARGSUSED */ 26826f9a767SRodney W. Grimes int 269b40ce416SJulian Elischer geteuid(td, uap) 270b40ce416SJulian Elischer struct thread *td; 271ad7507e2SSteven Wallace struct geteuid_args *uap; 272df8bae1dSRodney W. Grimes { 273835a82eeSMatthew Dillon mtx_lock(&Giant); 274b40ce416SJulian Elischer td->td_retval[0] = td->td_proc->p_ucred->cr_uid; 275835a82eeSMatthew Dillon mtx_unlock(&Giant); 276df8bae1dSRodney W. Grimes return (0); 277df8bae1dSRodney W. Grimes } 278df8bae1dSRodney W. Grimes 2797c8fdcbdSMatthew Dillon /* 2807c8fdcbdSMatthew Dillon * getgid() - MP SAFE 2817c8fdcbdSMatthew Dillon */ 282d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 283ad7507e2SSteven Wallace struct getgid_args { 284ad7507e2SSteven Wallace int dummy; 285ad7507e2SSteven Wallace }; 286d2d3e875SBruce Evans #endif 287ad7507e2SSteven Wallace 288835a82eeSMatthew Dillon /* 289835a82eeSMatthew Dillon * MPSAFE 290835a82eeSMatthew Dillon */ 291df8bae1dSRodney W. Grimes /* ARGSUSED */ 29226f9a767SRodney W. Grimes int 293b40ce416SJulian Elischer getgid(td, uap) 294b40ce416SJulian Elischer struct thread *td; 295ad7507e2SSteven Wallace struct getgid_args *uap; 296df8bae1dSRodney W. Grimes { 297b40ce416SJulian Elischer struct proc *p = td->td_proc; 298df8bae1dSRodney W. Grimes 299835a82eeSMatthew Dillon mtx_lock(&Giant); 300b40ce416SJulian Elischer td->td_retval[0] = p->p_ucred->cr_rgid; 301df8bae1dSRodney W. Grimes #if defined(COMPAT_43) || defined(COMPAT_SUNOS) 302b40ce416SJulian Elischer td->td_retval[1] = p->p_ucred->cr_groups[0]; 303df8bae1dSRodney W. Grimes #endif 304835a82eeSMatthew Dillon mtx_unlock(&Giant); 305df8bae1dSRodney W. Grimes return (0); 306df8bae1dSRodney W. Grimes } 307df8bae1dSRodney W. Grimes 308df8bae1dSRodney W. Grimes /* 309df8bae1dSRodney W. Grimes * Get effective group ID. The "egid" is groups[0], and could be obtained 310df8bae1dSRodney W. Grimes * via getgroups. This syscall exists because it is somewhat painful to do 311df8bae1dSRodney W. Grimes * correctly in a library function. 312df8bae1dSRodney W. Grimes */ 313d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 314ad7507e2SSteven Wallace struct getegid_args { 315ad7507e2SSteven Wallace int dummy; 316ad7507e2SSteven Wallace }; 317d2d3e875SBruce Evans #endif 318ad7507e2SSteven Wallace 319835a82eeSMatthew Dillon /* 320835a82eeSMatthew Dillon * MPSAFE 321835a82eeSMatthew Dillon */ 322df8bae1dSRodney W. Grimes /* ARGSUSED */ 32326f9a767SRodney W. Grimes int 324b40ce416SJulian Elischer getegid(td, uap) 325b40ce416SJulian Elischer struct thread *td; 326ad7507e2SSteven Wallace struct getegid_args *uap; 327df8bae1dSRodney W. Grimes { 328b40ce416SJulian Elischer struct proc *p = td->td_proc; 329df8bae1dSRodney W. Grimes 330835a82eeSMatthew Dillon mtx_lock(&Giant); 331b40ce416SJulian Elischer td->td_retval[0] = p->p_ucred->cr_groups[0]; 332835a82eeSMatthew Dillon mtx_unlock(&Giant); 333df8bae1dSRodney W. Grimes return (0); 334df8bae1dSRodney W. Grimes } 335df8bae1dSRodney W. Grimes 336d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 337df8bae1dSRodney W. Grimes struct getgroups_args { 338df8bae1dSRodney W. Grimes u_int gidsetsize; 339df8bae1dSRodney W. Grimes gid_t *gidset; 340df8bae1dSRodney W. Grimes }; 341d2d3e875SBruce Evans #endif 342835a82eeSMatthew Dillon /* 343835a82eeSMatthew Dillon * MPSAFE 344835a82eeSMatthew Dillon */ 34526f9a767SRodney W. Grimes int 346b40ce416SJulian Elischer getgroups(td, uap) 347b40ce416SJulian Elischer struct thread *td; 348df8bae1dSRodney W. Grimes register struct getgroups_args *uap; 349df8bae1dSRodney W. Grimes { 350835a82eeSMatthew Dillon struct ucred *cred; 351b40ce416SJulian Elischer struct proc *p = td->td_proc; 352b1fc0ec1SRobert Watson u_int ngrp; 353835a82eeSMatthew Dillon int error = 0; 354df8bae1dSRodney W. Grimes 355835a82eeSMatthew Dillon mtx_lock(&Giant); 356835a82eeSMatthew Dillon cred = p->p_ucred; 357df8bae1dSRodney W. Grimes if ((ngrp = uap->gidsetsize) == 0) { 358b40ce416SJulian Elischer td->td_retval[0] = cred->cr_ngroups; 359835a82eeSMatthew Dillon error = 0; 360835a82eeSMatthew Dillon goto done2; 361df8bae1dSRodney W. Grimes } 362835a82eeSMatthew Dillon if (ngrp < cred->cr_ngroups) { 363835a82eeSMatthew Dillon error = EINVAL; 364835a82eeSMatthew Dillon goto done2; 365835a82eeSMatthew Dillon } 366b1fc0ec1SRobert Watson ngrp = cred->cr_ngroups; 367b1fc0ec1SRobert Watson if ((error = copyout((caddr_t)cred->cr_groups, 368835a82eeSMatthew Dillon (caddr_t)uap->gidset, ngrp * sizeof(gid_t)))) { 369835a82eeSMatthew Dillon goto done2; 370835a82eeSMatthew Dillon } 371b40ce416SJulian Elischer td->td_retval[0] = ngrp; 372835a82eeSMatthew Dillon done2: 373835a82eeSMatthew Dillon mtx_unlock(&Giant); 374835a82eeSMatthew Dillon return (error); 375df8bae1dSRodney W. Grimes } 376df8bae1dSRodney W. Grimes 377d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 37882970b81SBruce Evans struct setsid_args { 379ad7507e2SSteven Wallace int dummy; 380ad7507e2SSteven Wallace }; 381d2d3e875SBruce Evans #endif 382ad7507e2SSteven Wallace 383835a82eeSMatthew Dillon /* 384835a82eeSMatthew Dillon * MPSAFE 385835a82eeSMatthew Dillon */ 386df8bae1dSRodney W. Grimes /* ARGSUSED */ 38726f9a767SRodney W. Grimes int 388b40ce416SJulian Elischer setsid(td, uap) 389b40ce416SJulian Elischer register struct thread *td; 39082970b81SBruce Evans struct setsid_args *uap; 391df8bae1dSRodney W. Grimes { 392835a82eeSMatthew Dillon int error; 393b40ce416SJulian Elischer struct proc *p = td->td_proc; 394df8bae1dSRodney W. Grimes 395835a82eeSMatthew Dillon mtx_lock(&Giant); 396df8bae1dSRodney W. Grimes if (p->p_pgid == p->p_pid || pgfind(p->p_pid)) { 397835a82eeSMatthew Dillon error = EPERM; 398df8bae1dSRodney W. Grimes } else { 399df8bae1dSRodney W. Grimes (void)enterpgrp(p, p->p_pid, 1); 400b40ce416SJulian Elischer td->td_retval[0] = p->p_pid; 401835a82eeSMatthew Dillon error = 0; 402df8bae1dSRodney W. Grimes } 403835a82eeSMatthew Dillon mtx_unlock(&Giant); 404835a82eeSMatthew Dillon return (error); 405df8bae1dSRodney W. Grimes } 406df8bae1dSRodney W. Grimes 407df8bae1dSRodney W. Grimes /* 408df8bae1dSRodney W. Grimes * set process group (setpgid/old setpgrp) 409df8bae1dSRodney W. Grimes * 410df8bae1dSRodney W. Grimes * caller does setpgid(targpid, targpgid) 411df8bae1dSRodney W. Grimes * 412df8bae1dSRodney W. Grimes * pid must be caller or child of caller (ESRCH) 413df8bae1dSRodney W. Grimes * if a child 414df8bae1dSRodney W. Grimes * pid must be in same session (EPERM) 415df8bae1dSRodney W. Grimes * pid can't have done an exec (EACCES) 416df8bae1dSRodney W. Grimes * if pgid != pid 417df8bae1dSRodney W. Grimes * there must exist some pid in same session having pgid (EPERM) 418df8bae1dSRodney W. Grimes * pid must not be session leader (EPERM) 419df8bae1dSRodney W. Grimes */ 420d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 421df8bae1dSRodney W. Grimes struct setpgid_args { 422df8bae1dSRodney W. Grimes int pid; /* target process id */ 423df8bae1dSRodney W. Grimes int pgid; /* target pgrp id */ 424df8bae1dSRodney W. Grimes }; 425d2d3e875SBruce Evans #endif 426835a82eeSMatthew Dillon /* 427835a82eeSMatthew Dillon * MPSAFE 428835a82eeSMatthew Dillon */ 429df8bae1dSRodney W. Grimes /* ARGSUSED */ 43026f9a767SRodney W. Grimes int 431b40ce416SJulian Elischer setpgid(td, uap) 432b40ce416SJulian Elischer struct thread *td; 433df8bae1dSRodney W. Grimes register struct setpgid_args *uap; 434df8bae1dSRodney W. Grimes { 435b40ce416SJulian Elischer struct proc *curp = td->td_proc; 436df8bae1dSRodney W. Grimes register struct proc *targp; /* target process */ 437df8bae1dSRodney W. Grimes register struct pgrp *pgrp; /* target pgrp */ 438eb9e5c1dSRobert Watson int error; 439df8bae1dSRodney W. Grimes 44078f64bccSBruce Evans if (uap->pgid < 0) 44178f64bccSBruce Evans return (EINVAL); 442835a82eeSMatthew Dillon 443835a82eeSMatthew Dillon mtx_lock(&Giant); 444835a82eeSMatthew Dillon 445df8bae1dSRodney W. Grimes if (uap->pid != 0 && uap->pid != curp->p_pid) { 44633a9ed9dSJohn Baldwin if ((targp = pfind(uap->pid)) == NULL || !inferior(targp)) { 44733a9ed9dSJohn Baldwin if (targp) 44833a9ed9dSJohn Baldwin PROC_UNLOCK(targp); 449835a82eeSMatthew Dillon error = ESRCH; 450835a82eeSMatthew Dillon goto done2; 45133a9ed9dSJohn Baldwin } 452a0f75161SRobert Watson if ((error = p_cansee(curproc, targp))) { 45333a9ed9dSJohn Baldwin PROC_UNLOCK(targp); 454835a82eeSMatthew Dillon goto done2; 45533a9ed9dSJohn Baldwin } 45633a9ed9dSJohn Baldwin if (targp->p_pgrp == NULL || 45733a9ed9dSJohn Baldwin targp->p_session != curp->p_session) { 45833a9ed9dSJohn Baldwin PROC_UNLOCK(targp); 459835a82eeSMatthew Dillon error = EPERM; 460835a82eeSMatthew Dillon goto done2; 46133a9ed9dSJohn Baldwin } 46233a9ed9dSJohn Baldwin if (targp->p_flag & P_EXEC) { 46333a9ed9dSJohn Baldwin PROC_UNLOCK(targp); 464835a82eeSMatthew Dillon error = EACCES; 465835a82eeSMatthew Dillon goto done2; 46633a9ed9dSJohn Baldwin } 46733a9ed9dSJohn Baldwin } else { 468df8bae1dSRodney W. Grimes targp = curp; 46933a9ed9dSJohn Baldwin PROC_LOCK(curp); /* XXX: not needed */ 47033a9ed9dSJohn Baldwin } 47133a9ed9dSJohn Baldwin if (SESS_LEADER(targp)) { 47233a9ed9dSJohn Baldwin PROC_UNLOCK(targp); 473835a82eeSMatthew Dillon error = EPERM; 474835a82eeSMatthew Dillon goto done2; 47533a9ed9dSJohn Baldwin } 476835a82eeSMatthew Dillon if (uap->pgid == 0) { 477df8bae1dSRodney W. Grimes uap->pgid = targp->p_pid; 478835a82eeSMatthew Dillon } else if (uap->pgid != targp->p_pid) { 479df8bae1dSRodney W. Grimes if ((pgrp = pgfind(uap->pgid)) == 0 || 48033a9ed9dSJohn Baldwin pgrp->pg_session != curp->p_session) { 48133a9ed9dSJohn Baldwin PROC_UNLOCK(targp); 482835a82eeSMatthew Dillon error = EPERM; 483835a82eeSMatthew Dillon goto done2; 484835a82eeSMatthew Dillon } 48533a9ed9dSJohn Baldwin } 48633a9ed9dSJohn Baldwin /* XXX: We should probably hold the lock across enterpgrp. */ 48733a9ed9dSJohn Baldwin PROC_UNLOCK(targp); 488835a82eeSMatthew Dillon error = enterpgrp(targp, uap->pgid, 0); 489835a82eeSMatthew Dillon done2: 490835a82eeSMatthew Dillon mtx_unlock(&Giant); 491835a82eeSMatthew Dillon return (error); 492df8bae1dSRodney W. Grimes } 493df8bae1dSRodney W. Grimes 494a08f4bf6SPeter Wemm /* 495a08f4bf6SPeter Wemm * Use the clause in B.4.2.2 that allows setuid/setgid to be 4.2/4.3BSD 4962fa72ea7SJeroen Ruigrok van der Werven * compatible. It says that setting the uid/gid to euid/egid is a special 497a08f4bf6SPeter Wemm * case of "appropriate privilege". Once the rules are expanded out, this 498a08f4bf6SPeter Wemm * basically means that setuid(nnn) sets all three id's, in all permitted 499a08f4bf6SPeter Wemm * cases unless _POSIX_SAVED_IDS is enabled. In that case, setuid(getuid()) 500a08f4bf6SPeter Wemm * does not set the saved id - this is dangerous for traditional BSD 501a08f4bf6SPeter Wemm * programs. For this reason, we *really* do not want to set 502a08f4bf6SPeter Wemm * _POSIX_SAVED_IDS and do not want to clear POSIX_APPENDIX_B_4_2_2. 503a08f4bf6SPeter Wemm */ 504a08f4bf6SPeter Wemm #define POSIX_APPENDIX_B_4_2_2 505a08f4bf6SPeter Wemm 506d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 507df8bae1dSRodney W. Grimes struct setuid_args { 508df8bae1dSRodney W. Grimes uid_t uid; 509df8bae1dSRodney W. Grimes }; 510d2d3e875SBruce Evans #endif 511835a82eeSMatthew Dillon /* 512835a82eeSMatthew Dillon * MPSAFE 513835a82eeSMatthew Dillon */ 514df8bae1dSRodney W. Grimes /* ARGSUSED */ 51526f9a767SRodney W. Grimes int 516b40ce416SJulian Elischer setuid(td, uap) 517b40ce416SJulian Elischer struct thread *td; 518df8bae1dSRodney W. Grimes struct setuid_args *uap; 519df8bae1dSRodney W. Grimes { 520b40ce416SJulian Elischer struct proc *p = td->td_proc; 521b1fc0ec1SRobert Watson struct ucred *newcred, *oldcred; 522b1fc0ec1SRobert Watson uid_t uid; 523835a82eeSMatthew Dillon int error = 0; 524df8bae1dSRodney W. Grimes 525b1fc0ec1SRobert Watson uid = uap->uid; 526b1fc0ec1SRobert Watson oldcred = p->p_ucred; 527835a82eeSMatthew Dillon mtx_lock(&Giant); 528835a82eeSMatthew Dillon 529a08f4bf6SPeter Wemm /* 530a08f4bf6SPeter Wemm * See if we have "permission" by POSIX 1003.1 rules. 531a08f4bf6SPeter Wemm * 532a08f4bf6SPeter Wemm * Note that setuid(geteuid()) is a special case of 533a08f4bf6SPeter Wemm * "appropriate privileges" in appendix B.4.2.2. We need 5342fa72ea7SJeroen Ruigrok van der Werven * to use this clause to be compatible with traditional BSD 535a08f4bf6SPeter Wemm * semantics. Basically, it means that "setuid(xx)" sets all 536a08f4bf6SPeter Wemm * three id's (assuming you have privs). 537a08f4bf6SPeter Wemm * 538a08f4bf6SPeter Wemm * Notes on the logic. We do things in three steps. 539a08f4bf6SPeter Wemm * 1: We determine if the euid is going to change, and do EPERM 540a08f4bf6SPeter Wemm * right away. We unconditionally change the euid later if this 541a08f4bf6SPeter Wemm * test is satisfied, simplifying that part of the logic. 542a08f4bf6SPeter Wemm * 2: We determine if the real and/or saved uid's are going to 543a08f4bf6SPeter Wemm * change. Determined by compile options. 544a08f4bf6SPeter Wemm * 3: Change euid last. (after tests in #2 for "appropriate privs") 545a08f4bf6SPeter Wemm */ 546b1fc0ec1SRobert Watson if (uid != oldcred->cr_ruid && /* allow setuid(getuid()) */ 5473f246666SAndrey A. Chernov #ifdef _POSIX_SAVED_IDS 548b1fc0ec1SRobert Watson uid != oldcred->cr_svuid && /* allow setuid(saved gid) */ 549a08f4bf6SPeter Wemm #endif 550a08f4bf6SPeter Wemm #ifdef POSIX_APPENDIX_B_4_2_2 /* Use BSD-compat clause from B.4.2.2 */ 551b1fc0ec1SRobert Watson uid != oldcred->cr_uid && /* allow setuid(geteuid()) */ 5523f246666SAndrey A. Chernov #endif 553b1fc0ec1SRobert Watson (error = suser_xxx(oldcred, NULL, PRISON_ROOT))) 554835a82eeSMatthew Dillon goto done2; 555a08f4bf6SPeter Wemm 556b1fc0ec1SRobert Watson newcred = crdup(oldcred); 557a08f4bf6SPeter Wemm #ifdef _POSIX_SAVED_IDS 558df8bae1dSRodney W. Grimes /* 559a08f4bf6SPeter Wemm * Do we have "appropriate privileges" (are we root or uid == euid) 560a08f4bf6SPeter Wemm * If so, we are changing the real uid and/or saved uid. 561df8bae1dSRodney W. Grimes */ 5623f246666SAndrey A. Chernov if ( 563a08f4bf6SPeter Wemm #ifdef POSIX_APPENDIX_B_4_2_2 /* Use the clause from B.4.2.2 */ 564b1fc0ec1SRobert Watson uid == oldcred->cr_uid || 5653f246666SAndrey A. Chernov #endif 566b1fc0ec1SRobert Watson suser_xxx(oldcred, NULL, PRISON_ROOT) == 0) /* we are using privs */ 567a08f4bf6SPeter Wemm #endif 568a08f4bf6SPeter Wemm { 569a08f4bf6SPeter Wemm /* 570f535380cSDon Lewis * Set the real uid and transfer proc count to new user. 571a08f4bf6SPeter Wemm */ 572b1fc0ec1SRobert Watson if (uid != oldcred->cr_ruid) { 573b1fc0ec1SRobert Watson change_ruid(newcred, uid); 574f535380cSDon Lewis setsugid(p); 575d3cdb93dSAndrey A. Chernov } 576a08f4bf6SPeter Wemm /* 577a08f4bf6SPeter Wemm * Set saved uid 578a08f4bf6SPeter Wemm * 579a08f4bf6SPeter Wemm * XXX always set saved uid even if not _POSIX_SAVED_IDS, as 580a08f4bf6SPeter Wemm * the security of seteuid() depends on it. B.4.2.2 says it 581a08f4bf6SPeter Wemm * is important that we should do this. 582a08f4bf6SPeter Wemm */ 583b1fc0ec1SRobert Watson if (uid != oldcred->cr_svuid) { 584b1fc0ec1SRobert Watson change_svuid(newcred, uid); 585d5f81602SSean Eric Fagan setsugid(p); 586a08f4bf6SPeter Wemm } 587a08f4bf6SPeter Wemm } 588a08f4bf6SPeter Wemm 589a08f4bf6SPeter Wemm /* 590a08f4bf6SPeter Wemm * In all permitted cases, we are changing the euid. 591a08f4bf6SPeter Wemm * Copy credentials so other references do not see our changes. 592a08f4bf6SPeter Wemm */ 593b1fc0ec1SRobert Watson if (uid != oldcred->cr_uid) { 594b1fc0ec1SRobert Watson change_euid(newcred, uid); 595d5f81602SSean Eric Fagan setsugid(p); 596a08f4bf6SPeter Wemm } 597b1fc0ec1SRobert Watson p->p_ucred = newcred; 598b1fc0ec1SRobert Watson crfree(oldcred); 599835a82eeSMatthew Dillon done2: 600835a82eeSMatthew Dillon mtx_unlock(&Giant); 601835a82eeSMatthew Dillon return (error); 602df8bae1dSRodney W. Grimes } 603df8bae1dSRodney W. Grimes 604d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 605df8bae1dSRodney W. Grimes struct seteuid_args { 606df8bae1dSRodney W. Grimes uid_t euid; 607df8bae1dSRodney W. Grimes }; 608d2d3e875SBruce Evans #endif 609835a82eeSMatthew Dillon /* 610835a82eeSMatthew Dillon * MPSAFE 611835a82eeSMatthew Dillon */ 612df8bae1dSRodney W. Grimes /* ARGSUSED */ 61326f9a767SRodney W. Grimes int 614b40ce416SJulian Elischer seteuid(td, uap) 615b40ce416SJulian Elischer struct thread *td; 616df8bae1dSRodney W. Grimes struct seteuid_args *uap; 617df8bae1dSRodney W. Grimes { 618b40ce416SJulian Elischer struct proc *p = td->td_proc; 619b1fc0ec1SRobert Watson struct ucred *newcred, *oldcred; 620b1fc0ec1SRobert Watson uid_t euid; 621835a82eeSMatthew Dillon int error = 0; 622df8bae1dSRodney W. Grimes 623df8bae1dSRodney W. Grimes euid = uap->euid; 624835a82eeSMatthew Dillon 625835a82eeSMatthew Dillon mtx_lock(&Giant); 626b1fc0ec1SRobert Watson oldcred = p->p_ucred; 627b1fc0ec1SRobert Watson if (euid != oldcred->cr_ruid && /* allow seteuid(getuid()) */ 628b1fc0ec1SRobert Watson euid != oldcred->cr_svuid && /* allow seteuid(saved uid) */ 629835a82eeSMatthew Dillon (error = suser_xxx(oldcred, NULL, PRISON_ROOT))) { 630835a82eeSMatthew Dillon goto done2; 631835a82eeSMatthew Dillon } 632df8bae1dSRodney W. Grimes /* 633df8bae1dSRodney W. Grimes * Everything's okay, do it. Copy credentials so other references do 634df8bae1dSRodney W. Grimes * not see our changes. 635df8bae1dSRodney W. Grimes */ 636b1fc0ec1SRobert Watson newcred = crdup(oldcred); 637b1fc0ec1SRobert Watson if (oldcred->cr_uid != euid) { 638b1fc0ec1SRobert Watson change_euid(newcred, euid); 639d5f81602SSean Eric Fagan setsugid(p); 640229a15f0SPeter Wemm } 641b1fc0ec1SRobert Watson p->p_ucred = newcred; 642b1fc0ec1SRobert Watson crfree(oldcred); 643835a82eeSMatthew Dillon done2: 644835a82eeSMatthew Dillon mtx_unlock(&Giant); 645835a82eeSMatthew Dillon return (error); 646df8bae1dSRodney W. Grimes } 647df8bae1dSRodney W. Grimes 648d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 649df8bae1dSRodney W. Grimes struct setgid_args { 650df8bae1dSRodney W. Grimes gid_t gid; 651df8bae1dSRodney W. Grimes }; 652d2d3e875SBruce Evans #endif 653835a82eeSMatthew Dillon /* 654835a82eeSMatthew Dillon * MPSAFE 655835a82eeSMatthew Dillon */ 656df8bae1dSRodney W. Grimes /* ARGSUSED */ 65726f9a767SRodney W. Grimes int 658b40ce416SJulian Elischer setgid(td, uap) 659b40ce416SJulian Elischer struct thread *td; 660df8bae1dSRodney W. Grimes struct setgid_args *uap; 661df8bae1dSRodney W. Grimes { 662b40ce416SJulian Elischer struct proc *p = td->td_proc; 663b1fc0ec1SRobert Watson struct ucred *newcred, *oldcred; 664b1fc0ec1SRobert Watson gid_t gid; 665835a82eeSMatthew Dillon int error = 0; 666df8bae1dSRodney W. Grimes 667b1fc0ec1SRobert Watson gid = uap->gid; 668835a82eeSMatthew Dillon 669835a82eeSMatthew Dillon mtx_lock(&Giant); 670b1fc0ec1SRobert Watson oldcred = p->p_ucred; 671a08f4bf6SPeter Wemm /* 672a08f4bf6SPeter Wemm * See if we have "permission" by POSIX 1003.1 rules. 673a08f4bf6SPeter Wemm * 674a08f4bf6SPeter Wemm * Note that setgid(getegid()) is a special case of 675a08f4bf6SPeter Wemm * "appropriate privileges" in appendix B.4.2.2. We need 6762fa72ea7SJeroen Ruigrok van der Werven * to use this clause to be compatible with traditional BSD 677a08f4bf6SPeter Wemm * semantics. Basically, it means that "setgid(xx)" sets all 678a08f4bf6SPeter Wemm * three id's (assuming you have privs). 679a08f4bf6SPeter Wemm * 680a08f4bf6SPeter Wemm * For notes on the logic here, see setuid() above. 681a08f4bf6SPeter Wemm */ 682b1fc0ec1SRobert Watson if (gid != oldcred->cr_rgid && /* allow setgid(getgid()) */ 6833f246666SAndrey A. Chernov #ifdef _POSIX_SAVED_IDS 684b1fc0ec1SRobert Watson gid != oldcred->cr_svgid && /* allow setgid(saved gid) */ 685a08f4bf6SPeter Wemm #endif 686a08f4bf6SPeter Wemm #ifdef POSIX_APPENDIX_B_4_2_2 /* Use BSD-compat clause from B.4.2.2 */ 687b1fc0ec1SRobert Watson gid != oldcred->cr_groups[0] && /* allow setgid(getegid()) */ 6883f246666SAndrey A. Chernov #endif 689835a82eeSMatthew Dillon (error = suser_xxx(oldcred, NULL, PRISON_ROOT))) { 690835a82eeSMatthew Dillon goto done2; 691835a82eeSMatthew Dillon } 692a08f4bf6SPeter Wemm 693b1fc0ec1SRobert Watson newcred = crdup(oldcred); 694a08f4bf6SPeter Wemm #ifdef _POSIX_SAVED_IDS 695a08f4bf6SPeter Wemm /* 696a08f4bf6SPeter Wemm * Do we have "appropriate privileges" (are we root or gid == egid) 697a08f4bf6SPeter Wemm * If so, we are changing the real uid and saved gid. 698a08f4bf6SPeter Wemm */ 699a08f4bf6SPeter Wemm if ( 700a08f4bf6SPeter Wemm #ifdef POSIX_APPENDIX_B_4_2_2 /* use the clause from B.4.2.2 */ 701b1fc0ec1SRobert Watson gid == oldcred->cr_groups[0] || 702a08f4bf6SPeter Wemm #endif 703b1fc0ec1SRobert Watson suser_xxx(oldcred, NULL, PRISON_ROOT) == 0) /* we are using privs */ 704a08f4bf6SPeter Wemm #endif 705a08f4bf6SPeter Wemm { 706a08f4bf6SPeter Wemm /* 707a08f4bf6SPeter Wemm * Set real gid 708a08f4bf6SPeter Wemm */ 709b1fc0ec1SRobert Watson if (oldcred->cr_rgid != gid) { 710b1fc0ec1SRobert Watson change_rgid(newcred, gid); 711d5f81602SSean Eric Fagan setsugid(p); 712a08f4bf6SPeter Wemm } 713a08f4bf6SPeter Wemm /* 714a08f4bf6SPeter Wemm * Set saved gid 715a08f4bf6SPeter Wemm * 716a08f4bf6SPeter Wemm * XXX always set saved gid even if not _POSIX_SAVED_IDS, as 717a08f4bf6SPeter Wemm * the security of setegid() depends on it. B.4.2.2 says it 718a08f4bf6SPeter Wemm * is important that we should do this. 719a08f4bf6SPeter Wemm */ 720b1fc0ec1SRobert Watson if (oldcred->cr_svgid != gid) { 721b1fc0ec1SRobert Watson change_svgid(newcred, gid); 722d5f81602SSean Eric Fagan setsugid(p); 723a08f4bf6SPeter Wemm } 724a08f4bf6SPeter Wemm } 725a08f4bf6SPeter Wemm /* 726a08f4bf6SPeter Wemm * In all cases permitted cases, we are changing the egid. 727a08f4bf6SPeter Wemm * Copy credentials so other references do not see our changes. 728a08f4bf6SPeter Wemm */ 729b1fc0ec1SRobert Watson if (oldcred->cr_groups[0] != gid) { 730b1fc0ec1SRobert Watson change_egid(newcred, gid); 731d5f81602SSean Eric Fagan setsugid(p); 732a08f4bf6SPeter Wemm } 733b1fc0ec1SRobert Watson p->p_ucred = newcred; 734b1fc0ec1SRobert Watson crfree(oldcred); 735835a82eeSMatthew Dillon done2: 736835a82eeSMatthew Dillon mtx_unlock(&Giant); 737835a82eeSMatthew Dillon return (error); 738df8bae1dSRodney W. Grimes } 739df8bae1dSRodney W. Grimes 740d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 741df8bae1dSRodney W. Grimes struct setegid_args { 742df8bae1dSRodney W. Grimes gid_t egid; 743df8bae1dSRodney W. Grimes }; 744d2d3e875SBruce Evans #endif 745835a82eeSMatthew Dillon /* 746835a82eeSMatthew Dillon * MPSAFE 747835a82eeSMatthew Dillon */ 748df8bae1dSRodney W. Grimes /* ARGSUSED */ 74926f9a767SRodney W. Grimes int 750b40ce416SJulian Elischer setegid(td, uap) 751b40ce416SJulian Elischer struct thread *td; 752df8bae1dSRodney W. Grimes struct setegid_args *uap; 753df8bae1dSRodney W. Grimes { 754b40ce416SJulian Elischer struct proc *p = td->td_proc; 755b1fc0ec1SRobert Watson struct ucred *newcred, *oldcred; 756b1fc0ec1SRobert Watson gid_t egid; 757835a82eeSMatthew Dillon int error = 0; 758df8bae1dSRodney W. Grimes 759df8bae1dSRodney W. Grimes egid = uap->egid; 760835a82eeSMatthew Dillon 761835a82eeSMatthew Dillon mtx_lock(&Giant); 762b1fc0ec1SRobert Watson oldcred = p->p_ucred; 763b1fc0ec1SRobert Watson if (egid != oldcred->cr_rgid && /* allow setegid(getgid()) */ 764b1fc0ec1SRobert Watson egid != oldcred->cr_svgid && /* allow setegid(saved gid) */ 765835a82eeSMatthew Dillon (error = suser_xxx(oldcred, NULL, PRISON_ROOT))) { 766835a82eeSMatthew Dillon goto done2; 767835a82eeSMatthew Dillon } 768b1fc0ec1SRobert Watson newcred = crdup(oldcred); 769b1fc0ec1SRobert Watson if (oldcred->cr_groups[0] != egid) { 770b1fc0ec1SRobert Watson change_egid(newcred, egid); 771d5f81602SSean Eric Fagan setsugid(p); 772229a15f0SPeter Wemm } 773b1fc0ec1SRobert Watson p->p_ucred = newcred; 774b1fc0ec1SRobert Watson crfree(oldcred); 775835a82eeSMatthew Dillon done2: 776835a82eeSMatthew Dillon mtx_unlock(&Giant); 777835a82eeSMatthew Dillon return (error); 778df8bae1dSRodney W. Grimes } 779df8bae1dSRodney W. Grimes 780d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 781df8bae1dSRodney W. Grimes struct setgroups_args { 782df8bae1dSRodney W. Grimes u_int gidsetsize; 783df8bae1dSRodney W. Grimes gid_t *gidset; 784df8bae1dSRodney W. Grimes }; 785d2d3e875SBruce Evans #endif 786835a82eeSMatthew Dillon /* 787835a82eeSMatthew Dillon * MPSAFE 788835a82eeSMatthew Dillon */ 789df8bae1dSRodney W. Grimes /* ARGSUSED */ 79026f9a767SRodney W. Grimes int 791b40ce416SJulian Elischer setgroups(td, uap) 792b40ce416SJulian Elischer struct thread *td; 793df8bae1dSRodney W. Grimes struct setgroups_args *uap; 794df8bae1dSRodney W. Grimes { 795b40ce416SJulian Elischer struct proc *p = td->td_proc; 796b1fc0ec1SRobert Watson struct ucred *newcred, *oldcred; 797b1fc0ec1SRobert Watson u_int ngrp; 798df8bae1dSRodney W. Grimes int error; 799df8bae1dSRodney W. Grimes 800835a82eeSMatthew Dillon mtx_lock(&Giant); 801835a82eeSMatthew Dillon 8023956a170SDavid Greenman ngrp = uap->gidsetsize; 803b1fc0ec1SRobert Watson oldcred = p->p_ucred; 804b1fc0ec1SRobert Watson if ((error = suser_xxx(oldcred, NULL, PRISON_ROOT))) 805835a82eeSMatthew Dillon goto done2; 806835a82eeSMatthew Dillon if (ngrp > NGROUPS) { 807835a82eeSMatthew Dillon error = EINVAL; 808835a82eeSMatthew Dillon goto done2; 809835a82eeSMatthew Dillon } 8108a5d815aSPeter Wemm /* 8118a5d815aSPeter Wemm * XXX A little bit lazy here. We could test if anything has 8128a5d815aSPeter Wemm * changed before crcopy() and setting P_SUGID. 8138a5d815aSPeter Wemm */ 814b1fc0ec1SRobert Watson newcred = crdup(oldcred); 8158a5d815aSPeter Wemm if (ngrp < 1) { 8168a5d815aSPeter Wemm /* 8178a5d815aSPeter Wemm * setgroups(0, NULL) is a legitimate way of clearing the 8188a5d815aSPeter Wemm * groups vector on non-BSD systems (which generally do not 8198a5d815aSPeter Wemm * have the egid in the groups[0]). We risk security holes 8208a5d815aSPeter Wemm * when running non-BSD software if we do not do the same. 8218a5d815aSPeter Wemm */ 822b1fc0ec1SRobert Watson newcred->cr_ngroups = 1; 8238a5d815aSPeter Wemm } else { 824bb56ec4aSPoul-Henning Kamp if ((error = copyin((caddr_t)uap->gidset, 825b1fc0ec1SRobert Watson (caddr_t)newcred->cr_groups, ngrp * sizeof(gid_t)))) { 826b1fc0ec1SRobert Watson crfree(newcred); 827835a82eeSMatthew Dillon goto done2; 828b1fc0ec1SRobert Watson } 829b1fc0ec1SRobert Watson newcred->cr_ngroups = ngrp; 8308a5d815aSPeter Wemm } 831d5f81602SSean Eric Fagan setsugid(p); 832b1fc0ec1SRobert Watson p->p_ucred = newcred; 833b1fc0ec1SRobert Watson crfree(oldcred); 834835a82eeSMatthew Dillon done2: 835835a82eeSMatthew Dillon mtx_unlock(&Giant); 836835a82eeSMatthew Dillon return (error); 837df8bae1dSRodney W. Grimes } 838df8bae1dSRodney W. Grimes 839d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 840df8bae1dSRodney W. Grimes struct setreuid_args { 84100999cd6SAndrey A. Chernov uid_t ruid; 84200999cd6SAndrey A. Chernov uid_t euid; 843df8bae1dSRodney W. Grimes }; 844d2d3e875SBruce Evans #endif 845835a82eeSMatthew Dillon /* 846835a82eeSMatthew Dillon * MPSAFE 847835a82eeSMatthew Dillon */ 848df8bae1dSRodney W. Grimes /* ARGSUSED */ 84926f9a767SRodney W. Grimes int 850b40ce416SJulian Elischer setreuid(td, uap) 851b40ce416SJulian Elischer register struct thread *td; 852df8bae1dSRodney W. Grimes struct setreuid_args *uap; 853df8bae1dSRodney W. Grimes { 854b40ce416SJulian Elischer struct proc *p = td->td_proc; 855b1fc0ec1SRobert Watson struct ucred *newcred, *oldcred; 856b1fc0ec1SRobert Watson uid_t ruid, euid; 857835a82eeSMatthew Dillon int error = 0; 858df8bae1dSRodney W. Grimes 85900999cd6SAndrey A. Chernov ruid = uap->ruid; 86000999cd6SAndrey A. Chernov euid = uap->euid; 861835a82eeSMatthew Dillon 862835a82eeSMatthew Dillon mtx_lock(&Giant); 863835a82eeSMatthew Dillon 864b1fc0ec1SRobert Watson oldcred = p->p_ucred; 865b1fc0ec1SRobert Watson if (((ruid != (uid_t)-1 && ruid != oldcred->cr_ruid && 866b1fc0ec1SRobert Watson ruid != oldcred->cr_svuid) || 867b1fc0ec1SRobert Watson (euid != (uid_t)-1 && euid != oldcred->cr_uid && 868b1fc0ec1SRobert Watson euid != oldcred->cr_ruid && euid != oldcred->cr_svuid)) && 869835a82eeSMatthew Dillon (error = suser_xxx(oldcred, NULL, PRISON_ROOT)) != 0) { 870835a82eeSMatthew Dillon goto done2; 871835a82eeSMatthew Dillon } 872b1fc0ec1SRobert Watson newcred = crdup(oldcred); 873b1fc0ec1SRobert Watson if (euid != (uid_t)-1 && oldcred->cr_uid != euid) { 874b1fc0ec1SRobert Watson change_euid(newcred, euid); 875d5f81602SSean Eric Fagan setsugid(p); 876a89a5370SPeter Wemm } 877b1fc0ec1SRobert Watson if (ruid != (uid_t)-1 && oldcred->cr_ruid != ruid) { 878b1fc0ec1SRobert Watson change_ruid(newcred, ruid); 879d5f81602SSean Eric Fagan setsugid(p); 88000999cd6SAndrey A. Chernov } 881b1fc0ec1SRobert Watson if ((ruid != (uid_t)-1 || newcred->cr_uid != newcred->cr_ruid) && 882b1fc0ec1SRobert Watson newcred->cr_svuid != newcred->cr_uid) { 883b1fc0ec1SRobert Watson change_svuid(newcred, newcred->cr_uid); 884d5f81602SSean Eric Fagan setsugid(p); 885a89a5370SPeter Wemm } 886b1fc0ec1SRobert Watson p->p_ucred = newcred; 887b1fc0ec1SRobert Watson crfree(oldcred); 888835a82eeSMatthew Dillon done2: 889835a82eeSMatthew Dillon mtx_unlock(&Giant); 890835a82eeSMatthew Dillon return (error); 891df8bae1dSRodney W. Grimes } 892df8bae1dSRodney W. Grimes 893d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 894df8bae1dSRodney W. Grimes struct setregid_args { 89500999cd6SAndrey A. Chernov gid_t rgid; 89600999cd6SAndrey A. Chernov gid_t egid; 897df8bae1dSRodney W. Grimes }; 898d2d3e875SBruce Evans #endif 899835a82eeSMatthew Dillon /* 900835a82eeSMatthew Dillon * MPSAFE 901835a82eeSMatthew Dillon */ 902df8bae1dSRodney W. Grimes /* ARGSUSED */ 90326f9a767SRodney W. Grimes int 904b40ce416SJulian Elischer setregid(td, uap) 905b40ce416SJulian Elischer register struct thread *td; 906df8bae1dSRodney W. Grimes struct setregid_args *uap; 907df8bae1dSRodney W. Grimes { 908b40ce416SJulian Elischer struct proc *p = td->td_proc; 909b1fc0ec1SRobert Watson struct ucred *newcred, *oldcred; 910b1fc0ec1SRobert Watson gid_t rgid, egid; 911835a82eeSMatthew Dillon int error = 0; 912df8bae1dSRodney W. Grimes 91300999cd6SAndrey A. Chernov rgid = uap->rgid; 91400999cd6SAndrey A. Chernov egid = uap->egid; 915835a82eeSMatthew Dillon 916835a82eeSMatthew Dillon mtx_lock(&Giant); 917835a82eeSMatthew Dillon 918b1fc0ec1SRobert Watson oldcred = p->p_ucred; 919b1fc0ec1SRobert Watson if (((rgid != (gid_t)-1 && rgid != oldcred->cr_rgid && 920b1fc0ec1SRobert Watson rgid != oldcred->cr_svgid) || 921b1fc0ec1SRobert Watson (egid != (gid_t)-1 && egid != oldcred->cr_groups[0] && 922b1fc0ec1SRobert Watson egid != oldcred->cr_rgid && egid != oldcred->cr_svgid)) && 923835a82eeSMatthew Dillon (error = suser_xxx(oldcred, NULL, PRISON_ROOT)) != 0) { 924835a82eeSMatthew Dillon goto done2; 925835a82eeSMatthew Dillon } 92600999cd6SAndrey A. Chernov 927b1fc0ec1SRobert Watson newcred = crdup(oldcred); 928b1fc0ec1SRobert Watson if (egid != (gid_t)-1 && oldcred->cr_groups[0] != egid) { 929b1fc0ec1SRobert Watson change_egid(newcred, egid); 930d5f81602SSean Eric Fagan setsugid(p); 931a89a5370SPeter Wemm } 932b1fc0ec1SRobert Watson if (rgid != (gid_t)-1 && oldcred->cr_rgid != rgid) { 933b1fc0ec1SRobert Watson change_rgid(newcred, rgid); 934d5f81602SSean Eric Fagan setsugid(p); 935a89a5370SPeter Wemm } 936b1fc0ec1SRobert Watson if ((rgid != (gid_t)-1 || newcred->cr_groups[0] != newcred->cr_rgid) && 937b1fc0ec1SRobert Watson newcred->cr_svgid != newcred->cr_groups[0]) { 938b1fc0ec1SRobert Watson change_svgid(newcred, newcred->cr_groups[0]); 939d5f81602SSean Eric Fagan setsugid(p); 940a89a5370SPeter Wemm } 9414589be70SRuslan Ermilov p->p_ucred = newcred; 9424589be70SRuslan Ermilov crfree(oldcred); 943835a82eeSMatthew Dillon done2: 944835a82eeSMatthew Dillon mtx_unlock(&Giant); 945835a82eeSMatthew Dillon return (error); 946df8bae1dSRodney W. Grimes } 947df8bae1dSRodney W. Grimes 9488ccd6334SPeter Wemm /* 9498ccd6334SPeter Wemm * setresuid(ruid, euid, suid) is like setreuid except control over the 9508ccd6334SPeter Wemm * saved uid is explicit. 9518ccd6334SPeter Wemm */ 9528ccd6334SPeter Wemm 9538ccd6334SPeter Wemm #ifndef _SYS_SYSPROTO_H_ 9548ccd6334SPeter Wemm struct setresuid_args { 9558ccd6334SPeter Wemm uid_t ruid; 9568ccd6334SPeter Wemm uid_t euid; 9578ccd6334SPeter Wemm uid_t suid; 9588ccd6334SPeter Wemm }; 9598ccd6334SPeter Wemm #endif 960835a82eeSMatthew Dillon /* 961835a82eeSMatthew Dillon * MPSAFE 962835a82eeSMatthew Dillon */ 9638ccd6334SPeter Wemm /* ARGSUSED */ 9648ccd6334SPeter Wemm int 965b40ce416SJulian Elischer setresuid(td, uap) 966b40ce416SJulian Elischer register struct thread *td; 9678ccd6334SPeter Wemm struct setresuid_args *uap; 9688ccd6334SPeter Wemm { 969b40ce416SJulian Elischer struct proc *p = td->td_proc; 970b1fc0ec1SRobert Watson struct ucred *newcred, *oldcred; 971b1fc0ec1SRobert Watson uid_t ruid, euid, suid; 9728ccd6334SPeter Wemm int error; 9738ccd6334SPeter Wemm 9748ccd6334SPeter Wemm ruid = uap->ruid; 9758ccd6334SPeter Wemm euid = uap->euid; 9768ccd6334SPeter Wemm suid = uap->suid; 977835a82eeSMatthew Dillon 978835a82eeSMatthew Dillon mtx_lock(&Giant); 979b1fc0ec1SRobert Watson oldcred = p->p_ucred; 980b1fc0ec1SRobert Watson if (((ruid != (uid_t)-1 && ruid != oldcred->cr_ruid && 981b1fc0ec1SRobert Watson ruid != oldcred->cr_svuid && 982b1fc0ec1SRobert Watson ruid != oldcred->cr_uid) || 983b1fc0ec1SRobert Watson (euid != (uid_t)-1 && euid != oldcred->cr_ruid && 984b1fc0ec1SRobert Watson euid != oldcred->cr_svuid && 985b1fc0ec1SRobert Watson euid != oldcred->cr_uid) || 986b1fc0ec1SRobert Watson (suid != (uid_t)-1 && suid != oldcred->cr_ruid && 987b1fc0ec1SRobert Watson suid != oldcred->cr_svuid && 988b1fc0ec1SRobert Watson suid != oldcred->cr_uid)) && 989835a82eeSMatthew Dillon (error = suser_xxx(oldcred, NULL, PRISON_ROOT)) != 0) { 990835a82eeSMatthew Dillon goto done2; 991835a82eeSMatthew Dillon } 992b1fc0ec1SRobert Watson 993b1fc0ec1SRobert Watson newcred = crdup(oldcred); 994b1fc0ec1SRobert Watson if (euid != (uid_t)-1 && oldcred->cr_uid != euid) { 995b1fc0ec1SRobert Watson change_euid(newcred, euid); 9968ccd6334SPeter Wemm setsugid(p); 9978ccd6334SPeter Wemm } 998b1fc0ec1SRobert Watson if (ruid != (uid_t)-1 && oldcred->cr_ruid != ruid) { 999b1fc0ec1SRobert Watson change_ruid(newcred, ruid); 10008ccd6334SPeter Wemm setsugid(p); 10018ccd6334SPeter Wemm } 1002b1fc0ec1SRobert Watson if (suid != (uid_t)-1 && oldcred->cr_svuid != suid) { 1003b1fc0ec1SRobert Watson change_svuid(newcred, suid); 10048ccd6334SPeter Wemm setsugid(p); 10058ccd6334SPeter Wemm } 1006b1fc0ec1SRobert Watson p->p_ucred = newcred; 1007b1fc0ec1SRobert Watson crfree(oldcred); 1008835a82eeSMatthew Dillon error = 0; 1009835a82eeSMatthew Dillon done2: 1010835a82eeSMatthew Dillon mtx_unlock(&Giant); 1011835a82eeSMatthew Dillon return (error); 10128ccd6334SPeter Wemm } 10138ccd6334SPeter Wemm 10148ccd6334SPeter Wemm /* 10158ccd6334SPeter Wemm * setresgid(rgid, egid, sgid) is like setregid except control over the 10168ccd6334SPeter Wemm * saved gid is explicit. 10178ccd6334SPeter Wemm */ 10188ccd6334SPeter Wemm 10198ccd6334SPeter Wemm #ifndef _SYS_SYSPROTO_H_ 10208ccd6334SPeter Wemm struct setresgid_args { 10218ccd6334SPeter Wemm gid_t rgid; 10228ccd6334SPeter Wemm gid_t egid; 10238ccd6334SPeter Wemm gid_t sgid; 10248ccd6334SPeter Wemm }; 10258ccd6334SPeter Wemm #endif 1026835a82eeSMatthew Dillon /* 1027835a82eeSMatthew Dillon * MPSAFE 1028835a82eeSMatthew Dillon */ 10298ccd6334SPeter Wemm /* ARGSUSED */ 10308ccd6334SPeter Wemm int 1031b40ce416SJulian Elischer setresgid(td, uap) 1032b40ce416SJulian Elischer register struct thread *td; 10338ccd6334SPeter Wemm struct setresgid_args *uap; 10348ccd6334SPeter Wemm { 1035b40ce416SJulian Elischer struct proc *p = td->td_proc; 1036b1fc0ec1SRobert Watson struct ucred *newcred, *oldcred; 1037b1fc0ec1SRobert Watson gid_t rgid, egid, sgid; 10388ccd6334SPeter Wemm int error; 10398ccd6334SPeter Wemm 10408ccd6334SPeter Wemm rgid = uap->rgid; 10418ccd6334SPeter Wemm egid = uap->egid; 10428ccd6334SPeter Wemm sgid = uap->sgid; 1043835a82eeSMatthew Dillon 1044835a82eeSMatthew Dillon mtx_lock(&Giant); 1045b1fc0ec1SRobert Watson oldcred = p->p_ucred; 1046b1fc0ec1SRobert Watson if (((rgid != (gid_t)-1 && rgid != oldcred->cr_rgid && 1047b1fc0ec1SRobert Watson rgid != oldcred->cr_svgid && 1048b1fc0ec1SRobert Watson rgid != oldcred->cr_groups[0]) || 1049b1fc0ec1SRobert Watson (egid != (gid_t)-1 && egid != oldcred->cr_rgid && 1050b1fc0ec1SRobert Watson egid != oldcred->cr_svgid && 1051b1fc0ec1SRobert Watson egid != oldcred->cr_groups[0]) || 1052b1fc0ec1SRobert Watson (sgid != (gid_t)-1 && sgid != oldcred->cr_rgid && 1053b1fc0ec1SRobert Watson sgid != oldcred->cr_svgid && 1054b1fc0ec1SRobert Watson sgid != oldcred->cr_groups[0])) && 1055835a82eeSMatthew Dillon (error = suser_xxx(oldcred, NULL, PRISON_ROOT)) != 0) { 1056835a82eeSMatthew Dillon goto done2; 1057835a82eeSMatthew Dillon } 1058b1fc0ec1SRobert Watson newcred = crdup(oldcred); 1059b1fc0ec1SRobert Watson if (egid != (gid_t)-1 && oldcred->cr_groups[0] != egid) { 1060b1fc0ec1SRobert Watson change_egid(newcred, egid); 10618ccd6334SPeter Wemm setsugid(p); 10628ccd6334SPeter Wemm } 1063b1fc0ec1SRobert Watson if (rgid != (gid_t)-1 && oldcred->cr_rgid != rgid) { 1064b1fc0ec1SRobert Watson change_rgid(newcred, rgid); 10658ccd6334SPeter Wemm setsugid(p); 10668ccd6334SPeter Wemm } 1067b1fc0ec1SRobert Watson if (sgid != (gid_t)-1 && oldcred->cr_svgid != sgid) { 1068b1fc0ec1SRobert Watson change_svgid(newcred, sgid); 10698ccd6334SPeter Wemm setsugid(p); 10708ccd6334SPeter Wemm } 1071b1fc0ec1SRobert Watson p->p_ucred = newcred; 1072b1fc0ec1SRobert Watson crfree(oldcred); 1073835a82eeSMatthew Dillon error = 0; 1074835a82eeSMatthew Dillon done2: 1075835a82eeSMatthew Dillon mtx_unlock(&Giant); 1076835a82eeSMatthew Dillon return (error); 10778ccd6334SPeter Wemm } 10788ccd6334SPeter Wemm 10798ccd6334SPeter Wemm #ifndef _SYS_SYSPROTO_H_ 10808ccd6334SPeter Wemm struct getresuid_args { 10818ccd6334SPeter Wemm uid_t *ruid; 10828ccd6334SPeter Wemm uid_t *euid; 10838ccd6334SPeter Wemm uid_t *suid; 10848ccd6334SPeter Wemm }; 10858ccd6334SPeter Wemm #endif 1086835a82eeSMatthew Dillon /* 1087835a82eeSMatthew Dillon * MPSAFE 1088835a82eeSMatthew Dillon */ 10898ccd6334SPeter Wemm /* ARGSUSED */ 10908ccd6334SPeter Wemm int 1091b40ce416SJulian Elischer getresuid(td, uap) 1092b40ce416SJulian Elischer register struct thread *td; 10938ccd6334SPeter Wemm struct getresuid_args *uap; 10948ccd6334SPeter Wemm { 1095835a82eeSMatthew Dillon struct ucred *cred; 1096b40ce416SJulian Elischer struct proc *p = td->td_proc; 10978ccd6334SPeter Wemm int error1 = 0, error2 = 0, error3 = 0; 10988ccd6334SPeter Wemm 1099835a82eeSMatthew Dillon mtx_lock(&Giant); 1100835a82eeSMatthew Dillon cred = p->p_ucred; 1101835a82eeSMatthew Dillon 11028ccd6334SPeter Wemm if (uap->ruid) 1103b1fc0ec1SRobert Watson error1 = copyout((caddr_t)&cred->cr_ruid, 1104b1fc0ec1SRobert Watson (caddr_t)uap->ruid, sizeof(cred->cr_ruid)); 11058ccd6334SPeter Wemm if (uap->euid) 1106b1fc0ec1SRobert Watson error2 = copyout((caddr_t)&cred->cr_uid, 1107b1fc0ec1SRobert Watson (caddr_t)uap->euid, sizeof(cred->cr_uid)); 11088ccd6334SPeter Wemm if (uap->suid) 1109b1fc0ec1SRobert Watson error3 = copyout((caddr_t)&cred->cr_svuid, 1110b1fc0ec1SRobert Watson (caddr_t)uap->suid, sizeof(cred->cr_svuid)); 1111835a82eeSMatthew Dillon mtx_unlock(&Giant); 11128ccd6334SPeter Wemm return error1 ? error1 : (error2 ? error2 : error3); 11138ccd6334SPeter Wemm } 11148ccd6334SPeter Wemm 11158ccd6334SPeter Wemm #ifndef _SYS_SYSPROTO_H_ 11168ccd6334SPeter Wemm struct getresgid_args { 11178ccd6334SPeter Wemm gid_t *rgid; 11188ccd6334SPeter Wemm gid_t *egid; 11198ccd6334SPeter Wemm gid_t *sgid; 11208ccd6334SPeter Wemm }; 11218ccd6334SPeter Wemm #endif 1122835a82eeSMatthew Dillon /* 1123835a82eeSMatthew Dillon * MPSAFE 1124835a82eeSMatthew Dillon */ 11258ccd6334SPeter Wemm /* ARGSUSED */ 11268ccd6334SPeter Wemm int 1127b40ce416SJulian Elischer getresgid(td, uap) 1128b40ce416SJulian Elischer register struct thread *td; 11298ccd6334SPeter Wemm struct getresgid_args *uap; 11308ccd6334SPeter Wemm { 1131835a82eeSMatthew Dillon struct ucred *cred; 1132b40ce416SJulian Elischer struct proc *p = td->td_proc; 11338ccd6334SPeter Wemm int error1 = 0, error2 = 0, error3 = 0; 11348ccd6334SPeter Wemm 1135835a82eeSMatthew Dillon mtx_lock(&Giant); 1136835a82eeSMatthew Dillon cred = p->p_ucred; 1137835a82eeSMatthew Dillon 11388ccd6334SPeter Wemm if (uap->rgid) 1139b1fc0ec1SRobert Watson error1 = copyout((caddr_t)&cred->cr_rgid, 1140b1fc0ec1SRobert Watson (caddr_t)uap->rgid, sizeof(cred->cr_rgid)); 11418ccd6334SPeter Wemm if (uap->egid) 1142b1fc0ec1SRobert Watson error2 = copyout((caddr_t)&cred->cr_groups[0], 1143b1fc0ec1SRobert Watson (caddr_t)uap->egid, sizeof(cred->cr_groups[0])); 11448ccd6334SPeter Wemm if (uap->sgid) 1145b1fc0ec1SRobert Watson error3 = copyout((caddr_t)&cred->cr_svgid, 1146b1fc0ec1SRobert Watson (caddr_t)uap->sgid, sizeof(cred->cr_svgid)); 1147835a82eeSMatthew Dillon mtx_unlock(&Giant); 11488ccd6334SPeter Wemm return error1 ? error1 : (error2 ? error2 : error3); 11498ccd6334SPeter Wemm } 11508ccd6334SPeter Wemm 11518ccd6334SPeter Wemm 1152b67cbc65SPeter Wemm #ifndef _SYS_SYSPROTO_H_ 1153b67cbc65SPeter Wemm struct issetugid_args { 1154b67cbc65SPeter Wemm int dummy; 1155b67cbc65SPeter Wemm }; 1156b67cbc65SPeter Wemm #endif 1157b67cbc65SPeter Wemm /* ARGSUSED */ 1158b67cbc65SPeter Wemm int 1159b40ce416SJulian Elischer issetugid(td, uap) 1160b40ce416SJulian Elischer register struct thread *td; 1161b67cbc65SPeter Wemm struct issetugid_args *uap; 1162b67cbc65SPeter Wemm { 1163b40ce416SJulian Elischer struct proc *p = td->td_proc; 1164b40ce416SJulian Elischer 1165b67cbc65SPeter Wemm /* 1166b67cbc65SPeter Wemm * Note: OpenBSD sets a P_SUGIDEXEC flag set at execve() time, 1167b67cbc65SPeter Wemm * we use P_SUGID because we consider changing the owners as 1168b67cbc65SPeter Wemm * "tainting" as well. 1169b67cbc65SPeter Wemm * This is significant for procs that start as root and "become" 1170b67cbc65SPeter Wemm * a user without an exec - programs cannot know *everything* 1171b67cbc65SPeter Wemm * that libc *might* have put in their data segment. 1172b67cbc65SPeter Wemm */ 1173b40ce416SJulian Elischer td->td_retval[0] = (p->p_flag & P_SUGID) ? 1 : 0; 1174b67cbc65SPeter Wemm return (0); 1175b67cbc65SPeter Wemm } 1176b67cbc65SPeter Wemm 1177835a82eeSMatthew Dillon /* 1178835a82eeSMatthew Dillon * MPSAFE 1179835a82eeSMatthew Dillon */ 1180130d0157SRobert Watson int 1181b40ce416SJulian Elischer __setugid(td, uap) 1182b40ce416SJulian Elischer struct thread *td; 1183130d0157SRobert Watson struct __setugid_args *uap; 1184130d0157SRobert Watson { 1185130d0157SRobert Watson #ifdef REGRESSION 1186835a82eeSMatthew Dillon int error = 0; 1187835a82eeSMatthew Dillon 1188835a82eeSMatthew Dillon mtx_lock(&Giant); 1189130d0157SRobert Watson switch (uap->flag) { 1190130d0157SRobert Watson case 0: 1191b40ce416SJulian Elischer td->td_proc->p_flag &= ~P_SUGID; 1192835a82eeSMatthew Dillon break; 1193130d0157SRobert Watson case 1: 1194b40ce416SJulian Elischer td->td_proc->p_flag |= P_SUGID; 1195835a82eeSMatthew Dillon break; 1196130d0157SRobert Watson default: 1197835a82eeSMatthew Dillon error = EINVAL; 1198835a82eeSMatthew Dillon break; 1199130d0157SRobert Watson } 1200835a82eeSMatthew Dillon mtx_unlock(&Giant); 1201835a82eeSMatthew Dillon return (error); 1202130d0157SRobert Watson #else /* !REGRESSION */ 1203130d0157SRobert Watson return (ENOSYS); 1204130d0157SRobert Watson #endif /* !REGRESSION */ 1205130d0157SRobert Watson } 1206130d0157SRobert Watson 1207df8bae1dSRodney W. Grimes /* 1208df8bae1dSRodney W. Grimes * Check if gid is a member of the group set. 1209df8bae1dSRodney W. Grimes */ 121026f9a767SRodney W. Grimes int 1211df8bae1dSRodney W. Grimes groupmember(gid, cred) 1212df8bae1dSRodney W. Grimes gid_t gid; 1213b1fc0ec1SRobert Watson struct ucred *cred; 1214df8bae1dSRodney W. Grimes { 1215df8bae1dSRodney W. Grimes register gid_t *gp; 1216df8bae1dSRodney W. Grimes gid_t *egp; 1217df8bae1dSRodney W. Grimes 1218df8bae1dSRodney W. Grimes egp = &(cred->cr_groups[cred->cr_ngroups]); 1219df8bae1dSRodney W. Grimes for (gp = cred->cr_groups; gp < egp; gp++) 1220df8bae1dSRodney W. Grimes if (*gp == gid) 1221df8bae1dSRodney W. Grimes return (1); 1222df8bae1dSRodney W. Grimes return (0); 1223df8bae1dSRodney W. Grimes } 1224df8bae1dSRodney W. Grimes 12253b243b72SRobert Watson /* 122693f4fd1cSRobert Watson * `suser_enabled' (which can be set by the kern.security.suser_enabled 12277fd6a959SRobert Watson * sysctl) determines whether the system 'super-user' policy is in effect. 12287fd6a959SRobert Watson * If it is nonzero, an effective uid of 0 connotes special privilege, 12297fd6a959SRobert Watson * overriding many mandatory and discretionary protections. If it is zero, 12307fd6a959SRobert Watson * uid 0 is offered no special privilege in the kernel security policy. 12317fd6a959SRobert Watson * Setting it to zero may seriously impact the functionality of many 12327fd6a959SRobert Watson * existing userland programs, and should not be done without careful 12337fd6a959SRobert Watson * consideration of the consequences. 12343b243b72SRobert Watson */ 123593f4fd1cSRobert Watson int suser_enabled = 1; 123693f4fd1cSRobert Watson SYSCTL_INT(_kern_security, OID_AUTO, suser_enabled, CTLFLAG_RW, 123793f4fd1cSRobert Watson &suser_enabled, 0, "processes with uid 0 have privilege"); 1238579f4eb4SRobert Watson 1239df8bae1dSRodney W. Grimes /* 12407fd6a959SRobert Watson * Test whether the specified credentials imply "super-user" privilege. 12417fd6a959SRobert Watson * Return 0 or EPERM. 1242df8bae1dSRodney W. Grimes */ 124326f9a767SRodney W. Grimes int 1244f711d546SPoul-Henning Kamp suser(p) 124591421ba2SRobert Watson struct proc *p; 1246f711d546SPoul-Henning Kamp { 124775c13541SPoul-Henning Kamp return suser_xxx(0, p, 0); 1248f711d546SPoul-Henning Kamp } 1249f711d546SPoul-Henning Kamp 1250b40ce416SJulian Elischer /* 1251b40ce416SJulian Elischer * version for when the thread pointer is available and not the proc. 1252b40ce416SJulian Elischer * (saves having to include proc.h into every file that needs to do the change.) 1253b40ce416SJulian Elischer */ 1254b40ce416SJulian Elischer int 1255b40ce416SJulian Elischer suser_td(td) 1256b40ce416SJulian Elischer 1257b40ce416SJulian Elischer struct thread *td; 1258b40ce416SJulian Elischer { 1259b40ce416SJulian Elischer return suser_xxx(0, td->td_proc, 0); 1260b40ce416SJulian Elischer } 1261b40ce416SJulian Elischer 1262b40ce416SJulian Elischer /* 1263b40ce416SJulian Elischer * wrapper to use if you have the thread on hand but not the proc. 1264b40ce416SJulian Elischer */ 1265b40ce416SJulian Elischer int 1266b40ce416SJulian Elischer suser_xxx_td(cred, td, flag) 1267b40ce416SJulian Elischer struct ucred *cred; 1268b40ce416SJulian Elischer struct thread *td; 1269b40ce416SJulian Elischer int flag; 1270b40ce416SJulian Elischer { 1271b40ce416SJulian Elischer return(suser_xxx(cred, td->td_proc, flag)); 1272b40ce416SJulian Elischer } 1273b40ce416SJulian Elischer 1274f711d546SPoul-Henning Kamp int 127575c13541SPoul-Henning Kamp suser_xxx(cred, proc, flag) 127691421ba2SRobert Watson struct ucred *cred; 127791421ba2SRobert Watson struct proc *proc; 127875c13541SPoul-Henning Kamp int flag; 1279df8bae1dSRodney W. Grimes { 128093f4fd1cSRobert Watson if (!suser_enabled) 128103095547SRobert Watson return (EPERM); 128275c13541SPoul-Henning Kamp if (!cred && !proc) { 128375c13541SPoul-Henning Kamp printf("suser_xxx(): THINK!\n"); 1284df8bae1dSRodney W. Grimes return (EPERM); 1285df8bae1dSRodney W. Grimes } 128675c13541SPoul-Henning Kamp if (!cred) 128775c13541SPoul-Henning Kamp cred = proc->p_ucred; 128875c13541SPoul-Henning Kamp if (cred->cr_uid != 0) 128975c13541SPoul-Henning Kamp return (EPERM); 129091421ba2SRobert Watson if (jailed(cred) && !(flag & PRISON_ROOT)) 129175c13541SPoul-Henning Kamp return (EPERM); 129275c13541SPoul-Henning Kamp return (0); 129375c13541SPoul-Henning Kamp } 1294df8bae1dSRodney W. Grimes 12953ca719f1SRobert Watson /* 129687fce2bbSRobert Watson * Test (local, globale) securelevel values against passed required 129787fce2bbSRobert Watson * securelevel. _gt implements (level > securelevel), and _ge implements 129875bc5b3fSRobert Watson * (level >= securelevel). Returns 0 oer EPERM. 12993ca719f1SRobert Watson * 13003ca719f1SRobert Watson * cr is permitted to be NULL for the time being, as there were some 13013ca719f1SRobert Watson * existing securelevel checks that occurred without a process/credential 13023ca719f1SRobert Watson * context. In the future this will be disallowed, so a kernel 13033ca719f1SRobert Watson * message is displayed. 13043ca719f1SRobert Watson */ 13053ca719f1SRobert Watson int 13063ca719f1SRobert Watson securelevel_gt(struct ucred *cr, int level) 13073ca719f1SRobert Watson { 13083ca719f1SRobert Watson 13093ca719f1SRobert Watson if (cr == NULL) { 13103ca719f1SRobert Watson printf("securelevel_gt: cr is NULL\n"); 131175bc5b3fSRobert Watson if (level > securelevel) 13123ca719f1SRobert Watson return (0); 13133ca719f1SRobert Watson else 13143ca719f1SRobert Watson return (EPERM); 131587fce2bbSRobert Watson } else if (cr->cr_prison == NULL) { 131675bc5b3fSRobert Watson if (level > securelevel) 13173ca719f1SRobert Watson return (0); 13183ca719f1SRobert Watson else 13193ca719f1SRobert Watson return (EPERM); 132087fce2bbSRobert Watson } else { 132187fce2bbSRobert Watson if (level > imax(cr->cr_prison->pr_securelevel, securelevel)) 132287fce2bbSRobert Watson return (0); 132387fce2bbSRobert Watson else 132487fce2bbSRobert Watson return (EPERM); 13253ca719f1SRobert Watson } 132687fce2bbSRobert Watson 13273ca719f1SRobert Watson } 13283ca719f1SRobert Watson 13293ca719f1SRobert Watson int 13303ca719f1SRobert Watson securelevel_ge(struct ucred *cr, int level) 13313ca719f1SRobert Watson { 13323ca719f1SRobert Watson 13333ca719f1SRobert Watson if (cr == NULL) { 13343ca719f1SRobert Watson printf("securelevel_ge: cr is NULL\n"); 133575bc5b3fSRobert Watson if (level >= securelevel) 13363ca719f1SRobert Watson return (0); 13373ca719f1SRobert Watson else 13383ca719f1SRobert Watson return (EPERM); 133987fce2bbSRobert Watson } if (cr->cr_prison == NULL) { 134075bc5b3fSRobert Watson if (level >= securelevel) 13413ca719f1SRobert Watson return (0); 13423ca719f1SRobert Watson else 13433ca719f1SRobert Watson return (EPERM); 134487fce2bbSRobert Watson } else { 134587fce2bbSRobert Watson if (level >= imax(cr->cr_prison->pr_securelevel, securelevel)) 134687fce2bbSRobert Watson return (0); 134787fce2bbSRobert Watson else 134887fce2bbSRobert Watson return (EPERM); 13493ca719f1SRobert Watson } 13503ca719f1SRobert Watson } 13513ca719f1SRobert Watson 13528a7d8cc6SRobert Watson /* 13538a7d8cc6SRobert Watson * kern_security_seeotheruids_permitted determines whether or not visibility 13548a7d8cc6SRobert Watson * of processes and sockets with credentials holding different real uid's 13558a7d8cc6SRobert Watson * is possible using a variety of system MIBs. 13568a7d8cc6SRobert Watson */ 13578a7d8cc6SRobert Watson static int kern_security_seeotheruids_permitted = 1; 13588a7d8cc6SRobert Watson SYSCTL_INT(_kern_security, OID_AUTO, seeotheruids_permitted, 13598a7d8cc6SRobert Watson CTLFLAG_RW, &kern_security_seeotheruids_permitted, 0, 13608a7d8cc6SRobert Watson "Unprivileged processes may see subjects/objects with different real uid"); 13618a7d8cc6SRobert Watson 13627fd6a959SRobert Watson /*- 13637fd6a959SRobert Watson * Determine if u1 "can see" the subject specified by u2. 1364ed639720SRobert Watson * Returns: 0 for permitted, an errno value otherwise 1365ed639720SRobert Watson * Locks: none 13667fd6a959SRobert Watson * References: u1 and u2 must be immutable credentials 13677fd6a959SRobert Watson * u1 and u2 must be valid for the lifetime of the call 1368ed639720SRobert Watson * u1 may equal u2, in which case only one reference is required 1369ed639720SRobert Watson */ 1370ed639720SRobert Watson int 137194088977SRobert Watson cr_cansee(struct ucred *u1, struct ucred *u2) 1372a9e0361bSPoul-Henning Kamp { 137391421ba2SRobert Watson int error; 1374a9e0361bSPoul-Henning Kamp 1375ed639720SRobert Watson if ((error = prison_check(u1, u2))) 137691421ba2SRobert Watson return (error); 13778a7d8cc6SRobert Watson if (!kern_security_seeotheruids_permitted && 13788a7d8cc6SRobert Watson u1->cr_ruid != u2->cr_ruid) { 1379f8e6ab29SRobert Watson if (suser_xxx(u1, NULL, PRISON_ROOT) != 0) 1380387d2c03SRobert Watson return (ESRCH); 1381c52396e3SRobert Watson } 1382387d2c03SRobert Watson return (0); 1383387d2c03SRobert Watson } 1384387d2c03SRobert Watson 13857fd6a959SRobert Watson /*- 13867fd6a959SRobert Watson * Determine if p1 "can see" the subject specified by p2. 13873b243b72SRobert Watson * Returns: 0 for permitted, an errno value otherwise 13887fd6a959SRobert Watson * Locks: Sufficient locks to protect p1->p_ucred and p2->p_ucred must 13893b243b72SRobert Watson * be held. Normally, p1 will be curproc, and a lock must be held 13903b243b72SRobert Watson * for p2. 13913b243b72SRobert Watson * References: p1 and p2 must be valid for the lifetime of the call 13923b243b72SRobert Watson */ 1393a0f75161SRobert Watson int 1394a0f75161SRobert Watson p_cansee(struct proc *p1, struct proc *p2) 1395ed639720SRobert Watson { 1396ed639720SRobert Watson 139794088977SRobert Watson /* Wrap cr_cansee() for all functionality. */ 139894088977SRobert Watson return (cr_cansee(p1->p_ucred, p2->p_ucred)); 1399ed639720SRobert Watson } 1400ed639720SRobert Watson 14017fd6a959SRobert Watson /*- 14027fd6a959SRobert Watson * Determine whether p1 may deliver the specified signal to p2. 14037fd6a959SRobert Watson * Returns: 0 for permitted, an errno value otherwise 14047fd6a959SRobert Watson * Locks: Sufficient locks to protect various components of p1 and p2 14057fd6a959SRobert Watson * must be held. Normally, p1 will be curproc, and a lock must 14067fd6a959SRobert Watson * be held for p2. 14073b243b72SRobert Watson * References: p1 and p2 must be valid for the lifetime of the call 14084c5eb9c3SRobert Watson */ 14094c5eb9c3SRobert Watson int 14104c5eb9c3SRobert Watson p_cansignal(struct proc *p1, struct proc *p2, int signum) 1411387d2c03SRobert Watson { 141291421ba2SRobert Watson int error; 1413387d2c03SRobert Watson 1414a9e0361bSPoul-Henning Kamp if (p1 == p2) 1415a9e0361bSPoul-Henning Kamp return (0); 1416387d2c03SRobert Watson 14174c5eb9c3SRobert Watson /* 14184c5eb9c3SRobert Watson * Jail semantics limit the scope of signalling to p2 in the same 14194c5eb9c3SRobert Watson * jail as p1, if p1 is in jail. 14204c5eb9c3SRobert Watson */ 142191421ba2SRobert Watson if ((error = prison_check(p1->p_ucred, p2->p_ucred))) 142291421ba2SRobert Watson return (error); 1423387d2c03SRobert Watson 1424387d2c03SRobert Watson /* 14254c5eb9c3SRobert Watson * UNIX signalling semantics require that processes in the same 14264c5eb9c3SRobert Watson * session always be able to deliver SIGCONT to one another, 14274c5eb9c3SRobert Watson * overriding the remaining protections. 1428387d2c03SRobert Watson */ 14294c5eb9c3SRobert Watson if (signum == SIGCONT && p1->p_session == p2->p_session) 1430a9e0361bSPoul-Henning Kamp return (0); 1431387d2c03SRobert Watson 14324c5eb9c3SRobert Watson /* 14333b243b72SRobert Watson * UNIX signal semantics depend on the status of the P_SUGID 14343b243b72SRobert Watson * bit on the target process. If the bit is set, then additional 14353b243b72SRobert Watson * restrictions are placed on the set of available signals. 14364c5eb9c3SRobert Watson */ 14374c5eb9c3SRobert Watson if (p2->p_flag & P_SUGID) { 14384c5eb9c3SRobert Watson switch (signum) { 14394c5eb9c3SRobert Watson case 0: 14404c5eb9c3SRobert Watson case SIGKILL: 14414c5eb9c3SRobert Watson case SIGINT: 14424c5eb9c3SRobert Watson case SIGTERM: 14434c5eb9c3SRobert Watson case SIGSTOP: 14444c5eb9c3SRobert Watson case SIGTTIN: 14454c5eb9c3SRobert Watson case SIGTTOU: 14464c5eb9c3SRobert Watson case SIGTSTP: 14474c5eb9c3SRobert Watson case SIGHUP: 14484c5eb9c3SRobert Watson case SIGUSR1: 14494c5eb9c3SRobert Watson case SIGUSR2: 14507fd6a959SRobert Watson /* 14517fd6a959SRobert Watson * Generally, permit job and terminal control 14527fd6a959SRobert Watson * signals. 14537fd6a959SRobert Watson */ 14544c5eb9c3SRobert Watson break; 14554c5eb9c3SRobert Watson default: 14563b243b72SRobert Watson /* Not permitted, privilege is required. */ 14574c5eb9c3SRobert Watson error = suser_xxx(NULL, p1, PRISON_ROOT); 14584c5eb9c3SRobert Watson if (error) 14594c5eb9c3SRobert Watson return (error); 14604c5eb9c3SRobert Watson } 1461e9e7ff5bSRobert Watson } 1462e9e7ff5bSRobert Watson 14634c5eb9c3SRobert Watson /* 14643b243b72SRobert Watson * Generally, the target credential's ruid or svuid must match the 1465e9e7ff5bSRobert Watson * subject credential's ruid or euid. 14664c5eb9c3SRobert Watson */ 1467b1fc0ec1SRobert Watson if (p1->p_ucred->cr_ruid != p2->p_ucred->cr_ruid && 1468b1fc0ec1SRobert Watson p1->p_ucred->cr_ruid != p2->p_ucred->cr_svuid && 1469b1fc0ec1SRobert Watson p1->p_ucred->cr_uid != p2->p_ucred->cr_ruid && 1470b1fc0ec1SRobert Watson p1->p_ucred->cr_uid != p2->p_ucred->cr_svuid) { 14714c5eb9c3SRobert Watson /* Not permitted, try privilege. */ 14724c5eb9c3SRobert Watson error = suser_xxx(NULL, p1, PRISON_ROOT); 14734c5eb9c3SRobert Watson if (error) 14744c5eb9c3SRobert Watson return (error); 14754c5eb9c3SRobert Watson } 1476387d2c03SRobert Watson 1477387d2c03SRobert Watson return (0); 1478387d2c03SRobert Watson } 1479a9e0361bSPoul-Henning Kamp 14807fd6a959SRobert Watson /*- 14817fd6a959SRobert Watson * Determine whether p1 may reschedule p2 14827fd6a959SRobert Watson * Returns: 0 for permitted, an errno value otherwise 14833b243b72SRobert Watson * Locks: Sufficient locks to protect various components of p1 and p2 14843b243b72SRobert Watson * must be held. Normally, p1 will be curproc, and a lock must 14857fd6a959SRobert Watson * be held for p2. 14863b243b72SRobert Watson * References: p1 and p2 must be valid for the lifetime of the call 14873b243b72SRobert Watson */ 1488a0f75161SRobert Watson int 1489a0f75161SRobert Watson p_cansched(struct proc *p1, struct proc *p2) 1490387d2c03SRobert Watson { 149191421ba2SRobert Watson int error; 1492387d2c03SRobert Watson 1493387d2c03SRobert Watson if (p1 == p2) 1494387d2c03SRobert Watson return (0); 149591421ba2SRobert Watson if ((error = prison_check(p1->p_ucred, p2->p_ucred))) 149691421ba2SRobert Watson return (error); 1497b1fc0ec1SRobert Watson if (p1->p_ucred->cr_ruid == p2->p_ucred->cr_ruid) 1498387d2c03SRobert Watson return (0); 1499b1fc0ec1SRobert Watson if (p1->p_ucred->cr_uid == p2->p_ucred->cr_ruid) 1500387d2c03SRobert Watson return (0); 15017fd6a959SRobert Watson if (suser_xxx(0, p1, PRISON_ROOT) == 0) 1502387d2c03SRobert Watson return (0); 1503387d2c03SRobert Watson 1504387d2c03SRobert Watson #ifdef CAPABILITIES 15054df571b1SRobert Watson if (!cap_check(NULL, p1, CAP_SYS_NICE, PRISON_ROOT)) 1506387d2c03SRobert Watson return (0); 1507387d2c03SRobert Watson #endif 1508387d2c03SRobert Watson 1509387d2c03SRobert Watson return (EPERM); 1510387d2c03SRobert Watson } 1511387d2c03SRobert Watson 15123b243b72SRobert Watson /* 15137fd6a959SRobert Watson * The kern_unprivileged_procdebug_permitted flag may be used to disable 15143b243b72SRobert Watson * a variety of unprivileged inter-process debugging services, including 15153b243b72SRobert Watson * some procfs functionality, ptrace(), and ktrace(). In the past, 15163b243b72SRobert Watson * inter-process debugging has been involved in a variety of security 15173b243b72SRobert Watson * problems, and sites not requiring the service might choose to disable it 15183b243b72SRobert Watson * when hardening systems. 15193b243b72SRobert Watson * 15203b243b72SRobert Watson * XXX: Should modifying and reading this variable require locking? 15213b243b72SRobert Watson */ 15220ef5652eSRobert Watson static int kern_unprivileged_procdebug_permitted = 1; 15230ef5652eSRobert Watson SYSCTL_INT(_kern_security, OID_AUTO, unprivileged_procdebug_permitted, 15240ef5652eSRobert Watson CTLFLAG_RW, &kern_unprivileged_procdebug_permitted, 0, 15250ef5652eSRobert Watson "Unprivileged processes may use process debugging facilities"); 15260ef5652eSRobert Watson 15277fd6a959SRobert Watson /*- 15287fd6a959SRobert Watson * Determine whether p1 may debug p2. 15297fd6a959SRobert Watson * Returns: 0 for permitted, an errno value otherwise 15307fd6a959SRobert Watson * Locks: Sufficient locks to protect various components of p1 and p2 15317fd6a959SRobert Watson * must be held. Normally, p1 will be curproc, and a lock must 15327fd6a959SRobert Watson * be held for p2. 15333b243b72SRobert Watson * References: p1 and p2 must be valid for the lifetime of the call 15343b243b72SRobert Watson */ 1535a0f75161SRobert Watson int 1536a0f75161SRobert Watson p_candebug(struct proc *p1, struct proc *p2) 1537387d2c03SRobert Watson { 1538387d2c03SRobert Watson int error; 1539387d2c03SRobert Watson 154032d18604SRobert Watson if (!kern_unprivileged_procdebug_permitted) { 154132d18604SRobert Watson error = suser_xxx(NULL, p1, PRISON_ROOT); 154232d18604SRobert Watson if (error) 154332d18604SRobert Watson return (error); 154432d18604SRobert Watson } 154532d18604SRobert Watson 154623fad5b6SDag-Erling Smørgrav if (p1 == p2) 154723fad5b6SDag-Erling Smørgrav return (0); 154823fad5b6SDag-Erling Smørgrav 154991421ba2SRobert Watson if ((error = prison_check(p1->p_ucred, p2->p_ucred))) 155091421ba2SRobert Watson return (error); 1551387d2c03SRobert Watson 15527fd6a959SRobert Watson /* 15537fd6a959SRobert Watson * Not owned by you, has done setuid (unless you're root). 15547fd6a959SRobert Watson * XXX add a CAP_SYS_PTRACE here? 15557fd6a959SRobert Watson */ 1556b1fc0ec1SRobert Watson if (p1->p_ucred->cr_uid != p2->p_ucred->cr_uid || 1557b1fc0ec1SRobert Watson p1->p_ucred->cr_uid != p2->p_ucred->cr_svuid || 1558b1fc0ec1SRobert Watson p1->p_ucred->cr_uid != p2->p_ucred->cr_ruid || 155932d18604SRobert Watson p2->p_flag & P_SUGID) { 156032d18604SRobert Watson error = suser_xxx(NULL, p1, PRISON_ROOT); 156132d18604SRobert Watson if (error) 1562387d2c03SRobert Watson return (error); 15637fd6a959SRobert Watson } 1564387d2c03SRobert Watson 15653ca719f1SRobert Watson /* can't trace init when securelevel > 0 */ 15663ca719f1SRobert Watson if (p2->p_pid == 1) { 15673ca719f1SRobert Watson error = securelevel_gt(p1->p_ucred, 0); 15683ca719f1SRobert Watson if (error) 15693ca719f1SRobert Watson return (error); 15703ca719f1SRobert Watson } 1571387d2c03SRobert Watson 15725fab7614SRobert Watson /* 15735fab7614SRobert Watson * Can't trace a process that's currently exec'ing. 15745fab7614SRobert Watson * XXX: Note, this is not a security policy decision, it's a 15755fab7614SRobert Watson * basic correctness/functionality decision. Therefore, this check 15765fab7614SRobert Watson * should be moved to the caller's of p_candebug(). 15775fab7614SRobert Watson */ 15789ca45e81SDag-Erling Smørgrav if ((p2->p_flag & P_INEXEC) != 0) 15799ca45e81SDag-Erling Smørgrav return (EAGAIN); 15809ca45e81SDag-Erling Smørgrav 1581387d2c03SRobert Watson return (0); 1582387d2c03SRobert Watson } 1583387d2c03SRobert Watson 1584a9e0361bSPoul-Henning Kamp /* 1585df8bae1dSRodney W. Grimes * Allocate a zeroed cred structure. 1586df8bae1dSRodney W. Grimes */ 1587df8bae1dSRodney W. Grimes struct ucred * 1588df8bae1dSRodney W. Grimes crget() 1589df8bae1dSRodney W. Grimes { 1590df8bae1dSRodney W. Grimes register struct ucred *cr; 1591df8bae1dSRodney W. Grimes 15921e5d626aSAlfred Perlstein MALLOC(cr, struct ucred *, sizeof(*cr), M_CRED, M_WAITOK | M_ZERO); 1593df8bae1dSRodney W. Grimes cr->cr_ref = 1; 15941e5d626aSAlfred Perlstein mtx_init(&cr->cr_mtx, "ucred", MTX_DEF); 1595df8bae1dSRodney W. Grimes return (cr); 1596df8bae1dSRodney W. Grimes } 1597df8bae1dSRodney W. Grimes 1598df8bae1dSRodney W. Grimes /* 15997fd6a959SRobert Watson * Claim another reference to a ucred structure. 16005c3f70d7SAlfred Perlstein */ 1601bd78ceceSJohn Baldwin struct ucred * 16025c3f70d7SAlfred Perlstein crhold(cr) 16035c3f70d7SAlfred Perlstein struct ucred *cr; 16045c3f70d7SAlfred Perlstein { 16055c3f70d7SAlfred Perlstein 16069ed346baSBosko Milekic mtx_lock(&cr->cr_mtx); 16075c3f70d7SAlfred Perlstein cr->cr_ref++; 1608bd78ceceSJohn Baldwin mtx_unlock(&cr->cr_mtx); 1609bd78ceceSJohn Baldwin return (cr); 16105c3f70d7SAlfred Perlstein } 16115c3f70d7SAlfred Perlstein 16125c3f70d7SAlfred Perlstein 16135c3f70d7SAlfred Perlstein /* 1614df8bae1dSRodney W. Grimes * Free a cred structure. 1615df8bae1dSRodney W. Grimes * Throws away space when ref count gets to 0. 1616df8bae1dSRodney W. Grimes */ 161726f9a767SRodney W. Grimes void 1618df8bae1dSRodney W. Grimes crfree(cr) 1619df8bae1dSRodney W. Grimes struct ucred *cr; 1620df8bae1dSRodney W. Grimes { 16211e5d626aSAlfred Perlstein 16229ed346baSBosko Milekic mtx_lock(&cr->cr_mtx); 1623e04670b7SAlfred Perlstein KASSERT(cr->cr_ref > 0, ("bad ucred refcount: %d", cr->cr_ref)); 1624f535380cSDon Lewis if (--cr->cr_ref == 0) { 16251e5d626aSAlfred Perlstein mtx_destroy(&cr->cr_mtx); 1626f535380cSDon Lewis /* 1627f535380cSDon Lewis * Some callers of crget(), such as nfs_statfs(), 1628f535380cSDon Lewis * allocate a temporary credential, but don't 1629f535380cSDon Lewis * allocate a uidinfo structure. 1630f535380cSDon Lewis */ 1631f535380cSDon Lewis if (cr->cr_uidinfo != NULL) 1632f535380cSDon Lewis uifree(cr->cr_uidinfo); 1633823c224eSRobert Watson if (cr->cr_ruidinfo != NULL) 1634823c224eSRobert Watson uifree(cr->cr_ruidinfo); 163591421ba2SRobert Watson /* 163691421ba2SRobert Watson * Free a prison, if any. 163791421ba2SRobert Watson */ 163891421ba2SRobert Watson if (jailed(cr)) 163991421ba2SRobert Watson prison_free(cr->cr_prison); 1640df8bae1dSRodney W. Grimes FREE((caddr_t)cr, M_CRED); 16411e5d626aSAlfred Perlstein } else { 16429ed346baSBosko Milekic mtx_unlock(&cr->cr_mtx); 1643df8bae1dSRodney W. Grimes } 1644f535380cSDon Lewis } 1645df8bae1dSRodney W. Grimes 1646df8bae1dSRodney W. Grimes /* 1647bd78ceceSJohn Baldwin * Check to see if this ucred is shared. 1648df8bae1dSRodney W. Grimes */ 1649bd78ceceSJohn Baldwin int 1650bd78ceceSJohn Baldwin crshared(cr) 1651df8bae1dSRodney W. Grimes struct ucred *cr; 1652df8bae1dSRodney W. Grimes { 1653bd78ceceSJohn Baldwin int shared; 1654df8bae1dSRodney W. Grimes 16559ed346baSBosko Milekic mtx_lock(&cr->cr_mtx); 1656bd78ceceSJohn Baldwin shared = (cr->cr_ref > 1); 16579ed346baSBosko Milekic mtx_unlock(&cr->cr_mtx); 1658bd78ceceSJohn Baldwin return (shared); 16591e5d626aSAlfred Perlstein } 1660bd78ceceSJohn Baldwin 1661bd78ceceSJohn Baldwin /* 1662bd78ceceSJohn Baldwin * Copy a ucred's contents from a template. Does not block. 1663bd78ceceSJohn Baldwin */ 1664bd78ceceSJohn Baldwin void 1665bd78ceceSJohn Baldwin crcopy(dest, src) 1666bd78ceceSJohn Baldwin struct ucred *dest, *src; 1667bd78ceceSJohn Baldwin { 1668bd78ceceSJohn Baldwin 1669bd78ceceSJohn Baldwin KASSERT(crshared(dest) == 0, ("crcopy of shared ucred")); 1670bd78ceceSJohn Baldwin bcopy(&src->cr_startcopy, &dest->cr_startcopy, 1671bd78ceceSJohn Baldwin (unsigned)((caddr_t)&src->cr_endcopy - 1672bd78ceceSJohn Baldwin (caddr_t)&src->cr_startcopy)); 1673bd78ceceSJohn Baldwin uihold(dest->cr_uidinfo); 1674bd78ceceSJohn Baldwin uihold(dest->cr_ruidinfo); 1675bd78ceceSJohn Baldwin if (jailed(dest)) 1676bd78ceceSJohn Baldwin prison_hold(dest->cr_prison); 1677df8bae1dSRodney W. Grimes } 1678df8bae1dSRodney W. Grimes 1679df8bae1dSRodney W. Grimes /* 1680df8bae1dSRodney W. Grimes * Dup cred struct to a new held one. 1681df8bae1dSRodney W. Grimes */ 1682df8bae1dSRodney W. Grimes struct ucred * 1683df8bae1dSRodney W. Grimes crdup(cr) 1684df8bae1dSRodney W. Grimes struct ucred *cr; 1685df8bae1dSRodney W. Grimes { 1686df8bae1dSRodney W. Grimes struct ucred *newcr; 1687df8bae1dSRodney W. Grimes 1688bd78ceceSJohn Baldwin newcr = crget(); 1689bd78ceceSJohn Baldwin crcopy(newcr, cr); 1690df8bae1dSRodney W. Grimes return (newcr); 1691df8bae1dSRodney W. Grimes } 1692df8bae1dSRodney W. Grimes 1693df8bae1dSRodney W. Grimes /* 1694df8bae1dSRodney W. Grimes * Get login name, if available. 1695df8bae1dSRodney W. Grimes */ 1696d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 1697df8bae1dSRodney W. Grimes struct getlogin_args { 1698df8bae1dSRodney W. Grimes char *namebuf; 1699df8bae1dSRodney W. Grimes u_int namelen; 1700df8bae1dSRodney W. Grimes }; 1701d2d3e875SBruce Evans #endif 1702835a82eeSMatthew Dillon /* 1703835a82eeSMatthew Dillon * MPSAFE 1704835a82eeSMatthew Dillon */ 1705df8bae1dSRodney W. Grimes /* ARGSUSED */ 170626f9a767SRodney W. Grimes int 1707b40ce416SJulian Elischer getlogin(td, uap) 1708b40ce416SJulian Elischer struct thread *td; 1709df8bae1dSRodney W. Grimes struct getlogin_args *uap; 1710df8bae1dSRodney W. Grimes { 1711835a82eeSMatthew Dillon int error; 1712b40ce416SJulian Elischer struct proc *p = td->td_proc; 1713df8bae1dSRodney W. Grimes 1714835a82eeSMatthew Dillon mtx_lock(&Giant); 171530cf3ac4SAndrey A. Chernov if (uap->namelen > MAXLOGNAME) 171653490b76SAndrey A. Chernov uap->namelen = MAXLOGNAME; 1717835a82eeSMatthew Dillon error = copyout((caddr_t) p->p_pgrp->pg_session->s_login, 1718835a82eeSMatthew Dillon (caddr_t) uap->namebuf, uap->namelen); 1719835a82eeSMatthew Dillon mtx_unlock(&Giant); 1720835a82eeSMatthew Dillon return(error); 1721df8bae1dSRodney W. Grimes } 1722df8bae1dSRodney W. Grimes 1723df8bae1dSRodney W. Grimes /* 1724df8bae1dSRodney W. Grimes * Set login name. 1725df8bae1dSRodney W. Grimes */ 1726d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 1727df8bae1dSRodney W. Grimes struct setlogin_args { 1728df8bae1dSRodney W. Grimes char *namebuf; 1729df8bae1dSRodney W. Grimes }; 1730d2d3e875SBruce Evans #endif 1731835a82eeSMatthew Dillon /* 1732835a82eeSMatthew Dillon * MPSAFE 1733835a82eeSMatthew Dillon */ 1734df8bae1dSRodney W. Grimes /* ARGSUSED */ 173526f9a767SRodney W. Grimes int 1736b40ce416SJulian Elischer setlogin(td, uap) 1737b40ce416SJulian Elischer struct thread *td; 1738df8bae1dSRodney W. Grimes struct setlogin_args *uap; 1739df8bae1dSRodney W. Grimes { 1740b40ce416SJulian Elischer struct proc *p = td->td_proc; 1741df8bae1dSRodney W. Grimes int error; 1742964ca0caSAndrey A. Chernov char logintmp[MAXLOGNAME]; 1743df8bae1dSRodney W. Grimes 1744835a82eeSMatthew Dillon mtx_lock(&Giant); 174575c13541SPoul-Henning Kamp if ((error = suser_xxx(0, p, PRISON_ROOT))) 1746835a82eeSMatthew Dillon goto done2; 1747184989c2SDavid Nugent error = copyinstr((caddr_t) uap->namebuf, (caddr_t) logintmp, 174810d4743fSDoug Rabson sizeof(logintmp), (size_t *)0); 1749835a82eeSMatthew Dillon if (error == ENAMETOOLONG) { 1750df8bae1dSRodney W. Grimes error = EINVAL; 1751835a82eeSMatthew Dillon } else if (!error) { 1752184989c2SDavid Nugent (void) memcpy(p->p_pgrp->pg_session->s_login, logintmp, 1753964ca0caSAndrey A. Chernov sizeof(logintmp)); 1754835a82eeSMatthew Dillon } 1755835a82eeSMatthew Dillon done2: 1756835a82eeSMatthew Dillon mtx_unlock(&Giant); 1757df8bae1dSRodney W. Grimes return (error); 1758df8bae1dSRodney W. Grimes } 1759d5f81602SSean Eric Fagan 1760d5f81602SSean Eric Fagan void 1761d5f81602SSean Eric Fagan setsugid(p) 1762d5f81602SSean Eric Fagan struct proc *p; 1763d5f81602SSean Eric Fagan { 1764d5f81602SSean Eric Fagan p->p_flag |= P_SUGID; 176589361835SSean Eric Fagan if (!(p->p_pfsflags & PF_ISUGID)) 1766d5f81602SSean Eric Fagan p->p_stops = 0; 1767d5f81602SSean Eric Fagan } 1768f535380cSDon Lewis 17697fd6a959SRobert Watson /*- 17707fd6a959SRobert Watson * Change a process's effective uid. 1771b1fc0ec1SRobert Watson * Side effects: newcred->cr_uid and newcred->cr_uidinfo will be modified. 1772b1fc0ec1SRobert Watson * References: newcred must be an exclusive credential reference for the 1773b1fc0ec1SRobert Watson * duration of the call. 1774f535380cSDon Lewis */ 1775f535380cSDon Lewis void 1776b1fc0ec1SRobert Watson change_euid(newcred, euid) 1777b1fc0ec1SRobert Watson struct ucred *newcred; 1778f535380cSDon Lewis uid_t euid; 1779f535380cSDon Lewis { 1780f535380cSDon Lewis 1781b1fc0ec1SRobert Watson newcred->cr_uid = euid; 1782b1fc0ec1SRobert Watson uifree(newcred->cr_uidinfo); 1783b1fc0ec1SRobert Watson newcred->cr_uidinfo = uifind(euid); 1784f535380cSDon Lewis } 1785f535380cSDon Lewis 17867fd6a959SRobert Watson /*- 17877fd6a959SRobert Watson * Change a process's effective gid. 1788b1fc0ec1SRobert Watson * Side effects: newcred->cr_gid will be modified. 1789b1fc0ec1SRobert Watson * References: newcred must be an exclusive credential reference for the 1790b1fc0ec1SRobert Watson * duration of the call. 1791f535380cSDon Lewis */ 1792810bfc8eSAndrew Gallatin void 1793b1fc0ec1SRobert Watson change_egid(newcred, egid) 1794b1fc0ec1SRobert Watson struct ucred *newcred; 1795b1fc0ec1SRobert Watson gid_t egid; 1796b1fc0ec1SRobert Watson { 1797b1fc0ec1SRobert Watson 1798b1fc0ec1SRobert Watson newcred->cr_groups[0] = egid; 1799b1fc0ec1SRobert Watson } 1800b1fc0ec1SRobert Watson 18017fd6a959SRobert Watson /*- 18027fd6a959SRobert Watson * Change a process's real uid. 1803b1fc0ec1SRobert Watson * Side effects: newcred->cr_ruid will be updated, newcred->cr_ruidinfo 1804b1fc0ec1SRobert Watson * will be updated, and the old and new cr_ruidinfo proc 1805b1fc0ec1SRobert Watson * counts will be updated. 1806b1fc0ec1SRobert Watson * References: newcred must be an exclusive credential reference for the 1807b1fc0ec1SRobert Watson * duration of the call. 1808b1fc0ec1SRobert Watson */ 1809b1fc0ec1SRobert Watson void 1810b1fc0ec1SRobert Watson change_ruid(newcred, ruid) 1811b1fc0ec1SRobert Watson struct ucred *newcred; 1812f535380cSDon Lewis uid_t ruid; 1813f535380cSDon Lewis { 1814f535380cSDon Lewis 1815b1fc0ec1SRobert Watson (void)chgproccnt(newcred->cr_ruidinfo, -1, 0); 1816b1fc0ec1SRobert Watson newcred->cr_ruid = ruid; 1817b1fc0ec1SRobert Watson uifree(newcred->cr_ruidinfo); 1818b1fc0ec1SRobert Watson newcred->cr_ruidinfo = uifind(ruid); 1819b1fc0ec1SRobert Watson (void)chgproccnt(newcred->cr_ruidinfo, 1, 0); 1820b1fc0ec1SRobert Watson } 1821b1fc0ec1SRobert Watson 18227fd6a959SRobert Watson /*- 18237fd6a959SRobert Watson * Change a process's real gid. 1824b1fc0ec1SRobert Watson * Side effects: newcred->cr_rgid will be updated. 1825b1fc0ec1SRobert Watson * References: newcred must be an exclusive credential reference for the 1826b1fc0ec1SRobert Watson * duration of the call. 1827b1fc0ec1SRobert Watson */ 1828b1fc0ec1SRobert Watson void 1829b1fc0ec1SRobert Watson change_rgid(newcred, rgid) 1830b1fc0ec1SRobert Watson struct ucred *newcred; 1831b1fc0ec1SRobert Watson gid_t rgid; 1832b1fc0ec1SRobert Watson { 1833b1fc0ec1SRobert Watson 1834b1fc0ec1SRobert Watson newcred->cr_rgid = rgid; 1835b1fc0ec1SRobert Watson } 1836b1fc0ec1SRobert Watson 18377fd6a959SRobert Watson /*- 18387fd6a959SRobert Watson * Change a process's saved uid. 1839b1fc0ec1SRobert Watson * Side effects: newcred->cr_svuid will be updated. 1840b1fc0ec1SRobert Watson * References: newcred must be an exclusive credential reference for the 1841b1fc0ec1SRobert Watson * duration of the call. 1842b1fc0ec1SRobert Watson */ 1843b1fc0ec1SRobert Watson void 1844b1fc0ec1SRobert Watson change_svuid(newcred, svuid) 1845b1fc0ec1SRobert Watson struct ucred *newcred; 1846b1fc0ec1SRobert Watson uid_t svuid; 1847b1fc0ec1SRobert Watson { 1848b1fc0ec1SRobert Watson 1849b1fc0ec1SRobert Watson newcred->cr_svuid = svuid; 1850b1fc0ec1SRobert Watson } 1851b1fc0ec1SRobert Watson 18527fd6a959SRobert Watson /*- 18537fd6a959SRobert Watson * Change a process's saved gid. 1854b1fc0ec1SRobert Watson * Side effects: newcred->cr_svgid will be updated. 1855b1fc0ec1SRobert Watson * References: newcred must be an exclusive credential reference for the 1856b1fc0ec1SRobert Watson * duration of the call. 1857b1fc0ec1SRobert Watson */ 1858b1fc0ec1SRobert Watson void 1859b1fc0ec1SRobert Watson change_svgid(newcred, svgid) 1860b1fc0ec1SRobert Watson struct ucred *newcred; 1861b1fc0ec1SRobert Watson gid_t svgid; 1862b1fc0ec1SRobert Watson { 1863b1fc0ec1SRobert Watson 1864b1fc0ec1SRobert Watson newcred->cr_svgid = svgid; 1865f535380cSDon Lewis } 1866