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 /* 7698f03f90SJake Burkholder * getpid - MP SAFE 7736e9f877SMatthew Dillon */ 7898f03f90SJake Burkholder 79df8bae1dSRodney W. Grimes /* ARGSUSED */ 8026f9a767SRodney W. Grimes int 81cb226aaaSPoul-Henning Kamp getpid(p, uap) 82df8bae1dSRodney W. Grimes struct proc *p; 83ad7507e2SSteven Wallace struct getpid_args *uap; 84df8bae1dSRodney W. Grimes { 85df8bae1dSRodney W. Grimes 86cb226aaaSPoul-Henning Kamp p->p_retval[0] = p->p_pid; 87df8bae1dSRodney W. Grimes #if defined(COMPAT_43) || defined(COMPAT_SUNOS) 88bae3a80bSJohn Baldwin PROC_LOCK(p); 89cb226aaaSPoul-Henning Kamp p->p_retval[1] = p->p_pptr->p_pid; 90bae3a80bSJohn Baldwin PROC_UNLOCK(p); 91df8bae1dSRodney W. Grimes #endif 92df8bae1dSRodney W. Grimes return (0); 93df8bae1dSRodney W. Grimes } 94df8bae1dSRodney W. Grimes 9598f03f90SJake Burkholder /* 9698f03f90SJake Burkholder * getppid - MP SAFE 9798f03f90SJake Burkholder */ 9898f03f90SJake Burkholder 99d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 100ad7507e2SSteven Wallace struct getppid_args { 101ad7507e2SSteven Wallace int dummy; 102ad7507e2SSteven Wallace }; 103d2d3e875SBruce Evans #endif 104df8bae1dSRodney W. Grimes /* ARGSUSED */ 10526f9a767SRodney W. Grimes int 106cb226aaaSPoul-Henning Kamp getppid(p, uap) 107df8bae1dSRodney W. Grimes struct proc *p; 108ad7507e2SSteven Wallace struct getppid_args *uap; 109df8bae1dSRodney W. Grimes { 110df8bae1dSRodney W. Grimes 111bae3a80bSJohn Baldwin PROC_LOCK(p); 112cb226aaaSPoul-Henning Kamp p->p_retval[0] = p->p_pptr->p_pid; 113bae3a80bSJohn Baldwin PROC_UNLOCK(p); 114df8bae1dSRodney W. Grimes return (0); 115df8bae1dSRodney W. Grimes } 116df8bae1dSRodney W. Grimes 11736e9f877SMatthew Dillon /* 11836e9f877SMatthew Dillon * Get process group ID; note that POSIX getpgrp takes no parameter 11936e9f877SMatthew Dillon * 12036e9f877SMatthew Dillon * MP SAFE 12136e9f877SMatthew Dillon */ 122d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 123ad7507e2SSteven Wallace struct getpgrp_args { 124ad7507e2SSteven Wallace int dummy; 125ad7507e2SSteven Wallace }; 126d2d3e875SBruce Evans #endif 127ad7507e2SSteven Wallace 12826f9a767SRodney W. Grimes int 129cb226aaaSPoul-Henning Kamp getpgrp(p, uap) 130df8bae1dSRodney W. Grimes struct proc *p; 131ad7507e2SSteven Wallace struct getpgrp_args *uap; 132df8bae1dSRodney W. Grimes { 133df8bae1dSRodney W. Grimes 134cb226aaaSPoul-Henning Kamp p->p_retval[0] = p->p_pgrp->pg_id; 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 1441a5018a0SPeter Wemm 1451a5018a0SPeter Wemm int 146cb226aaaSPoul-Henning Kamp getpgid(p, uap) 1471a5018a0SPeter Wemm struct proc *p; 1481a5018a0SPeter Wemm struct getpgid_args *uap; 1491a5018a0SPeter Wemm { 15065de0c7aSDon Lewis struct proc *pt; 151eb9e5c1dSRobert Watson int error; 15265de0c7aSDon Lewis 1531a5018a0SPeter Wemm if (uap->pid == 0) 15433a9ed9dSJohn Baldwin p->p_retval[0] = p->p_pgrp->pg_id; 15533a9ed9dSJohn Baldwin else { 15633a9ed9dSJohn Baldwin if ((pt = pfind(uap->pid)) == NULL) 1571a5018a0SPeter Wemm return ESRCH; 158a0f75161SRobert Watson if ((error = p_cansee(p, pt))) { 15933a9ed9dSJohn Baldwin PROC_UNLOCK(pt); 160eb9e5c1dSRobert Watson return (error); 16133a9ed9dSJohn Baldwin } 16265de0c7aSDon Lewis p->p_retval[0] = pt->p_pgrp->pg_id; 16333a9ed9dSJohn Baldwin PROC_UNLOCK(pt); 16433a9ed9dSJohn Baldwin } 1651a5018a0SPeter Wemm return 0; 1661a5018a0SPeter Wemm } 1671a5018a0SPeter Wemm 1681a5018a0SPeter Wemm /* 1691a5018a0SPeter Wemm * Get an arbitary pid's session id. 1701a5018a0SPeter Wemm */ 1711a5018a0SPeter Wemm #ifndef _SYS_SYSPROTO_H_ 1721a5018a0SPeter Wemm struct getsid_args { 1731a5018a0SPeter Wemm pid_t pid; 1741a5018a0SPeter Wemm }; 1751a5018a0SPeter Wemm #endif 1761a5018a0SPeter Wemm 1771a5018a0SPeter Wemm int 178cb226aaaSPoul-Henning Kamp getsid(p, uap) 1791a5018a0SPeter Wemm struct proc *p; 1801a5018a0SPeter Wemm struct getsid_args *uap; 1811a5018a0SPeter Wemm { 18265de0c7aSDon Lewis struct proc *pt; 183eb9e5c1dSRobert Watson int error; 18465de0c7aSDon Lewis 1851a5018a0SPeter Wemm if (uap->pid == 0) 18633a9ed9dSJohn Baldwin p->p_retval[0] = p->p_session->s_sid; 18733a9ed9dSJohn Baldwin else { 18833a9ed9dSJohn Baldwin if ((pt = pfind(uap->pid)) == NULL) 1891a5018a0SPeter Wemm return ESRCH; 190a0f75161SRobert Watson if ((error = p_cansee(p, pt))) { 19133a9ed9dSJohn Baldwin PROC_UNLOCK(pt); 192eb9e5c1dSRobert Watson return (error); 19333a9ed9dSJohn Baldwin } 19465de0c7aSDon Lewis p->p_retval[0] = pt->p_session->s_sid; 19533a9ed9dSJohn Baldwin PROC_UNLOCK(pt); 19633a9ed9dSJohn Baldwin } 1971a5018a0SPeter Wemm return 0; 1981a5018a0SPeter Wemm } 1991a5018a0SPeter Wemm 2001a5018a0SPeter Wemm 2017c8fdcbdSMatthew Dillon /* 2027c8fdcbdSMatthew Dillon * getuid() - MP SAFE 2037c8fdcbdSMatthew Dillon */ 204d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 205ad7507e2SSteven Wallace struct getuid_args { 206ad7507e2SSteven Wallace int dummy; 207ad7507e2SSteven Wallace }; 208d2d3e875SBruce Evans #endif 209ad7507e2SSteven Wallace 210df8bae1dSRodney W. Grimes /* ARGSUSED */ 21126f9a767SRodney W. Grimes int 212cb226aaaSPoul-Henning Kamp getuid(p, uap) 213df8bae1dSRodney W. Grimes struct proc *p; 214ad7507e2SSteven Wallace struct getuid_args *uap; 215df8bae1dSRodney W. Grimes { 216df8bae1dSRodney W. Grimes 217b1fc0ec1SRobert Watson p->p_retval[0] = p->p_ucred->cr_ruid; 218df8bae1dSRodney W. Grimes #if defined(COMPAT_43) || defined(COMPAT_SUNOS) 219cb226aaaSPoul-Henning Kamp p->p_retval[1] = p->p_ucred->cr_uid; 220df8bae1dSRodney W. Grimes #endif 221df8bae1dSRodney W. Grimes return (0); 222df8bae1dSRodney W. Grimes } 223df8bae1dSRodney W. Grimes 2247c8fdcbdSMatthew Dillon /* 2257c8fdcbdSMatthew Dillon * geteuid() - MP SAFE 2267c8fdcbdSMatthew Dillon */ 227d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 228ad7507e2SSteven Wallace struct geteuid_args { 229ad7507e2SSteven Wallace int dummy; 230ad7507e2SSteven Wallace }; 231d2d3e875SBruce Evans #endif 232ad7507e2SSteven Wallace 233df8bae1dSRodney W. Grimes /* ARGSUSED */ 23426f9a767SRodney W. Grimes int 235cb226aaaSPoul-Henning Kamp geteuid(p, uap) 236df8bae1dSRodney W. Grimes struct proc *p; 237ad7507e2SSteven Wallace struct geteuid_args *uap; 238df8bae1dSRodney W. Grimes { 239df8bae1dSRodney W. Grimes 240cb226aaaSPoul-Henning Kamp p->p_retval[0] = p->p_ucred->cr_uid; 241df8bae1dSRodney W. Grimes return (0); 242df8bae1dSRodney W. Grimes } 243df8bae1dSRodney W. Grimes 2447c8fdcbdSMatthew Dillon /* 2457c8fdcbdSMatthew Dillon * getgid() - MP SAFE 2467c8fdcbdSMatthew Dillon */ 247d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 248ad7507e2SSteven Wallace struct getgid_args { 249ad7507e2SSteven Wallace int dummy; 250ad7507e2SSteven Wallace }; 251d2d3e875SBruce Evans #endif 252ad7507e2SSteven Wallace 253df8bae1dSRodney W. Grimes /* ARGSUSED */ 25426f9a767SRodney W. Grimes int 255cb226aaaSPoul-Henning Kamp getgid(p, uap) 256df8bae1dSRodney W. Grimes struct proc *p; 257ad7507e2SSteven Wallace struct getgid_args *uap; 258df8bae1dSRodney W. Grimes { 259df8bae1dSRodney W. Grimes 260b1fc0ec1SRobert Watson p->p_retval[0] = p->p_ucred->cr_rgid; 261df8bae1dSRodney W. Grimes #if defined(COMPAT_43) || defined(COMPAT_SUNOS) 262cb226aaaSPoul-Henning Kamp p->p_retval[1] = p->p_ucred->cr_groups[0]; 263df8bae1dSRodney W. Grimes #endif 264df8bae1dSRodney W. Grimes return (0); 265df8bae1dSRodney W. Grimes } 266df8bae1dSRodney W. Grimes 267df8bae1dSRodney W. Grimes /* 268df8bae1dSRodney W. Grimes * Get effective group ID. The "egid" is groups[0], and could be obtained 269df8bae1dSRodney W. Grimes * via getgroups. This syscall exists because it is somewhat painful to do 270df8bae1dSRodney W. Grimes * correctly in a library function. 271df8bae1dSRodney W. Grimes */ 272d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 273ad7507e2SSteven Wallace struct getegid_args { 274ad7507e2SSteven Wallace int dummy; 275ad7507e2SSteven Wallace }; 276d2d3e875SBruce Evans #endif 277ad7507e2SSteven Wallace 278df8bae1dSRodney W. Grimes /* ARGSUSED */ 27926f9a767SRodney W. Grimes int 280cb226aaaSPoul-Henning Kamp getegid(p, uap) 281df8bae1dSRodney W. Grimes struct proc *p; 282ad7507e2SSteven Wallace struct getegid_args *uap; 283df8bae1dSRodney W. Grimes { 284df8bae1dSRodney W. Grimes 285cb226aaaSPoul-Henning Kamp p->p_retval[0] = p->p_ucred->cr_groups[0]; 286df8bae1dSRodney W. Grimes return (0); 287df8bae1dSRodney W. Grimes } 288df8bae1dSRodney W. Grimes 289d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 290df8bae1dSRodney W. Grimes struct getgroups_args { 291df8bae1dSRodney W. Grimes u_int gidsetsize; 292df8bae1dSRodney W. Grimes gid_t *gidset; 293df8bae1dSRodney W. Grimes }; 294d2d3e875SBruce Evans #endif 29526f9a767SRodney W. Grimes int 296cb226aaaSPoul-Henning Kamp getgroups(p, uap) 297df8bae1dSRodney W. Grimes struct proc *p; 298df8bae1dSRodney W. Grimes register struct getgroups_args *uap; 299df8bae1dSRodney W. Grimes { 300b1fc0ec1SRobert Watson struct ucred *cred = p->p_ucred; 301b1fc0ec1SRobert Watson u_int ngrp; 302df8bae1dSRodney W. Grimes int error; 303df8bae1dSRodney W. Grimes 304df8bae1dSRodney W. Grimes if ((ngrp = uap->gidsetsize) == 0) { 305b1fc0ec1SRobert Watson p->p_retval[0] = cred->cr_ngroups; 306df8bae1dSRodney W. Grimes return (0); 307df8bae1dSRodney W. Grimes } 308b1fc0ec1SRobert Watson if (ngrp < cred->cr_ngroups) 309df8bae1dSRodney W. Grimes return (EINVAL); 310b1fc0ec1SRobert Watson ngrp = cred->cr_ngroups; 311b1fc0ec1SRobert Watson if ((error = copyout((caddr_t)cred->cr_groups, 312bb56ec4aSPoul-Henning Kamp (caddr_t)uap->gidset, ngrp * sizeof(gid_t)))) 313df8bae1dSRodney W. Grimes return (error); 314cb226aaaSPoul-Henning Kamp p->p_retval[0] = ngrp; 315df8bae1dSRodney W. Grimes return (0); 316df8bae1dSRodney W. Grimes } 317df8bae1dSRodney W. Grimes 318d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 31982970b81SBruce Evans struct setsid_args { 320ad7507e2SSteven Wallace int dummy; 321ad7507e2SSteven Wallace }; 322d2d3e875SBruce Evans #endif 323ad7507e2SSteven Wallace 324df8bae1dSRodney W. Grimes /* ARGSUSED */ 32526f9a767SRodney W. Grimes int 326cb226aaaSPoul-Henning Kamp setsid(p, uap) 327df8bae1dSRodney W. Grimes register struct proc *p; 32882970b81SBruce Evans struct setsid_args *uap; 329df8bae1dSRodney W. Grimes { 330df8bae1dSRodney W. Grimes 331df8bae1dSRodney W. Grimes if (p->p_pgid == p->p_pid || pgfind(p->p_pid)) { 332df8bae1dSRodney W. Grimes return (EPERM); 333df8bae1dSRodney W. Grimes } else { 334df8bae1dSRodney W. Grimes (void)enterpgrp(p, p->p_pid, 1); 335cb226aaaSPoul-Henning Kamp p->p_retval[0] = p->p_pid; 336df8bae1dSRodney W. Grimes return (0); 337df8bae1dSRodney W. Grimes } 338df8bae1dSRodney W. Grimes } 339df8bae1dSRodney W. Grimes 340df8bae1dSRodney W. Grimes /* 341df8bae1dSRodney W. Grimes * set process group (setpgid/old setpgrp) 342df8bae1dSRodney W. Grimes * 343df8bae1dSRodney W. Grimes * caller does setpgid(targpid, targpgid) 344df8bae1dSRodney W. Grimes * 345df8bae1dSRodney W. Grimes * pid must be caller or child of caller (ESRCH) 346df8bae1dSRodney W. Grimes * if a child 347df8bae1dSRodney W. Grimes * pid must be in same session (EPERM) 348df8bae1dSRodney W. Grimes * pid can't have done an exec (EACCES) 349df8bae1dSRodney W. Grimes * if pgid != pid 350df8bae1dSRodney W. Grimes * there must exist some pid in same session having pgid (EPERM) 351df8bae1dSRodney W. Grimes * pid must not be session leader (EPERM) 352df8bae1dSRodney W. Grimes */ 353d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 354df8bae1dSRodney W. Grimes struct setpgid_args { 355df8bae1dSRodney W. Grimes int pid; /* target process id */ 356df8bae1dSRodney W. Grimes int pgid; /* target pgrp id */ 357df8bae1dSRodney W. Grimes }; 358d2d3e875SBruce Evans #endif 359df8bae1dSRodney W. Grimes /* ARGSUSED */ 36026f9a767SRodney W. Grimes int 361cb226aaaSPoul-Henning Kamp setpgid(curp, uap) 362df8bae1dSRodney W. Grimes struct proc *curp; 363df8bae1dSRodney W. Grimes register struct setpgid_args *uap; 364df8bae1dSRodney W. Grimes { 365df8bae1dSRodney W. Grimes register struct proc *targp; /* target process */ 366df8bae1dSRodney W. Grimes register struct pgrp *pgrp; /* target pgrp */ 367eb9e5c1dSRobert Watson int error; 368df8bae1dSRodney W. Grimes 36978f64bccSBruce Evans if (uap->pgid < 0) 37078f64bccSBruce Evans return (EINVAL); 371df8bae1dSRodney W. Grimes if (uap->pid != 0 && uap->pid != curp->p_pid) { 37233a9ed9dSJohn Baldwin if ((targp = pfind(uap->pid)) == NULL || !inferior(targp)) { 37333a9ed9dSJohn Baldwin if (targp) 37433a9ed9dSJohn Baldwin PROC_UNLOCK(targp); 375df8bae1dSRodney W. Grimes return (ESRCH); 37633a9ed9dSJohn Baldwin } 377a0f75161SRobert Watson if ((error = p_cansee(curproc, targp))) { 37833a9ed9dSJohn Baldwin PROC_UNLOCK(targp); 379eb9e5c1dSRobert Watson return (error); 38033a9ed9dSJohn Baldwin } 38133a9ed9dSJohn Baldwin if (targp->p_pgrp == NULL || 38233a9ed9dSJohn Baldwin targp->p_session != curp->p_session) { 38333a9ed9dSJohn Baldwin PROC_UNLOCK(targp); 384df8bae1dSRodney W. Grimes return (EPERM); 38533a9ed9dSJohn Baldwin } 38633a9ed9dSJohn Baldwin if (targp->p_flag & P_EXEC) { 38733a9ed9dSJohn Baldwin PROC_UNLOCK(targp); 388df8bae1dSRodney W. Grimes return (EACCES); 38933a9ed9dSJohn Baldwin } 39033a9ed9dSJohn Baldwin } else { 391df8bae1dSRodney W. Grimes targp = curp; 39233a9ed9dSJohn Baldwin PROC_LOCK(curp); /* XXX: not needed */ 39333a9ed9dSJohn Baldwin } 39433a9ed9dSJohn Baldwin if (SESS_LEADER(targp)) { 39533a9ed9dSJohn Baldwin PROC_UNLOCK(targp); 396df8bae1dSRodney W. Grimes return (EPERM); 39733a9ed9dSJohn Baldwin } 398df8bae1dSRodney W. Grimes if (uap->pgid == 0) 399df8bae1dSRodney W. Grimes uap->pgid = targp->p_pid; 400df8bae1dSRodney W. Grimes else if (uap->pgid != targp->p_pid) 401df8bae1dSRodney W. Grimes if ((pgrp = pgfind(uap->pgid)) == 0 || 40233a9ed9dSJohn Baldwin pgrp->pg_session != curp->p_session) { 40333a9ed9dSJohn Baldwin PROC_UNLOCK(targp); 404df8bae1dSRodney W. Grimes return (EPERM); 40533a9ed9dSJohn Baldwin } 40633a9ed9dSJohn Baldwin /* XXX: We should probably hold the lock across enterpgrp. */ 40733a9ed9dSJohn Baldwin PROC_UNLOCK(targp); 408df8bae1dSRodney W. Grimes return (enterpgrp(targp, uap->pgid, 0)); 409df8bae1dSRodney W. Grimes } 410df8bae1dSRodney W. Grimes 411a08f4bf6SPeter Wemm /* 412a08f4bf6SPeter Wemm * Use the clause in B.4.2.2 that allows setuid/setgid to be 4.2/4.3BSD 4132fa72ea7SJeroen Ruigrok van der Werven * compatible. It says that setting the uid/gid to euid/egid is a special 414a08f4bf6SPeter Wemm * case of "appropriate privilege". Once the rules are expanded out, this 415a08f4bf6SPeter Wemm * basically means that setuid(nnn) sets all three id's, in all permitted 416a08f4bf6SPeter Wemm * cases unless _POSIX_SAVED_IDS is enabled. In that case, setuid(getuid()) 417a08f4bf6SPeter Wemm * does not set the saved id - this is dangerous for traditional BSD 418a08f4bf6SPeter Wemm * programs. For this reason, we *really* do not want to set 419a08f4bf6SPeter Wemm * _POSIX_SAVED_IDS and do not want to clear POSIX_APPENDIX_B_4_2_2. 420a08f4bf6SPeter Wemm */ 421a08f4bf6SPeter Wemm #define POSIX_APPENDIX_B_4_2_2 422a08f4bf6SPeter Wemm 423d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 424df8bae1dSRodney W. Grimes struct setuid_args { 425df8bae1dSRodney W. Grimes uid_t uid; 426df8bae1dSRodney W. Grimes }; 427d2d3e875SBruce Evans #endif 428df8bae1dSRodney W. Grimes /* ARGSUSED */ 42926f9a767SRodney W. Grimes int 430cb226aaaSPoul-Henning Kamp setuid(p, uap) 431df8bae1dSRodney W. Grimes struct proc *p; 432df8bae1dSRodney W. Grimes struct setuid_args *uap; 433df8bae1dSRodney W. Grimes { 434b1fc0ec1SRobert Watson struct ucred *newcred, *oldcred; 435b1fc0ec1SRobert Watson uid_t uid; 436df8bae1dSRodney W. Grimes int error; 437df8bae1dSRodney W. Grimes 438b1fc0ec1SRobert Watson uid = uap->uid; 439b1fc0ec1SRobert Watson oldcred = p->p_ucred; 440a08f4bf6SPeter Wemm /* 441a08f4bf6SPeter Wemm * See if we have "permission" by POSIX 1003.1 rules. 442a08f4bf6SPeter Wemm * 443a08f4bf6SPeter Wemm * Note that setuid(geteuid()) is a special case of 444a08f4bf6SPeter Wemm * "appropriate privileges" in appendix B.4.2.2. We need 4452fa72ea7SJeroen Ruigrok van der Werven * to use this clause to be compatible with traditional BSD 446a08f4bf6SPeter Wemm * semantics. Basically, it means that "setuid(xx)" sets all 447a08f4bf6SPeter Wemm * three id's (assuming you have privs). 448a08f4bf6SPeter Wemm * 449a08f4bf6SPeter Wemm * Notes on the logic. We do things in three steps. 450a08f4bf6SPeter Wemm * 1: We determine if the euid is going to change, and do EPERM 451a08f4bf6SPeter Wemm * right away. We unconditionally change the euid later if this 452a08f4bf6SPeter Wemm * test is satisfied, simplifying that part of the logic. 453a08f4bf6SPeter Wemm * 2: We determine if the real and/or saved uid's are going to 454a08f4bf6SPeter Wemm * change. Determined by compile options. 455a08f4bf6SPeter Wemm * 3: Change euid last. (after tests in #2 for "appropriate privs") 456a08f4bf6SPeter Wemm */ 457b1fc0ec1SRobert Watson if (uid != oldcred->cr_ruid && /* allow setuid(getuid()) */ 4583f246666SAndrey A. Chernov #ifdef _POSIX_SAVED_IDS 459b1fc0ec1SRobert Watson uid != oldcred->cr_svuid && /* allow setuid(saved gid) */ 460a08f4bf6SPeter Wemm #endif 461a08f4bf6SPeter Wemm #ifdef POSIX_APPENDIX_B_4_2_2 /* Use BSD-compat clause from B.4.2.2 */ 462b1fc0ec1SRobert Watson uid != oldcred->cr_uid && /* allow setuid(geteuid()) */ 4633f246666SAndrey A. Chernov #endif 464b1fc0ec1SRobert Watson (error = suser_xxx(oldcred, NULL, PRISON_ROOT))) 465df8bae1dSRodney W. Grimes return (error); 466a08f4bf6SPeter Wemm 467b1fc0ec1SRobert Watson newcred = crdup(oldcred); 468a08f4bf6SPeter Wemm #ifdef _POSIX_SAVED_IDS 469df8bae1dSRodney W. Grimes /* 470a08f4bf6SPeter Wemm * Do we have "appropriate privileges" (are we root or uid == euid) 471a08f4bf6SPeter Wemm * If so, we are changing the real uid and/or saved uid. 472df8bae1dSRodney W. Grimes */ 4733f246666SAndrey A. Chernov if ( 474a08f4bf6SPeter Wemm #ifdef POSIX_APPENDIX_B_4_2_2 /* Use the clause from B.4.2.2 */ 475b1fc0ec1SRobert Watson uid == oldcred->cr_uid || 4763f246666SAndrey A. Chernov #endif 477b1fc0ec1SRobert Watson suser_xxx(oldcred, NULL, PRISON_ROOT) == 0) /* we are using privs */ 478a08f4bf6SPeter Wemm #endif 479a08f4bf6SPeter Wemm { 480a08f4bf6SPeter Wemm /* 481f535380cSDon Lewis * Set the real uid and transfer proc count to new user. 482a08f4bf6SPeter Wemm */ 483b1fc0ec1SRobert Watson if (uid != oldcred->cr_ruid) { 484b1fc0ec1SRobert Watson change_ruid(newcred, uid); 485f535380cSDon Lewis setsugid(p); 486d3cdb93dSAndrey A. Chernov } 487a08f4bf6SPeter Wemm /* 488a08f4bf6SPeter Wemm * Set saved uid 489a08f4bf6SPeter Wemm * 490a08f4bf6SPeter Wemm * XXX always set saved uid even if not _POSIX_SAVED_IDS, as 491a08f4bf6SPeter Wemm * the security of seteuid() depends on it. B.4.2.2 says it 492a08f4bf6SPeter Wemm * is important that we should do this. 493a08f4bf6SPeter Wemm */ 494b1fc0ec1SRobert Watson if (uid != oldcred->cr_svuid) { 495b1fc0ec1SRobert Watson change_svuid(newcred, uid); 496d5f81602SSean Eric Fagan setsugid(p); 497a08f4bf6SPeter Wemm } 498a08f4bf6SPeter Wemm } 499a08f4bf6SPeter Wemm 500a08f4bf6SPeter Wemm /* 501a08f4bf6SPeter Wemm * In all permitted cases, we are changing the euid. 502a08f4bf6SPeter Wemm * Copy credentials so other references do not see our changes. 503a08f4bf6SPeter Wemm */ 504b1fc0ec1SRobert Watson if (uid != oldcred->cr_uid) { 505b1fc0ec1SRobert Watson change_euid(newcred, uid); 506d5f81602SSean Eric Fagan setsugid(p); 507a08f4bf6SPeter Wemm } 508b1fc0ec1SRobert Watson p->p_ucred = newcred; 509b1fc0ec1SRobert Watson crfree(oldcred); 510df8bae1dSRodney W. Grimes return (0); 511df8bae1dSRodney W. Grimes } 512df8bae1dSRodney W. Grimes 513d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 514df8bae1dSRodney W. Grimes struct seteuid_args { 515df8bae1dSRodney W. Grimes uid_t euid; 516df8bae1dSRodney W. Grimes }; 517d2d3e875SBruce Evans #endif 518df8bae1dSRodney W. Grimes /* ARGSUSED */ 51926f9a767SRodney W. Grimes int 520cb226aaaSPoul-Henning Kamp seteuid(p, uap) 521df8bae1dSRodney W. Grimes struct proc *p; 522df8bae1dSRodney W. Grimes struct seteuid_args *uap; 523df8bae1dSRodney W. Grimes { 524b1fc0ec1SRobert Watson struct ucred *newcred, *oldcred; 525b1fc0ec1SRobert Watson uid_t euid; 526df8bae1dSRodney W. Grimes int error; 527df8bae1dSRodney W. Grimes 528df8bae1dSRodney W. Grimes euid = uap->euid; 529b1fc0ec1SRobert Watson oldcred = p->p_ucred; 530b1fc0ec1SRobert Watson if (euid != oldcred->cr_ruid && /* allow seteuid(getuid()) */ 531b1fc0ec1SRobert Watson euid != oldcred->cr_svuid && /* allow seteuid(saved uid) */ 532b1fc0ec1SRobert Watson (error = suser_xxx(oldcred, NULL, PRISON_ROOT))) 533df8bae1dSRodney W. Grimes return (error); 534df8bae1dSRodney W. Grimes /* 535df8bae1dSRodney W. Grimes * Everything's okay, do it. Copy credentials so other references do 536df8bae1dSRodney W. Grimes * not see our changes. 537df8bae1dSRodney W. Grimes */ 538b1fc0ec1SRobert Watson newcred = crdup(oldcred); 539b1fc0ec1SRobert Watson if (oldcred->cr_uid != euid) { 540b1fc0ec1SRobert Watson change_euid(newcred, euid); 541d5f81602SSean Eric Fagan setsugid(p); 542229a15f0SPeter Wemm } 543b1fc0ec1SRobert Watson p->p_ucred = newcred; 544b1fc0ec1SRobert Watson crfree(oldcred); 545df8bae1dSRodney W. Grimes return (0); 546df8bae1dSRodney W. Grimes } 547df8bae1dSRodney W. Grimes 548d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 549df8bae1dSRodney W. Grimes struct setgid_args { 550df8bae1dSRodney W. Grimes gid_t gid; 551df8bae1dSRodney W. Grimes }; 552d2d3e875SBruce Evans #endif 553df8bae1dSRodney W. Grimes /* ARGSUSED */ 55426f9a767SRodney W. Grimes int 555cb226aaaSPoul-Henning Kamp setgid(p, uap) 556df8bae1dSRodney W. Grimes struct proc *p; 557df8bae1dSRodney W. Grimes struct setgid_args *uap; 558df8bae1dSRodney W. Grimes { 559b1fc0ec1SRobert Watson struct ucred *newcred, *oldcred; 560b1fc0ec1SRobert Watson gid_t gid; 561df8bae1dSRodney W. Grimes int error; 562df8bae1dSRodney W. Grimes 563b1fc0ec1SRobert Watson gid = uap->gid; 564b1fc0ec1SRobert Watson oldcred = p->p_ucred; 565a08f4bf6SPeter Wemm /* 566a08f4bf6SPeter Wemm * See if we have "permission" by POSIX 1003.1 rules. 567a08f4bf6SPeter Wemm * 568a08f4bf6SPeter Wemm * Note that setgid(getegid()) is a special case of 569a08f4bf6SPeter Wemm * "appropriate privileges" in appendix B.4.2.2. We need 5702fa72ea7SJeroen Ruigrok van der Werven * to use this clause to be compatible with traditional BSD 571a08f4bf6SPeter Wemm * semantics. Basically, it means that "setgid(xx)" sets all 572a08f4bf6SPeter Wemm * three id's (assuming you have privs). 573a08f4bf6SPeter Wemm * 574a08f4bf6SPeter Wemm * For notes on the logic here, see setuid() above. 575a08f4bf6SPeter Wemm */ 576b1fc0ec1SRobert Watson if (gid != oldcred->cr_rgid && /* allow setgid(getgid()) */ 5773f246666SAndrey A. Chernov #ifdef _POSIX_SAVED_IDS 578b1fc0ec1SRobert Watson gid != oldcred->cr_svgid && /* allow setgid(saved gid) */ 579a08f4bf6SPeter Wemm #endif 580a08f4bf6SPeter Wemm #ifdef POSIX_APPENDIX_B_4_2_2 /* Use BSD-compat clause from B.4.2.2 */ 581b1fc0ec1SRobert Watson gid != oldcred->cr_groups[0] && /* allow setgid(getegid()) */ 5823f246666SAndrey A. Chernov #endif 583b1fc0ec1SRobert Watson (error = suser_xxx(oldcred, NULL, PRISON_ROOT))) 584df8bae1dSRodney W. Grimes return (error); 585a08f4bf6SPeter Wemm 586b1fc0ec1SRobert Watson newcred = crdup(oldcred); 587a08f4bf6SPeter Wemm #ifdef _POSIX_SAVED_IDS 588a08f4bf6SPeter Wemm /* 589a08f4bf6SPeter Wemm * Do we have "appropriate privileges" (are we root or gid == egid) 590a08f4bf6SPeter Wemm * If so, we are changing the real uid and saved gid. 591a08f4bf6SPeter Wemm */ 592a08f4bf6SPeter Wemm if ( 593a08f4bf6SPeter Wemm #ifdef POSIX_APPENDIX_B_4_2_2 /* use the clause from B.4.2.2 */ 594b1fc0ec1SRobert Watson gid == oldcred->cr_groups[0] || 595a08f4bf6SPeter Wemm #endif 596b1fc0ec1SRobert Watson suser_xxx(oldcred, NULL, PRISON_ROOT) == 0) /* we are using privs */ 597a08f4bf6SPeter Wemm #endif 598a08f4bf6SPeter Wemm { 599a08f4bf6SPeter Wemm /* 600a08f4bf6SPeter Wemm * Set real gid 601a08f4bf6SPeter Wemm */ 602b1fc0ec1SRobert Watson if (oldcred->cr_rgid != gid) { 603b1fc0ec1SRobert Watson change_rgid(newcred, gid); 604d5f81602SSean Eric Fagan setsugid(p); 605a08f4bf6SPeter Wemm } 606a08f4bf6SPeter Wemm /* 607a08f4bf6SPeter Wemm * Set saved gid 608a08f4bf6SPeter Wemm * 609a08f4bf6SPeter Wemm * XXX always set saved gid even if not _POSIX_SAVED_IDS, as 610a08f4bf6SPeter Wemm * the security of setegid() depends on it. B.4.2.2 says it 611a08f4bf6SPeter Wemm * is important that we should do this. 612a08f4bf6SPeter Wemm */ 613b1fc0ec1SRobert Watson if (oldcred->cr_svgid != gid) { 614b1fc0ec1SRobert Watson change_svgid(newcred, gid); 615d5f81602SSean Eric Fagan setsugid(p); 616a08f4bf6SPeter Wemm } 617a08f4bf6SPeter Wemm } 618a08f4bf6SPeter Wemm /* 619a08f4bf6SPeter Wemm * In all cases permitted cases, we are changing the egid. 620a08f4bf6SPeter Wemm * Copy credentials so other references do not see our changes. 621a08f4bf6SPeter Wemm */ 622b1fc0ec1SRobert Watson if (oldcred->cr_groups[0] != gid) { 623b1fc0ec1SRobert Watson change_egid(newcred, gid); 624d5f81602SSean Eric Fagan setsugid(p); 625a08f4bf6SPeter Wemm } 626b1fc0ec1SRobert Watson p->p_ucred = newcred; 627b1fc0ec1SRobert Watson crfree(oldcred); 628df8bae1dSRodney W. Grimes return (0); 629df8bae1dSRodney W. Grimes } 630df8bae1dSRodney W. Grimes 631d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 632df8bae1dSRodney W. Grimes struct setegid_args { 633df8bae1dSRodney W. Grimes gid_t egid; 634df8bae1dSRodney W. Grimes }; 635d2d3e875SBruce Evans #endif 636df8bae1dSRodney W. Grimes /* ARGSUSED */ 63726f9a767SRodney W. Grimes int 638cb226aaaSPoul-Henning Kamp setegid(p, uap) 639df8bae1dSRodney W. Grimes struct proc *p; 640df8bae1dSRodney W. Grimes struct setegid_args *uap; 641df8bae1dSRodney W. Grimes { 642b1fc0ec1SRobert Watson struct ucred *newcred, *oldcred; 643b1fc0ec1SRobert Watson gid_t egid; 644df8bae1dSRodney W. Grimes int error; 645df8bae1dSRodney W. Grimes 646df8bae1dSRodney W. Grimes egid = uap->egid; 647b1fc0ec1SRobert Watson oldcred = p->p_ucred; 648b1fc0ec1SRobert Watson if (egid != oldcred->cr_rgid && /* allow setegid(getgid()) */ 649b1fc0ec1SRobert Watson egid != oldcred->cr_svgid && /* allow setegid(saved gid) */ 650b1fc0ec1SRobert Watson (error = suser_xxx(oldcred, NULL, PRISON_ROOT))) 651df8bae1dSRodney W. Grimes return (error); 652b1fc0ec1SRobert Watson newcred = crdup(oldcred); 653b1fc0ec1SRobert Watson if (oldcred->cr_groups[0] != egid) { 654b1fc0ec1SRobert Watson change_egid(newcred, egid); 655d5f81602SSean Eric Fagan setsugid(p); 656229a15f0SPeter Wemm } 657b1fc0ec1SRobert Watson p->p_ucred = newcred; 658b1fc0ec1SRobert Watson crfree(oldcred); 659df8bae1dSRodney W. Grimes return (0); 660df8bae1dSRodney W. Grimes } 661df8bae1dSRodney W. Grimes 662d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 663df8bae1dSRodney W. Grimes struct setgroups_args { 664df8bae1dSRodney W. Grimes u_int gidsetsize; 665df8bae1dSRodney W. Grimes gid_t *gidset; 666df8bae1dSRodney W. Grimes }; 667d2d3e875SBruce Evans #endif 668df8bae1dSRodney W. Grimes /* ARGSUSED */ 66926f9a767SRodney W. Grimes int 670cb226aaaSPoul-Henning Kamp setgroups(p, uap) 671df8bae1dSRodney W. Grimes struct proc *p; 672df8bae1dSRodney W. Grimes struct setgroups_args *uap; 673df8bae1dSRodney W. Grimes { 674b1fc0ec1SRobert Watson struct ucred *newcred, *oldcred; 675b1fc0ec1SRobert Watson u_int ngrp; 676df8bae1dSRodney W. Grimes int error; 677df8bae1dSRodney W. Grimes 6783956a170SDavid Greenman ngrp = uap->gidsetsize; 679b1fc0ec1SRobert Watson oldcred = p->p_ucred; 680b1fc0ec1SRobert Watson if ((error = suser_xxx(oldcred, NULL, PRISON_ROOT))) 681b1fc0ec1SRobert Watson return (error); 6828a5d815aSPeter Wemm if (ngrp > NGROUPS) 683df8bae1dSRodney W. Grimes return (EINVAL); 6848a5d815aSPeter Wemm /* 6858a5d815aSPeter Wemm * XXX A little bit lazy here. We could test if anything has 6868a5d815aSPeter Wemm * changed before crcopy() and setting P_SUGID. 6878a5d815aSPeter Wemm */ 688b1fc0ec1SRobert Watson newcred = crdup(oldcred); 6898a5d815aSPeter Wemm if (ngrp < 1) { 6908a5d815aSPeter Wemm /* 6918a5d815aSPeter Wemm * setgroups(0, NULL) is a legitimate way of clearing the 6928a5d815aSPeter Wemm * groups vector on non-BSD systems (which generally do not 6938a5d815aSPeter Wemm * have the egid in the groups[0]). We risk security holes 6948a5d815aSPeter Wemm * when running non-BSD software if we do not do the same. 6958a5d815aSPeter Wemm */ 696b1fc0ec1SRobert Watson newcred->cr_ngroups = 1; 6978a5d815aSPeter Wemm } else { 698bb56ec4aSPoul-Henning Kamp if ((error = copyin((caddr_t)uap->gidset, 699b1fc0ec1SRobert Watson (caddr_t)newcred->cr_groups, ngrp * sizeof(gid_t)))) { 700b1fc0ec1SRobert Watson crfree(newcred); 701df8bae1dSRodney W. Grimes return (error); 702b1fc0ec1SRobert Watson } 703b1fc0ec1SRobert Watson newcred->cr_ngroups = ngrp; 7048a5d815aSPeter Wemm } 705d5f81602SSean Eric Fagan setsugid(p); 706b1fc0ec1SRobert Watson p->p_ucred = newcred; 707b1fc0ec1SRobert Watson crfree(oldcred); 708df8bae1dSRodney W. Grimes return (0); 709df8bae1dSRodney W. Grimes } 710df8bae1dSRodney W. Grimes 711d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 712df8bae1dSRodney W. Grimes struct setreuid_args { 71300999cd6SAndrey A. Chernov uid_t ruid; 71400999cd6SAndrey A. Chernov uid_t euid; 715df8bae1dSRodney W. Grimes }; 716d2d3e875SBruce Evans #endif 717df8bae1dSRodney W. Grimes /* ARGSUSED */ 71826f9a767SRodney W. Grimes int 719cb226aaaSPoul-Henning Kamp setreuid(p, uap) 720df8bae1dSRodney W. Grimes register struct proc *p; 721df8bae1dSRodney W. Grimes struct setreuid_args *uap; 722df8bae1dSRodney W. Grimes { 723b1fc0ec1SRobert Watson struct ucred *newcred, *oldcred; 724b1fc0ec1SRobert Watson uid_t ruid, euid; 725611d721eSAndrey A. Chernov int error; 726df8bae1dSRodney W. Grimes 72700999cd6SAndrey A. Chernov ruid = uap->ruid; 72800999cd6SAndrey A. Chernov euid = uap->euid; 729b1fc0ec1SRobert Watson oldcred = p->p_ucred; 730b1fc0ec1SRobert Watson if (((ruid != (uid_t)-1 && ruid != oldcred->cr_ruid && 731b1fc0ec1SRobert Watson ruid != oldcred->cr_svuid) || 732b1fc0ec1SRobert Watson (euid != (uid_t)-1 && euid != oldcred->cr_uid && 733b1fc0ec1SRobert Watson euid != oldcred->cr_ruid && euid != oldcred->cr_svuid)) && 734b1fc0ec1SRobert Watson (error = suser_xxx(oldcred, NULL, PRISON_ROOT)) != 0) 735611d721eSAndrey A. Chernov return (error); 736b1fc0ec1SRobert Watson newcred = crdup(oldcred); 737b1fc0ec1SRobert Watson if (euid != (uid_t)-1 && oldcred->cr_uid != euid) { 738b1fc0ec1SRobert Watson change_euid(newcred, euid); 739d5f81602SSean Eric Fagan setsugid(p); 740a89a5370SPeter Wemm } 741b1fc0ec1SRobert Watson if (ruid != (uid_t)-1 && oldcred->cr_ruid != ruid) { 742b1fc0ec1SRobert Watson change_ruid(newcred, ruid); 743d5f81602SSean Eric Fagan setsugid(p); 74400999cd6SAndrey A. Chernov } 745b1fc0ec1SRobert Watson if ((ruid != (uid_t)-1 || newcred->cr_uid != newcred->cr_ruid) && 746b1fc0ec1SRobert Watson newcred->cr_svuid != newcred->cr_uid) { 747b1fc0ec1SRobert Watson change_svuid(newcred, newcred->cr_uid); 748d5f81602SSean Eric Fagan setsugid(p); 749a89a5370SPeter Wemm } 750b1fc0ec1SRobert Watson p->p_ucred = newcred; 751b1fc0ec1SRobert Watson crfree(oldcred); 752611d721eSAndrey A. Chernov return (0); 753df8bae1dSRodney W. Grimes } 754df8bae1dSRodney W. Grimes 755d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 756df8bae1dSRodney W. Grimes struct setregid_args { 75700999cd6SAndrey A. Chernov gid_t rgid; 75800999cd6SAndrey A. Chernov gid_t egid; 759df8bae1dSRodney W. Grimes }; 760d2d3e875SBruce Evans #endif 761df8bae1dSRodney W. Grimes /* ARGSUSED */ 76226f9a767SRodney W. Grimes int 763cb226aaaSPoul-Henning Kamp setregid(p, uap) 764df8bae1dSRodney W. Grimes register struct proc *p; 765df8bae1dSRodney W. Grimes struct setregid_args *uap; 766df8bae1dSRodney W. Grimes { 767b1fc0ec1SRobert Watson struct ucred *newcred, *oldcred; 768b1fc0ec1SRobert Watson gid_t rgid, egid; 769611d721eSAndrey A. Chernov int error; 770df8bae1dSRodney W. Grimes 77100999cd6SAndrey A. Chernov rgid = uap->rgid; 77200999cd6SAndrey A. Chernov egid = uap->egid; 773b1fc0ec1SRobert Watson oldcred = p->p_ucred; 774b1fc0ec1SRobert Watson if (((rgid != (gid_t)-1 && rgid != oldcred->cr_rgid && 775b1fc0ec1SRobert Watson rgid != oldcred->cr_svgid) || 776b1fc0ec1SRobert Watson (egid != (gid_t)-1 && egid != oldcred->cr_groups[0] && 777b1fc0ec1SRobert Watson egid != oldcred->cr_rgid && egid != oldcred->cr_svgid)) && 778b1fc0ec1SRobert Watson (error = suser_xxx(oldcred, NULL, PRISON_ROOT)) != 0) 779611d721eSAndrey A. Chernov return (error); 78000999cd6SAndrey A. Chernov 781b1fc0ec1SRobert Watson newcred = crdup(oldcred); 782b1fc0ec1SRobert Watson if (egid != (gid_t)-1 && oldcred->cr_groups[0] != egid) { 783b1fc0ec1SRobert Watson change_egid(newcred, egid); 784d5f81602SSean Eric Fagan setsugid(p); 785a89a5370SPeter Wemm } 786b1fc0ec1SRobert Watson if (rgid != (gid_t)-1 && oldcred->cr_rgid != rgid) { 787b1fc0ec1SRobert Watson change_rgid(newcred, rgid); 788d5f81602SSean Eric Fagan setsugid(p); 789a89a5370SPeter Wemm } 790b1fc0ec1SRobert Watson if ((rgid != (gid_t)-1 || newcred->cr_groups[0] != newcred->cr_rgid) && 791b1fc0ec1SRobert Watson newcred->cr_svgid != newcred->cr_groups[0]) { 792b1fc0ec1SRobert Watson change_svgid(newcred, newcred->cr_groups[0]); 793d5f81602SSean Eric Fagan setsugid(p); 794a89a5370SPeter Wemm } 7954589be70SRuslan Ermilov p->p_ucred = newcred; 7964589be70SRuslan Ermilov crfree(oldcred); 797611d721eSAndrey A. Chernov return (0); 798df8bae1dSRodney W. Grimes } 799df8bae1dSRodney W. Grimes 8008ccd6334SPeter Wemm /* 8018ccd6334SPeter Wemm * setresuid(ruid, euid, suid) is like setreuid except control over the 8028ccd6334SPeter Wemm * saved uid is explicit. 8038ccd6334SPeter Wemm */ 8048ccd6334SPeter Wemm 8058ccd6334SPeter Wemm #ifndef _SYS_SYSPROTO_H_ 8068ccd6334SPeter Wemm struct setresuid_args { 8078ccd6334SPeter Wemm uid_t ruid; 8088ccd6334SPeter Wemm uid_t euid; 8098ccd6334SPeter Wemm uid_t suid; 8108ccd6334SPeter Wemm }; 8118ccd6334SPeter Wemm #endif 8128ccd6334SPeter Wemm /* ARGSUSED */ 8138ccd6334SPeter Wemm int 8148ccd6334SPeter Wemm setresuid(p, uap) 8158ccd6334SPeter Wemm register struct proc *p; 8168ccd6334SPeter Wemm struct setresuid_args *uap; 8178ccd6334SPeter Wemm { 818b1fc0ec1SRobert Watson struct ucred *newcred, *oldcred; 819b1fc0ec1SRobert Watson uid_t ruid, euid, suid; 8208ccd6334SPeter Wemm int error; 8218ccd6334SPeter Wemm 8228ccd6334SPeter Wemm ruid = uap->ruid; 8238ccd6334SPeter Wemm euid = uap->euid; 8248ccd6334SPeter Wemm suid = uap->suid; 825b1fc0ec1SRobert Watson oldcred = p->p_ucred; 826b1fc0ec1SRobert Watson if (((ruid != (uid_t)-1 && ruid != oldcred->cr_ruid && 827b1fc0ec1SRobert Watson ruid != oldcred->cr_svuid && 828b1fc0ec1SRobert Watson ruid != oldcred->cr_uid) || 829b1fc0ec1SRobert Watson (euid != (uid_t)-1 && euid != oldcred->cr_ruid && 830b1fc0ec1SRobert Watson euid != oldcred->cr_svuid && 831b1fc0ec1SRobert Watson euid != oldcred->cr_uid) || 832b1fc0ec1SRobert Watson (suid != (uid_t)-1 && suid != oldcred->cr_ruid && 833b1fc0ec1SRobert Watson suid != oldcred->cr_svuid && 834b1fc0ec1SRobert Watson suid != oldcred->cr_uid)) && 835b1fc0ec1SRobert Watson (error = suser_xxx(oldcred, NULL, PRISON_ROOT)) != 0) 8368ccd6334SPeter Wemm return (error); 837b1fc0ec1SRobert Watson 838b1fc0ec1SRobert Watson newcred = crdup(oldcred); 839b1fc0ec1SRobert Watson if (euid != (uid_t)-1 && oldcred->cr_uid != euid) { 840b1fc0ec1SRobert Watson change_euid(newcred, euid); 8418ccd6334SPeter Wemm setsugid(p); 8428ccd6334SPeter Wemm } 843b1fc0ec1SRobert Watson if (ruid != (uid_t)-1 && oldcred->cr_ruid != ruid) { 844b1fc0ec1SRobert Watson change_ruid(newcred, ruid); 8458ccd6334SPeter Wemm setsugid(p); 8468ccd6334SPeter Wemm } 847b1fc0ec1SRobert Watson if (suid != (uid_t)-1 && oldcred->cr_svuid != suid) { 848b1fc0ec1SRobert Watson change_svuid(newcred, suid); 8498ccd6334SPeter Wemm setsugid(p); 8508ccd6334SPeter Wemm } 851b1fc0ec1SRobert Watson p->p_ucred = newcred; 852b1fc0ec1SRobert Watson crfree(oldcred); 8538ccd6334SPeter Wemm return (0); 8548ccd6334SPeter Wemm } 8558ccd6334SPeter Wemm 8568ccd6334SPeter Wemm /* 8578ccd6334SPeter Wemm * setresgid(rgid, egid, sgid) is like setregid except control over the 8588ccd6334SPeter Wemm * saved gid is explicit. 8598ccd6334SPeter Wemm */ 8608ccd6334SPeter Wemm 8618ccd6334SPeter Wemm #ifndef _SYS_SYSPROTO_H_ 8628ccd6334SPeter Wemm struct setresgid_args { 8638ccd6334SPeter Wemm gid_t rgid; 8648ccd6334SPeter Wemm gid_t egid; 8658ccd6334SPeter Wemm gid_t sgid; 8668ccd6334SPeter Wemm }; 8678ccd6334SPeter Wemm #endif 8688ccd6334SPeter Wemm /* ARGSUSED */ 8698ccd6334SPeter Wemm int 8708ccd6334SPeter Wemm setresgid(p, uap) 8718ccd6334SPeter Wemm register struct proc *p; 8728ccd6334SPeter Wemm struct setresgid_args *uap; 8738ccd6334SPeter Wemm { 874b1fc0ec1SRobert Watson struct ucred *newcred, *oldcred; 875b1fc0ec1SRobert Watson gid_t rgid, egid, sgid; 8768ccd6334SPeter Wemm int error; 8778ccd6334SPeter Wemm 8788ccd6334SPeter Wemm rgid = uap->rgid; 8798ccd6334SPeter Wemm egid = uap->egid; 8808ccd6334SPeter Wemm sgid = uap->sgid; 881b1fc0ec1SRobert Watson oldcred = p->p_ucred; 882b1fc0ec1SRobert Watson if (((rgid != (gid_t)-1 && rgid != oldcred->cr_rgid && 883b1fc0ec1SRobert Watson rgid != oldcred->cr_svgid && 884b1fc0ec1SRobert Watson rgid != oldcred->cr_groups[0]) || 885b1fc0ec1SRobert Watson (egid != (gid_t)-1 && egid != oldcred->cr_rgid && 886b1fc0ec1SRobert Watson egid != oldcred->cr_svgid && 887b1fc0ec1SRobert Watson egid != oldcred->cr_groups[0]) || 888b1fc0ec1SRobert Watson (sgid != (gid_t)-1 && sgid != oldcred->cr_rgid && 889b1fc0ec1SRobert Watson sgid != oldcred->cr_svgid && 890b1fc0ec1SRobert Watson sgid != oldcred->cr_groups[0])) && 891b1fc0ec1SRobert Watson (error = suser_xxx(oldcred, NULL, PRISON_ROOT)) != 0) 8928ccd6334SPeter Wemm return (error); 8938ccd6334SPeter Wemm 894b1fc0ec1SRobert Watson newcred = crdup(oldcred); 895b1fc0ec1SRobert Watson if (egid != (gid_t)-1 && oldcred->cr_groups[0] != egid) { 896b1fc0ec1SRobert Watson change_egid(newcred, egid); 8978ccd6334SPeter Wemm setsugid(p); 8988ccd6334SPeter Wemm } 899b1fc0ec1SRobert Watson if (rgid != (gid_t)-1 && oldcred->cr_rgid != rgid) { 900b1fc0ec1SRobert Watson change_rgid(newcred, rgid); 9018ccd6334SPeter Wemm setsugid(p); 9028ccd6334SPeter Wemm } 903b1fc0ec1SRobert Watson if (sgid != (gid_t)-1 && oldcred->cr_svgid != sgid) { 904b1fc0ec1SRobert Watson change_svgid(newcred, sgid); 9058ccd6334SPeter Wemm setsugid(p); 9068ccd6334SPeter Wemm } 907b1fc0ec1SRobert Watson p->p_ucred = newcred; 908b1fc0ec1SRobert Watson crfree(oldcred); 9098ccd6334SPeter Wemm return (0); 9108ccd6334SPeter Wemm } 9118ccd6334SPeter Wemm 9128ccd6334SPeter Wemm #ifndef _SYS_SYSPROTO_H_ 9138ccd6334SPeter Wemm struct getresuid_args { 9148ccd6334SPeter Wemm uid_t *ruid; 9158ccd6334SPeter Wemm uid_t *euid; 9168ccd6334SPeter Wemm uid_t *suid; 9178ccd6334SPeter Wemm }; 9188ccd6334SPeter Wemm #endif 9198ccd6334SPeter Wemm /* ARGSUSED */ 9208ccd6334SPeter Wemm int 9218ccd6334SPeter Wemm getresuid(p, uap) 9228ccd6334SPeter Wemm register struct proc *p; 9238ccd6334SPeter Wemm struct getresuid_args *uap; 9248ccd6334SPeter Wemm { 925b1fc0ec1SRobert Watson struct ucred *cred = p->p_ucred; 9268ccd6334SPeter Wemm int error1 = 0, error2 = 0, error3 = 0; 9278ccd6334SPeter Wemm 9288ccd6334SPeter Wemm if (uap->ruid) 929b1fc0ec1SRobert Watson error1 = copyout((caddr_t)&cred->cr_ruid, 930b1fc0ec1SRobert Watson (caddr_t)uap->ruid, sizeof(cred->cr_ruid)); 9318ccd6334SPeter Wemm if (uap->euid) 932b1fc0ec1SRobert Watson error2 = copyout((caddr_t)&cred->cr_uid, 933b1fc0ec1SRobert Watson (caddr_t)uap->euid, sizeof(cred->cr_uid)); 9348ccd6334SPeter Wemm if (uap->suid) 935b1fc0ec1SRobert Watson error3 = copyout((caddr_t)&cred->cr_svuid, 936b1fc0ec1SRobert Watson (caddr_t)uap->suid, sizeof(cred->cr_svuid)); 9378ccd6334SPeter Wemm return error1 ? error1 : (error2 ? error2 : error3); 9388ccd6334SPeter Wemm } 9398ccd6334SPeter Wemm 9408ccd6334SPeter Wemm #ifndef _SYS_SYSPROTO_H_ 9418ccd6334SPeter Wemm struct getresgid_args { 9428ccd6334SPeter Wemm gid_t *rgid; 9438ccd6334SPeter Wemm gid_t *egid; 9448ccd6334SPeter Wemm gid_t *sgid; 9458ccd6334SPeter Wemm }; 9468ccd6334SPeter Wemm #endif 9478ccd6334SPeter Wemm /* ARGSUSED */ 9488ccd6334SPeter Wemm int 9498ccd6334SPeter Wemm getresgid(p, uap) 9508ccd6334SPeter Wemm register struct proc *p; 9518ccd6334SPeter Wemm struct getresgid_args *uap; 9528ccd6334SPeter Wemm { 953b1fc0ec1SRobert Watson struct ucred *cred = p->p_ucred; 9548ccd6334SPeter Wemm int error1 = 0, error2 = 0, error3 = 0; 9558ccd6334SPeter Wemm 9568ccd6334SPeter Wemm if (uap->rgid) 957b1fc0ec1SRobert Watson error1 = copyout((caddr_t)&cred->cr_rgid, 958b1fc0ec1SRobert Watson (caddr_t)uap->rgid, sizeof(cred->cr_rgid)); 9598ccd6334SPeter Wemm if (uap->egid) 960b1fc0ec1SRobert Watson error2 = copyout((caddr_t)&cred->cr_groups[0], 961b1fc0ec1SRobert Watson (caddr_t)uap->egid, sizeof(cred->cr_groups[0])); 9628ccd6334SPeter Wemm if (uap->sgid) 963b1fc0ec1SRobert Watson error3 = copyout((caddr_t)&cred->cr_svgid, 964b1fc0ec1SRobert Watson (caddr_t)uap->sgid, sizeof(cred->cr_svgid)); 9658ccd6334SPeter Wemm return error1 ? error1 : (error2 ? error2 : error3); 9668ccd6334SPeter Wemm } 9678ccd6334SPeter Wemm 9688ccd6334SPeter Wemm 969b67cbc65SPeter Wemm #ifndef _SYS_SYSPROTO_H_ 970b67cbc65SPeter Wemm struct issetugid_args { 971b67cbc65SPeter Wemm int dummy; 972b67cbc65SPeter Wemm }; 973b67cbc65SPeter Wemm #endif 974b67cbc65SPeter Wemm /* ARGSUSED */ 975b67cbc65SPeter Wemm int 976cb226aaaSPoul-Henning Kamp issetugid(p, uap) 977b67cbc65SPeter Wemm register struct proc *p; 978b67cbc65SPeter Wemm struct issetugid_args *uap; 979b67cbc65SPeter Wemm { 980b67cbc65SPeter Wemm /* 981b67cbc65SPeter Wemm * Note: OpenBSD sets a P_SUGIDEXEC flag set at execve() time, 982b67cbc65SPeter Wemm * we use P_SUGID because we consider changing the owners as 983b67cbc65SPeter Wemm * "tainting" as well. 984b67cbc65SPeter Wemm * This is significant for procs that start as root and "become" 985b67cbc65SPeter Wemm * a user without an exec - programs cannot know *everything* 986b67cbc65SPeter Wemm * that libc *might* have put in their data segment. 987b67cbc65SPeter Wemm */ 9880e59fec6SPeter Wemm p->p_retval[0] = (p->p_flag & P_SUGID) ? 1 : 0; 989b67cbc65SPeter Wemm return (0); 990b67cbc65SPeter Wemm } 991b67cbc65SPeter Wemm 992130d0157SRobert Watson int 993130d0157SRobert Watson __setugid(p, uap) 994130d0157SRobert Watson struct proc *p; 995130d0157SRobert Watson struct __setugid_args *uap; 996130d0157SRobert Watson { 997130d0157SRobert Watson 998130d0157SRobert Watson #ifdef REGRESSION 999130d0157SRobert Watson switch (uap->flag) { 1000130d0157SRobert Watson case 0: 1001130d0157SRobert Watson p->p_flag &= ~P_SUGID; 1002130d0157SRobert Watson return (0); 1003130d0157SRobert Watson case 1: 1004130d0157SRobert Watson p->p_flag |= P_SUGID; 1005130d0157SRobert Watson return (0); 1006130d0157SRobert Watson default: 1007130d0157SRobert Watson return (EINVAL); 1008130d0157SRobert Watson } 1009130d0157SRobert Watson #else /* !REGRESSION */ 1010130d0157SRobert Watson return (ENOSYS); 1011130d0157SRobert Watson #endif /* !REGRESSION */ 1012130d0157SRobert Watson } 1013130d0157SRobert Watson 1014df8bae1dSRodney W. Grimes /* 1015df8bae1dSRodney W. Grimes * Check if gid is a member of the group set. 1016df8bae1dSRodney W. Grimes */ 101726f9a767SRodney W. Grimes int 1018df8bae1dSRodney W. Grimes groupmember(gid, cred) 1019df8bae1dSRodney W. Grimes gid_t gid; 1020b1fc0ec1SRobert Watson struct ucred *cred; 1021df8bae1dSRodney W. Grimes { 1022df8bae1dSRodney W. Grimes register gid_t *gp; 1023df8bae1dSRodney W. Grimes gid_t *egp; 1024df8bae1dSRodney W. Grimes 1025df8bae1dSRodney W. Grimes egp = &(cred->cr_groups[cred->cr_ngroups]); 1026df8bae1dSRodney W. Grimes for (gp = cred->cr_groups; gp < egp; gp++) 1027df8bae1dSRodney W. Grimes if (*gp == gid) 1028df8bae1dSRodney W. Grimes return (1); 1029df8bae1dSRodney W. Grimes return (0); 1030df8bae1dSRodney W. Grimes } 1031df8bae1dSRodney W. Grimes 10323b243b72SRobert Watson /* 10333b243b72SRobert Watson * The suser_permitted MIB entry allows the determination of whether or 10343b243b72SRobert Watson * not the system 'super-user' policy is in effect. If true, an effective 10353b243b72SRobert Watson * uid of 0 connotes special privilege, overriding many mandatory and 10363b243b72SRobert Watson * discretionary system protections. If false, uid 0 is offered no 10373b243b72SRobert Watson * special privilege in the kernel security policy. Setting this value 10383b243b72SRobert Watson * to 0 may seriously impact the functionality of many existing userland 10393b243b72SRobert Watson * programs, and should not be changed without careful consideration of 10403b243b72SRobert Watson * the consequences. 10413b243b72SRobert Watson */ 1042579f4eb4SRobert Watson static int suser_permitted = 1; 10430ef5652eSRobert Watson SYSCTL_INT(_kern_security, OID_AUTO, suser_permitted, CTLFLAG_RW, 10440ef5652eSRobert Watson &suser_permitted, 0, "processes with uid 0 have privilege"); 1045579f4eb4SRobert Watson 1046df8bae1dSRodney W. Grimes /* 1047df8bae1dSRodney W. Grimes * Test whether the specified credentials imply "super-user" 10483b243b72SRobert Watson * privilege. 10493b243b72SRobert Watson * 1050df8bae1dSRodney W. Grimes * Returns 0 or error. 1051df8bae1dSRodney W. Grimes */ 105226f9a767SRodney W. Grimes int 1053f711d546SPoul-Henning Kamp suser(p) 105491421ba2SRobert Watson struct proc *p; 1055f711d546SPoul-Henning Kamp { 105675c13541SPoul-Henning Kamp return suser_xxx(0, p, 0); 1057f711d546SPoul-Henning Kamp } 1058f711d546SPoul-Henning Kamp 1059f711d546SPoul-Henning Kamp int 106075c13541SPoul-Henning Kamp suser_xxx(cred, proc, flag) 106191421ba2SRobert Watson struct ucred *cred; 106291421ba2SRobert Watson struct proc *proc; 106375c13541SPoul-Henning Kamp int flag; 1064df8bae1dSRodney W. Grimes { 106503095547SRobert Watson if (!suser_permitted) 106603095547SRobert Watson return (EPERM); 106775c13541SPoul-Henning Kamp if (!cred && !proc) { 106875c13541SPoul-Henning Kamp printf("suser_xxx(): THINK!\n"); 1069df8bae1dSRodney W. Grimes return (EPERM); 1070df8bae1dSRodney W. Grimes } 107175c13541SPoul-Henning Kamp if (!cred) 107275c13541SPoul-Henning Kamp cred = proc->p_ucred; 107375c13541SPoul-Henning Kamp if (cred->cr_uid != 0) 107475c13541SPoul-Henning Kamp return (EPERM); 107591421ba2SRobert Watson if (jailed(cred) && !(flag & PRISON_ROOT)) 107675c13541SPoul-Henning Kamp return (EPERM); 107775c13541SPoul-Henning Kamp return (0); 107875c13541SPoul-Henning Kamp } 1079df8bae1dSRodney W. Grimes 1080ed639720SRobert Watson /* 1081ed639720SRobert Watson * u_cansee(u1, u2): determine if u1 "can see" the subject specified by u2 1082ed639720SRobert Watson * Arguments: imutable credentials u1, u2 1083ed639720SRobert Watson * Returns: 0 for permitted, an errno value otherwise 1084ed639720SRobert Watson * Locks: none 1085ed639720SRobert Watson * References: u1 and u2 must be valid for the lifetime of the call 1086ed639720SRobert Watson * u1 may equal u2, in which case only one reference is required 1087ed639720SRobert Watson */ 1088ed639720SRobert Watson int 1089ed639720SRobert Watson u_cansee(struct ucred *u1, struct ucred *u2) 1090a9e0361bSPoul-Henning Kamp { 109191421ba2SRobert Watson int error; 1092a9e0361bSPoul-Henning Kamp 1093ed639720SRobert Watson if ((error = prison_check(u1, u2))) 109491421ba2SRobert Watson return (error); 1095b1fc0ec1SRobert Watson if (!ps_showallprocs && u1->cr_ruid != u2->cr_ruid) { 1096f8e6ab29SRobert Watson if (suser_xxx(u1, NULL, PRISON_ROOT) != 0) 1097387d2c03SRobert Watson return (ESRCH); 1098c52396e3SRobert Watson } 1099387d2c03SRobert Watson return (0); 1100387d2c03SRobert Watson } 1101387d2c03SRobert Watson 11023b243b72SRobert Watson /* 11033b243b72SRobert Watson * p_cansee(p1, p2): determine of p1 "can see" the subject specified by p2 11043b243b72SRobert Watson * Arguments: processes p1 and p2 11053b243b72SRobert Watson * Returns: 0 for permitted, an errno value otherwise 11063b243b72SRobert Watson * Locks: Sufficient locks to protection p1->p_ucred and p2->p_cured must 11073b243b72SRobert Watson * be held. Normally, p1 will be curproc, and a lock must be held 11083b243b72SRobert Watson * for p2. 11093b243b72SRobert Watson * References: p1 and p2 must be valid for the lifetime of the call 11103b243b72SRobert Watson */ 1111a0f75161SRobert Watson int 1112a0f75161SRobert Watson p_cansee(struct proc *p1, struct proc *p2) 1113ed639720SRobert Watson { 1114ed639720SRobert Watson 1115ed639720SRobert Watson /* Wrap u_cansee() for all functionality. */ 1116ed639720SRobert Watson return (u_cansee(p1->p_ucred, p2->p_ucred)); 1117ed639720SRobert Watson } 1118ed639720SRobert Watson 11194c5eb9c3SRobert Watson /* 11203b243b72SRobert Watson * p_cansignal(p1, p2, signum): determine whether p1 may deliver the 11213b243b72SRobert Watson * specified signal to p2 11223b243b72SRobert Watson * Arguments: processes p1 and p2, signal number 'signum' 11233b243b72SRobert Watson * Returns: 0 on success, an errno value otherwise 11243b243b72SRobert Watson * Locks: Sufficient locks to protect various components of p1 and p2 must 11253b243b72SRobert Watson * be held. Normally, p1 will be curproc, and a lock must be held 11263b243b72SRobert Watson * for p2. 11273b243b72SRobert Watson * References: p1 and p2 must be valid for the lifetime of the call 11284c5eb9c3SRobert Watson */ 11294c5eb9c3SRobert Watson int 11304c5eb9c3SRobert Watson p_cansignal(struct proc *p1, struct proc *p2, int signum) 1131387d2c03SRobert Watson { 113291421ba2SRobert Watson int error; 1133387d2c03SRobert Watson 1134a9e0361bSPoul-Henning Kamp if (p1 == p2) 1135a9e0361bSPoul-Henning Kamp return (0); 1136387d2c03SRobert Watson 11374c5eb9c3SRobert Watson /* 11384c5eb9c3SRobert Watson * Jail semantics limit the scope of signalling to p2 in the same 11394c5eb9c3SRobert Watson * jail as p1, if p1 is in jail. 11404c5eb9c3SRobert Watson */ 114191421ba2SRobert Watson if ((error = prison_check(p1->p_ucred, p2->p_ucred))) 114291421ba2SRobert Watson return (error); 1143387d2c03SRobert Watson 1144387d2c03SRobert Watson /* 11454c5eb9c3SRobert Watson * UNIX signalling semantics require that processes in the same 11464c5eb9c3SRobert Watson * session always be able to deliver SIGCONT to one another, 11474c5eb9c3SRobert Watson * overriding the remaining protections. 1148387d2c03SRobert Watson */ 11494c5eb9c3SRobert Watson if (signum == SIGCONT && p1->p_session == p2->p_session) 1150a9e0361bSPoul-Henning Kamp return (0); 1151387d2c03SRobert Watson 11524c5eb9c3SRobert Watson /* 11533b243b72SRobert Watson * UNIX signal semantics depend on the status of the P_SUGID 11543b243b72SRobert Watson * bit on the target process. If the bit is set, then additional 11553b243b72SRobert Watson * restrictions are placed on the set of available signals. 11564c5eb9c3SRobert Watson */ 11574c5eb9c3SRobert Watson if (p2->p_flag & P_SUGID) { 11584c5eb9c3SRobert Watson switch (signum) { 11593b243b72SRobert Watson /* Generally permit job and terminal control signals. */ 11604c5eb9c3SRobert Watson case 0: 11614c5eb9c3SRobert Watson case SIGKILL: 11624c5eb9c3SRobert Watson case SIGINT: 11634c5eb9c3SRobert Watson case SIGTERM: 11644c5eb9c3SRobert Watson case SIGSTOP: 11654c5eb9c3SRobert Watson case SIGTTIN: 11664c5eb9c3SRobert Watson case SIGTTOU: 11674c5eb9c3SRobert Watson case SIGTSTP: 11684c5eb9c3SRobert Watson case SIGHUP: 11694c5eb9c3SRobert Watson case SIGUSR1: 11704c5eb9c3SRobert Watson case SIGUSR2: 11714c5eb9c3SRobert Watson break; 11724c5eb9c3SRobert Watson default: 11733b243b72SRobert Watson /* Not permitted, privilege is required. */ 11744c5eb9c3SRobert Watson error = suser_xxx(NULL, p1, PRISON_ROOT); 11754c5eb9c3SRobert Watson if (error) 11764c5eb9c3SRobert Watson return (error); 11774c5eb9c3SRobert Watson } 1178e9e7ff5bSRobert Watson } 1179e9e7ff5bSRobert Watson 11804c5eb9c3SRobert Watson /* 11813b243b72SRobert Watson * Generally, the target credential's ruid or svuid must match the 1182e9e7ff5bSRobert Watson * subject credential's ruid or euid. 11834c5eb9c3SRobert Watson */ 1184b1fc0ec1SRobert Watson if (p1->p_ucred->cr_ruid != p2->p_ucred->cr_ruid && 1185b1fc0ec1SRobert Watson p1->p_ucred->cr_ruid != p2->p_ucred->cr_svuid && 1186b1fc0ec1SRobert Watson p1->p_ucred->cr_uid != p2->p_ucred->cr_ruid && 1187b1fc0ec1SRobert Watson p1->p_ucred->cr_uid != p2->p_ucred->cr_svuid) { 11884c5eb9c3SRobert Watson /* Not permitted, try privilege. */ 11894c5eb9c3SRobert Watson error = suser_xxx(NULL, p1, PRISON_ROOT); 11904c5eb9c3SRobert Watson if (error) 11914c5eb9c3SRobert Watson return (error); 11924c5eb9c3SRobert Watson } 1193387d2c03SRobert Watson 1194387d2c03SRobert Watson return (0); 1195387d2c03SRobert Watson } 1196a9e0361bSPoul-Henning Kamp 11973b243b72SRobert Watson /* 11983b243b72SRobert Watson * p_cansched(p1, p2): determine whether p1 may reschedule p2 11993b243b72SRobert Watson * Arguments: processes p1 and p2 12003b243b72SRobert Watson * Returns: 0 on success, an errno value otherwise 12013b243b72SRobert Watson * Locks: Sufficient locks to protect various components of p1 and p2 12023b243b72SRobert Watson * must be held. Normally, p1 will be curproc, and a lock must 12033b243b72SRobert Watson * be held on p2. 12043b243b72SRobert Watson * References: p1 and p2 must be valid for the lifetime of the call 12053b243b72SRobert Watson */ 1206a0f75161SRobert Watson int 1207a0f75161SRobert Watson p_cansched(struct proc *p1, struct proc *p2) 1208387d2c03SRobert Watson { 120991421ba2SRobert Watson int error; 1210387d2c03SRobert Watson 1211387d2c03SRobert Watson if (p1 == p2) 1212387d2c03SRobert Watson return (0); 1213387d2c03SRobert Watson 121491421ba2SRobert Watson if ((error = prison_check(p1->p_ucred, p2->p_ucred))) 121591421ba2SRobert Watson return (error); 1216387d2c03SRobert Watson 1217b1fc0ec1SRobert Watson if (p1->p_ucred->cr_ruid == p2->p_ucred->cr_ruid) 1218387d2c03SRobert Watson return (0); 1219b1fc0ec1SRobert Watson if (p1->p_ucred->cr_uid == p2->p_ucred->cr_ruid) 1220387d2c03SRobert Watson return (0); 1221387d2c03SRobert Watson 1222a0f75161SRobert Watson if (!suser_xxx(0, p1, PRISON_ROOT)) 1223387d2c03SRobert Watson return (0); 1224387d2c03SRobert Watson 1225387d2c03SRobert Watson #ifdef CAPABILITIES 1226a0f75161SRobert Watson if (!cap_check_xxx(0, p1, CAP_SYS_NICE, PRISON_ROOT)) 1227387d2c03SRobert Watson return (0); 1228387d2c03SRobert Watson #endif 1229387d2c03SRobert Watson 1230387d2c03SRobert Watson return (EPERM); 1231387d2c03SRobert Watson } 1232387d2c03SRobert Watson 12333b243b72SRobert Watson /* 12343b243b72SRobert Watson * The kern.unprivileged_procdebug_permitted flag may be used to disable 12353b243b72SRobert Watson * a variety of unprivileged inter-process debugging services, including 12363b243b72SRobert Watson * some procfs functionality, ptrace(), and ktrace(). In the past, 12373b243b72SRobert Watson * inter-process debugging has been involved in a variety of security 12383b243b72SRobert Watson * problems, and sites not requiring the service might choose to disable it 12393b243b72SRobert Watson * when hardening systems. 12403b243b72SRobert Watson * 12413b243b72SRobert Watson * XXX: Should modifying and reading this variable require locking? 12423b243b72SRobert Watson */ 12430ef5652eSRobert Watson static int kern_unprivileged_procdebug_permitted = 1; 12440ef5652eSRobert Watson SYSCTL_INT(_kern_security, OID_AUTO, unprivileged_procdebug_permitted, 12450ef5652eSRobert Watson CTLFLAG_RW, &kern_unprivileged_procdebug_permitted, 0, 12460ef5652eSRobert Watson "Unprivileged processes may use process debugging facilities"); 12470ef5652eSRobert Watson 12483b243b72SRobert Watson /* 12493b243b72SRobert Watson * p_candebug(p1, p2): determine whether p1 may debug p2 12503b243b72SRobert Watson * Arguments: processes p1 and p2 12513b243b72SRobert Watson * Returns: 0 on success, an errno value otherwise 12523b243b72SRobert Watson * Locks: Sufficient locks to protect the various components of p1 and p2 12533b243b72SRobert Watson * must be held. Normally, p1 will be curproc, and a lock must be 12543b243b72SRobert Watson * held for p2. 12553b243b72SRobert Watson * References: p1 and p2 must be valid for the lifetime of the call 12563b243b72SRobert Watson */ 1257a0f75161SRobert Watson int 1258a0f75161SRobert Watson p_candebug(struct proc *p1, struct proc *p2) 1259387d2c03SRobert Watson { 1260387d2c03SRobert Watson int error; 1261387d2c03SRobert Watson 126291421ba2SRobert Watson if ((error = prison_check(p1->p_ucred, p2->p_ucred))) 126391421ba2SRobert Watson return (error); 1264387d2c03SRobert Watson 1265387d2c03SRobert Watson /* not owned by you, has done setuid (unless you're root) */ 1266387d2c03SRobert Watson /* add a CAP_SYS_PTRACE here? */ 1267b1fc0ec1SRobert Watson if (p1->p_ucred->cr_uid != p2->p_ucred->cr_uid || 1268b1fc0ec1SRobert Watson p1->p_ucred->cr_uid != p2->p_ucred->cr_svuid || 1269b1fc0ec1SRobert Watson p1->p_ucred->cr_uid != p2->p_ucred->cr_ruid || 12700ef5652eSRobert Watson p2->p_flag & P_SUGID || !kern_unprivileged_procdebug_permitted) 1271387d2c03SRobert Watson if ((error = suser_xxx(0, p1, PRISON_ROOT))) 1272387d2c03SRobert Watson return (error); 1273387d2c03SRobert Watson 1274387d2c03SRobert Watson /* can't trace init when securelevel > 0 */ 1275387d2c03SRobert Watson if (securelevel > 0 && p2->p_pid == 1) 1276387d2c03SRobert Watson return (EPERM); 1277387d2c03SRobert Watson 1278387d2c03SRobert Watson return (0); 1279387d2c03SRobert Watson } 1280387d2c03SRobert Watson 1281a9e0361bSPoul-Henning Kamp /* 1282df8bae1dSRodney W. Grimes * Allocate a zeroed cred structure. 1283df8bae1dSRodney W. Grimes */ 1284df8bae1dSRodney W. Grimes struct ucred * 1285df8bae1dSRodney W. Grimes crget() 1286df8bae1dSRodney W. Grimes { 1287df8bae1dSRodney W. Grimes register struct ucred *cr; 1288df8bae1dSRodney W. Grimes 12891e5d626aSAlfred Perlstein MALLOC(cr, struct ucred *, sizeof(*cr), M_CRED, M_WAITOK|M_ZERO); 1290df8bae1dSRodney W. Grimes cr->cr_ref = 1; 12911e5d626aSAlfred Perlstein mtx_init(&cr->cr_mtx, "ucred", MTX_DEF); 1292df8bae1dSRodney W. Grimes return (cr); 1293df8bae1dSRodney W. Grimes } 1294df8bae1dSRodney W. Grimes 1295df8bae1dSRodney W. Grimes /* 1296661702abSRobert Watson * Claim another reference to a ucred structure 12975c3f70d7SAlfred Perlstein */ 12985c3f70d7SAlfred Perlstein void 12995c3f70d7SAlfred Perlstein crhold(cr) 13005c3f70d7SAlfred Perlstein struct ucred *cr; 13015c3f70d7SAlfred Perlstein { 13025c3f70d7SAlfred Perlstein 13039ed346baSBosko Milekic mtx_lock(&cr->cr_mtx); 13045c3f70d7SAlfred Perlstein cr->cr_ref++; 13059ed346baSBosko Milekic mtx_unlock(&(cr)->cr_mtx); 13065c3f70d7SAlfred Perlstein } 13075c3f70d7SAlfred Perlstein 13085c3f70d7SAlfred Perlstein 13095c3f70d7SAlfred Perlstein /* 1310df8bae1dSRodney W. Grimes * Free a cred structure. 1311df8bae1dSRodney W. Grimes * Throws away space when ref count gets to 0. 1312df8bae1dSRodney W. Grimes */ 131326f9a767SRodney W. Grimes void 1314df8bae1dSRodney W. Grimes crfree(cr) 1315df8bae1dSRodney W. Grimes struct ucred *cr; 1316df8bae1dSRodney W. Grimes { 13171e5d626aSAlfred Perlstein 13189ed346baSBosko Milekic mtx_lock(&cr->cr_mtx); 1319e04670b7SAlfred Perlstein KASSERT(cr->cr_ref > 0, ("bad ucred refcount: %d", cr->cr_ref)); 1320f535380cSDon Lewis if (--cr->cr_ref == 0) { 13211e5d626aSAlfred Perlstein mtx_destroy(&cr->cr_mtx); 1322f535380cSDon Lewis /* 1323f535380cSDon Lewis * Some callers of crget(), such as nfs_statfs(), 1324f535380cSDon Lewis * allocate a temporary credential, but don't 1325f535380cSDon Lewis * allocate a uidinfo structure. 1326f535380cSDon Lewis */ 1327f535380cSDon Lewis if (cr->cr_uidinfo != NULL) 1328f535380cSDon Lewis uifree(cr->cr_uidinfo); 1329823c224eSRobert Watson if (cr->cr_ruidinfo != NULL) 1330823c224eSRobert Watson uifree(cr->cr_ruidinfo); 133191421ba2SRobert Watson /* 133291421ba2SRobert Watson * Free a prison, if any. 133391421ba2SRobert Watson */ 133491421ba2SRobert Watson if (jailed(cr)) 133591421ba2SRobert Watson prison_free(cr->cr_prison); 1336df8bae1dSRodney W. Grimes FREE((caddr_t)cr, M_CRED); 13371e5d626aSAlfred Perlstein } else { 13389ed346baSBosko Milekic mtx_unlock(&cr->cr_mtx); 1339df8bae1dSRodney W. Grimes } 1340f535380cSDon Lewis } 1341df8bae1dSRodney W. Grimes 1342df8bae1dSRodney W. Grimes /* 1343df8bae1dSRodney W. Grimes * Copy cred structure to a new one and free the old one. 1344df8bae1dSRodney W. Grimes */ 1345df8bae1dSRodney W. Grimes struct ucred * 1346df8bae1dSRodney W. Grimes crcopy(cr) 1347df8bae1dSRodney W. Grimes struct ucred *cr; 1348df8bae1dSRodney W. Grimes { 1349df8bae1dSRodney W. Grimes struct ucred *newcr; 1350df8bae1dSRodney W. Grimes 13519ed346baSBosko Milekic mtx_lock(&cr->cr_mtx); 13521e5d626aSAlfred Perlstein if (cr->cr_ref == 1) { 13539ed346baSBosko Milekic mtx_unlock(&cr->cr_mtx); 1354df8bae1dSRodney W. Grimes return (cr); 13551e5d626aSAlfred Perlstein } 13569ed346baSBosko Milekic mtx_unlock(&cr->cr_mtx); 13571e5d626aSAlfred Perlstein newcr = crdup(cr); 1358df8bae1dSRodney W. Grimes crfree(cr); 1359df8bae1dSRodney W. Grimes return (newcr); 1360df8bae1dSRodney W. Grimes } 1361df8bae1dSRodney W. Grimes 1362df8bae1dSRodney W. Grimes /* 1363df8bae1dSRodney W. Grimes * Dup cred struct to a new held one. 1364df8bae1dSRodney W. Grimes */ 1365df8bae1dSRodney W. Grimes struct ucred * 1366df8bae1dSRodney W. Grimes crdup(cr) 1367df8bae1dSRodney W. Grimes struct ucred *cr; 1368df8bae1dSRodney W. Grimes { 1369df8bae1dSRodney W. Grimes struct ucred *newcr; 1370df8bae1dSRodney W. Grimes 13711e5d626aSAlfred Perlstein MALLOC(newcr, struct ucred *, sizeof(*cr), M_CRED, M_WAITOK); 1372df8bae1dSRodney W. Grimes *newcr = *cr; 13731e5d626aSAlfred Perlstein mtx_init(&newcr->cr_mtx, "ucred", MTX_DEF); 1374f535380cSDon Lewis uihold(newcr->cr_uidinfo); 1375b1fc0ec1SRobert Watson uihold(newcr->cr_ruidinfo); 137691421ba2SRobert Watson if (jailed(newcr)) 137791421ba2SRobert Watson prison_hold(newcr->cr_prison); 1378df8bae1dSRodney W. Grimes newcr->cr_ref = 1; 1379df8bae1dSRodney W. Grimes return (newcr); 1380df8bae1dSRodney W. Grimes } 1381df8bae1dSRodney W. Grimes 1382df8bae1dSRodney W. Grimes /* 1383df8bae1dSRodney W. Grimes * Get login name, if available. 1384df8bae1dSRodney W. Grimes */ 1385d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 1386df8bae1dSRodney W. Grimes struct getlogin_args { 1387df8bae1dSRodney W. Grimes char *namebuf; 1388df8bae1dSRodney W. Grimes u_int namelen; 1389df8bae1dSRodney W. Grimes }; 1390d2d3e875SBruce Evans #endif 1391df8bae1dSRodney W. Grimes /* ARGSUSED */ 139226f9a767SRodney W. Grimes int 1393cb226aaaSPoul-Henning Kamp getlogin(p, uap) 1394df8bae1dSRodney W. Grimes struct proc *p; 1395df8bae1dSRodney W. Grimes struct getlogin_args *uap; 1396df8bae1dSRodney W. Grimes { 1397df8bae1dSRodney W. Grimes 139830cf3ac4SAndrey A. Chernov if (uap->namelen > MAXLOGNAME) 139953490b76SAndrey A. Chernov uap->namelen = MAXLOGNAME; 1400df8bae1dSRodney W. Grimes return (copyout((caddr_t) p->p_pgrp->pg_session->s_login, 1401df8bae1dSRodney W. Grimes (caddr_t) uap->namebuf, uap->namelen)); 1402df8bae1dSRodney W. Grimes } 1403df8bae1dSRodney W. Grimes 1404df8bae1dSRodney W. Grimes /* 1405df8bae1dSRodney W. Grimes * Set login name. 1406df8bae1dSRodney W. Grimes */ 1407d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 1408df8bae1dSRodney W. Grimes struct setlogin_args { 1409df8bae1dSRodney W. Grimes char *namebuf; 1410df8bae1dSRodney W. Grimes }; 1411d2d3e875SBruce Evans #endif 1412df8bae1dSRodney W. Grimes /* ARGSUSED */ 141326f9a767SRodney W. Grimes int 1414cb226aaaSPoul-Henning Kamp setlogin(p, uap) 1415df8bae1dSRodney W. Grimes struct proc *p; 1416df8bae1dSRodney W. Grimes struct setlogin_args *uap; 1417df8bae1dSRodney W. Grimes { 1418df8bae1dSRodney W. Grimes int error; 1419964ca0caSAndrey A. Chernov char logintmp[MAXLOGNAME]; 1420df8bae1dSRodney W. Grimes 142175c13541SPoul-Henning Kamp if ((error = suser_xxx(0, p, PRISON_ROOT))) 1422df8bae1dSRodney W. Grimes return (error); 1423184989c2SDavid Nugent error = copyinstr((caddr_t) uap->namebuf, (caddr_t) logintmp, 142410d4743fSDoug Rabson sizeof(logintmp), (size_t *)0); 1425df8bae1dSRodney W. Grimes if (error == ENAMETOOLONG) 1426df8bae1dSRodney W. Grimes error = EINVAL; 1427184989c2SDavid Nugent else if (!error) 1428184989c2SDavid Nugent (void) memcpy(p->p_pgrp->pg_session->s_login, logintmp, 1429964ca0caSAndrey A. Chernov sizeof(logintmp)); 1430df8bae1dSRodney W. Grimes return (error); 1431df8bae1dSRodney W. Grimes } 1432d5f81602SSean Eric Fagan 1433d5f81602SSean Eric Fagan void 1434d5f81602SSean Eric Fagan setsugid(p) 1435d5f81602SSean Eric Fagan struct proc *p; 1436d5f81602SSean Eric Fagan { 1437d5f81602SSean Eric Fagan p->p_flag |= P_SUGID; 143889361835SSean Eric Fagan if (!(p->p_pfsflags & PF_ISUGID)) 1439d5f81602SSean Eric Fagan p->p_stops = 0; 1440d5f81602SSean Eric Fagan } 1441f535380cSDon Lewis 1442f535380cSDon Lewis /* 1443b1fc0ec1SRobert Watson * change_euid(): Change a process's effective uid. 1444b1fc0ec1SRobert Watson * Side effects: newcred->cr_uid and newcred->cr_uidinfo will be modified. 1445b1fc0ec1SRobert Watson * References: newcred must be an exclusive credential reference for the 1446b1fc0ec1SRobert Watson * duration of the call. 1447f535380cSDon Lewis */ 1448f535380cSDon Lewis void 1449b1fc0ec1SRobert Watson change_euid(newcred, euid) 1450b1fc0ec1SRobert Watson struct ucred *newcred; 1451f535380cSDon Lewis uid_t euid; 1452f535380cSDon Lewis { 1453f535380cSDon Lewis 1454b1fc0ec1SRobert Watson newcred->cr_uid = euid; 1455b1fc0ec1SRobert Watson uifree(newcred->cr_uidinfo); 1456b1fc0ec1SRobert Watson newcred->cr_uidinfo = uifind(euid); 1457f535380cSDon Lewis } 1458f535380cSDon Lewis 1459f535380cSDon Lewis /* 1460b1fc0ec1SRobert Watson * change_egid(): Change a process's effective gid. 1461b1fc0ec1SRobert Watson * Side effects: newcred->cr_gid will be modified. 1462b1fc0ec1SRobert Watson * References: newcred must be an exclusive credential reference for the 1463b1fc0ec1SRobert Watson * duration of the call. 1464f535380cSDon Lewis */ 1465810bfc8eSAndrew Gallatin void 1466b1fc0ec1SRobert Watson change_egid(newcred, egid) 1467b1fc0ec1SRobert Watson struct ucred *newcred; 1468b1fc0ec1SRobert Watson gid_t egid; 1469b1fc0ec1SRobert Watson { 1470b1fc0ec1SRobert Watson 1471b1fc0ec1SRobert Watson newcred->cr_groups[0] = egid; 1472b1fc0ec1SRobert Watson } 1473b1fc0ec1SRobert Watson 1474b1fc0ec1SRobert Watson /* 1475b1fc0ec1SRobert Watson * change_ruid(): Change a process's real uid. 1476b1fc0ec1SRobert Watson * Side effects: newcred->cr_ruid will be updated, newcred->cr_ruidinfo 1477b1fc0ec1SRobert Watson * will be updated, and the old and new cr_ruidinfo proc 1478b1fc0ec1SRobert Watson * counts will be updated. 1479b1fc0ec1SRobert Watson * References: newcred must be an exclusive credential reference for the 1480b1fc0ec1SRobert Watson * duration of the call. 1481b1fc0ec1SRobert Watson */ 1482b1fc0ec1SRobert Watson void 1483b1fc0ec1SRobert Watson change_ruid(newcred, ruid) 1484b1fc0ec1SRobert Watson struct ucred *newcred; 1485f535380cSDon Lewis uid_t ruid; 1486f535380cSDon Lewis { 1487f535380cSDon Lewis 1488b1fc0ec1SRobert Watson (void)chgproccnt(newcred->cr_ruidinfo, -1, 0); 1489b1fc0ec1SRobert Watson newcred->cr_ruid = ruid; 1490b1fc0ec1SRobert Watson uifree(newcred->cr_ruidinfo); 1491b1fc0ec1SRobert Watson newcred->cr_ruidinfo = uifind(ruid); 1492b1fc0ec1SRobert Watson (void)chgproccnt(newcred->cr_ruidinfo, 1, 0); 1493b1fc0ec1SRobert Watson } 1494b1fc0ec1SRobert Watson 1495b1fc0ec1SRobert Watson /* 1496b1fc0ec1SRobert Watson * change_rgid(): Change a process's real gid. 1497b1fc0ec1SRobert Watson * Side effects: newcred->cr_rgid will be updated. 1498b1fc0ec1SRobert Watson * References: newcred must be an exclusive credential reference for the 1499b1fc0ec1SRobert Watson * duration of the call. 1500b1fc0ec1SRobert Watson */ 1501b1fc0ec1SRobert Watson void 1502b1fc0ec1SRobert Watson change_rgid(newcred, rgid) 1503b1fc0ec1SRobert Watson struct ucred *newcred; 1504b1fc0ec1SRobert Watson gid_t rgid; 1505b1fc0ec1SRobert Watson { 1506b1fc0ec1SRobert Watson 1507b1fc0ec1SRobert Watson newcred->cr_rgid = rgid; 1508b1fc0ec1SRobert Watson } 1509b1fc0ec1SRobert Watson 1510b1fc0ec1SRobert Watson /* 1511b1fc0ec1SRobert Watson * change_svuid(): Change a process's saved uid. 1512b1fc0ec1SRobert Watson * Side effects: newcred->cr_svuid will be updated. 1513b1fc0ec1SRobert Watson * References: newcred must be an exclusive credential reference for the 1514b1fc0ec1SRobert Watson * duration of the call. 1515b1fc0ec1SRobert Watson */ 1516b1fc0ec1SRobert Watson void 1517b1fc0ec1SRobert Watson change_svuid(newcred, svuid) 1518b1fc0ec1SRobert Watson struct ucred *newcred; 1519b1fc0ec1SRobert Watson uid_t svuid; 1520b1fc0ec1SRobert Watson { 1521b1fc0ec1SRobert Watson 1522b1fc0ec1SRobert Watson newcred->cr_svuid = svuid; 1523b1fc0ec1SRobert Watson } 1524b1fc0ec1SRobert Watson 1525b1fc0ec1SRobert Watson /* 1526b1fc0ec1SRobert Watson * change_svgid(): Change a process's saved gid. 1527b1fc0ec1SRobert Watson * Side effects: newcred->cr_svgid will be updated. 1528b1fc0ec1SRobert Watson * References: newcred must be an exclusive credential reference for the 1529b1fc0ec1SRobert Watson * duration of the call. 1530b1fc0ec1SRobert Watson */ 1531b1fc0ec1SRobert Watson void 1532b1fc0ec1SRobert Watson change_svgid(newcred, svgid) 1533b1fc0ec1SRobert Watson struct ucred *newcred; 1534b1fc0ec1SRobert Watson gid_t svgid; 1535b1fc0ec1SRobert Watson { 1536b1fc0ec1SRobert Watson 1537b1fc0ec1SRobert Watson newcred->cr_svgid = svgid; 1538f535380cSDon Lewis } 1539