1df8bae1dSRodney W. Grimes /* 2df8bae1dSRodney W. Grimes * Copyright (c) 1982, 1986, 1989, 1990, 1991, 1993 3df8bae1dSRodney W. Grimes * The Regents of the University of California. All rights reserved. 4df8bae1dSRodney W. Grimes * (c) UNIX System Laboratories, Inc. 5df8bae1dSRodney W. Grimes * All or some portions of this file are derived from material licensed 6df8bae1dSRodney W. Grimes * to the University of California by American Telephone and Telegraph 7df8bae1dSRodney W. Grimes * Co. or Unix System Laboratories, Inc. and are reproduced herein with 8df8bae1dSRodney W. Grimes * the permission of UNIX System Laboratories, Inc. 9df8bae1dSRodney W. Grimes * 10df8bae1dSRodney W. Grimes * Redistribution and use in source and binary forms, with or without 11df8bae1dSRodney W. Grimes * modification, are permitted provided that the following conditions 12df8bae1dSRodney W. Grimes * are met: 13df8bae1dSRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 14df8bae1dSRodney W. Grimes * notice, this list of conditions and the following disclaimer. 15df8bae1dSRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 16df8bae1dSRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 17df8bae1dSRodney W. Grimes * documentation and/or other materials provided with the distribution. 18df8bae1dSRodney W. Grimes * 3. All advertising materials mentioning features or use of this software 19df8bae1dSRodney W. Grimes * must display the following acknowledgement: 20df8bae1dSRodney W. Grimes * This product includes software developed by the University of 21df8bae1dSRodney W. Grimes * California, Berkeley and its contributors. 22df8bae1dSRodney W. Grimes * 4. Neither the name of the University nor the names of its contributors 23df8bae1dSRodney W. Grimes * may be used to endorse or promote products derived from this software 24df8bae1dSRodney W. Grimes * without specific prior written permission. 25df8bae1dSRodney W. Grimes * 26df8bae1dSRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27df8bae1dSRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28df8bae1dSRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29df8bae1dSRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30df8bae1dSRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31df8bae1dSRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32df8bae1dSRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33df8bae1dSRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34df8bae1dSRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35df8bae1dSRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36df8bae1dSRodney W. Grimes * SUCH DAMAGE. 37df8bae1dSRodney W. Grimes * 38df8bae1dSRodney W. Grimes * @(#)kern_prot.c 8.6 (Berkeley) 1/21/94 391a5018a0SPeter Wemm * $Id: kern_prot.c,v 1.33 1997/08/02 14:31:34 bde Exp $ 40df8bae1dSRodney W. Grimes */ 41df8bae1dSRodney W. Grimes 42df8bae1dSRodney W. Grimes /* 43df8bae1dSRodney W. Grimes * System calls related to processes and protection 44df8bae1dSRodney W. Grimes */ 45df8bae1dSRodney W. Grimes 46df8bae1dSRodney W. Grimes #include <sys/param.h> 47df8bae1dSRodney W. Grimes #include <sys/acct.h> 48df8bae1dSRodney W. Grimes #include <sys/systm.h> 49d2d3e875SBruce Evans #include <sys/sysproto.h> 50df8bae1dSRodney W. Grimes #include <sys/proc.h> 51df8bae1dSRodney W. Grimes #include <sys/malloc.h> 52c957118eSBruce Evans #include <sys/unistd.h> 53df8bae1dSRodney W. Grimes 54d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 55ad7507e2SSteven Wallace struct getpid_args { 56df8bae1dSRodney W. Grimes int dummy; 57df8bae1dSRodney W. Grimes }; 58d2d3e875SBruce Evans #endif 59df8bae1dSRodney W. Grimes 60df8bae1dSRodney W. Grimes /* ARGSUSED */ 6126f9a767SRodney W. Grimes int 62df8bae1dSRodney W. Grimes getpid(p, uap, retval) 63df8bae1dSRodney W. Grimes struct proc *p; 64ad7507e2SSteven Wallace struct getpid_args *uap; 65df8bae1dSRodney W. Grimes int *retval; 66df8bae1dSRodney W. Grimes { 67df8bae1dSRodney W. Grimes 68df8bae1dSRodney W. Grimes *retval = p->p_pid; 69df8bae1dSRodney W. Grimes #if defined(COMPAT_43) || defined(COMPAT_SUNOS) 70df8bae1dSRodney W. Grimes retval[1] = p->p_pptr->p_pid; 71df8bae1dSRodney W. Grimes #endif 72df8bae1dSRodney W. Grimes return (0); 73df8bae1dSRodney W. Grimes } 74df8bae1dSRodney W. Grimes 75d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 76ad7507e2SSteven Wallace struct getppid_args { 77ad7507e2SSteven Wallace int dummy; 78ad7507e2SSteven Wallace }; 79d2d3e875SBruce Evans #endif 80df8bae1dSRodney W. Grimes /* ARGSUSED */ 8126f9a767SRodney W. Grimes int 82df8bae1dSRodney W. Grimes getppid(p, uap, retval) 83df8bae1dSRodney W. Grimes struct proc *p; 84ad7507e2SSteven Wallace struct getppid_args *uap; 85df8bae1dSRodney W. Grimes int *retval; 86df8bae1dSRodney W. Grimes { 87df8bae1dSRodney W. Grimes 88df8bae1dSRodney W. Grimes *retval = p->p_pptr->p_pid; 89df8bae1dSRodney W. Grimes return (0); 90df8bae1dSRodney W. Grimes } 91df8bae1dSRodney W. Grimes 92df8bae1dSRodney W. Grimes /* Get process group ID; note that POSIX getpgrp takes no parameter */ 93d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 94ad7507e2SSteven Wallace struct getpgrp_args { 95ad7507e2SSteven Wallace int dummy; 96ad7507e2SSteven Wallace }; 97d2d3e875SBruce Evans #endif 98ad7507e2SSteven Wallace 9926f9a767SRodney W. Grimes int 100df8bae1dSRodney W. Grimes getpgrp(p, uap, retval) 101df8bae1dSRodney W. Grimes struct proc *p; 102ad7507e2SSteven Wallace struct getpgrp_args *uap; 103df8bae1dSRodney W. Grimes int *retval; 104df8bae1dSRodney W. Grimes { 105df8bae1dSRodney W. Grimes 106df8bae1dSRodney W. Grimes *retval = p->p_pgrp->pg_id; 107df8bae1dSRodney W. Grimes return (0); 108df8bae1dSRodney W. Grimes } 109df8bae1dSRodney W. Grimes 1101a5018a0SPeter Wemm /* Get an arbitary pid's process group id */ 1111a5018a0SPeter Wemm #ifndef _SYS_SYSPROTO_H_ 1121a5018a0SPeter Wemm struct getpgid_args { 1131a5018a0SPeter Wemm pid_t pid; 1141a5018a0SPeter Wemm }; 1151a5018a0SPeter Wemm #endif 1161a5018a0SPeter Wemm 1171a5018a0SPeter Wemm int 1181a5018a0SPeter Wemm getpgid(p, uap, retval) 1191a5018a0SPeter Wemm struct proc *p; 1201a5018a0SPeter Wemm struct getpgid_args *uap; 1211a5018a0SPeter Wemm int *retval; 1221a5018a0SPeter Wemm { 1231a5018a0SPeter Wemm if (uap->pid == 0) 1241a5018a0SPeter Wemm goto found; 1251a5018a0SPeter Wemm 1261a5018a0SPeter Wemm if ((p == pfind(uap->pid)) == 0) 1271a5018a0SPeter Wemm return ESRCH; 1281a5018a0SPeter Wemm found: 1291a5018a0SPeter Wemm *retval = p->p_pgrp->pg_id; 1301a5018a0SPeter Wemm return 0; 1311a5018a0SPeter Wemm } 1321a5018a0SPeter Wemm 1331a5018a0SPeter Wemm /* 1341a5018a0SPeter Wemm * Get an arbitary pid's session id. 1351a5018a0SPeter Wemm */ 1361a5018a0SPeter Wemm #ifndef _SYS_SYSPROTO_H_ 1371a5018a0SPeter Wemm struct getsid_args { 1381a5018a0SPeter Wemm pid_t pid; 1391a5018a0SPeter Wemm }; 1401a5018a0SPeter Wemm #endif 1411a5018a0SPeter Wemm 1421a5018a0SPeter Wemm int 1431a5018a0SPeter Wemm getsid(p, uap, retval) 1441a5018a0SPeter Wemm struct proc *p; 1451a5018a0SPeter Wemm struct getsid_args *uap; 1461a5018a0SPeter Wemm int *retval; 1471a5018a0SPeter Wemm { 1481a5018a0SPeter Wemm if (uap->pid == 0) 1491a5018a0SPeter Wemm goto found; 1501a5018a0SPeter Wemm 1511a5018a0SPeter Wemm if ((p == pfind(uap->pid)) == 0) 1521a5018a0SPeter Wemm return ESRCH; 1531a5018a0SPeter Wemm found: 1541a5018a0SPeter Wemm *retval = p->p_pgrp->pg_session->s_leader->p_pid; 1551a5018a0SPeter Wemm return 0; 1561a5018a0SPeter Wemm } 1571a5018a0SPeter Wemm 1581a5018a0SPeter Wemm 159d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 160ad7507e2SSteven Wallace struct getuid_args { 161ad7507e2SSteven Wallace int dummy; 162ad7507e2SSteven Wallace }; 163d2d3e875SBruce Evans #endif 164ad7507e2SSteven Wallace 165df8bae1dSRodney W. Grimes /* ARGSUSED */ 16626f9a767SRodney W. Grimes int 167df8bae1dSRodney W. Grimes getuid(p, uap, retval) 168df8bae1dSRodney W. Grimes struct proc *p; 169ad7507e2SSteven Wallace struct getuid_args *uap; 170df8bae1dSRodney W. Grimes int *retval; 171df8bae1dSRodney W. Grimes { 172df8bae1dSRodney W. Grimes 173df8bae1dSRodney W. Grimes *retval = p->p_cred->p_ruid; 174df8bae1dSRodney W. Grimes #if defined(COMPAT_43) || defined(COMPAT_SUNOS) 175df8bae1dSRodney W. Grimes retval[1] = p->p_ucred->cr_uid; 176df8bae1dSRodney W. Grimes #endif 177df8bae1dSRodney W. Grimes return (0); 178df8bae1dSRodney W. Grimes } 179df8bae1dSRodney W. Grimes 180d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 181ad7507e2SSteven Wallace struct geteuid_args { 182ad7507e2SSteven Wallace int dummy; 183ad7507e2SSteven Wallace }; 184d2d3e875SBruce Evans #endif 185ad7507e2SSteven Wallace 186df8bae1dSRodney W. Grimes /* ARGSUSED */ 18726f9a767SRodney W. Grimes int 188df8bae1dSRodney W. Grimes geteuid(p, uap, retval) 189df8bae1dSRodney W. Grimes struct proc *p; 190ad7507e2SSteven Wallace struct geteuid_args *uap; 191df8bae1dSRodney W. Grimes int *retval; 192df8bae1dSRodney W. Grimes { 193df8bae1dSRodney W. Grimes 194df8bae1dSRodney W. Grimes *retval = p->p_ucred->cr_uid; 195df8bae1dSRodney W. Grimes return (0); 196df8bae1dSRodney W. Grimes } 197df8bae1dSRodney W. Grimes 198d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 199ad7507e2SSteven Wallace struct getgid_args { 200ad7507e2SSteven Wallace int dummy; 201ad7507e2SSteven Wallace }; 202d2d3e875SBruce Evans #endif 203ad7507e2SSteven Wallace 204df8bae1dSRodney W. Grimes /* ARGSUSED */ 20526f9a767SRodney W. Grimes int 206df8bae1dSRodney W. Grimes getgid(p, uap, retval) 207df8bae1dSRodney W. Grimes struct proc *p; 208ad7507e2SSteven Wallace struct getgid_args *uap; 209df8bae1dSRodney W. Grimes int *retval; 210df8bae1dSRodney W. Grimes { 211df8bae1dSRodney W. Grimes 212df8bae1dSRodney W. Grimes *retval = p->p_cred->p_rgid; 213df8bae1dSRodney W. Grimes #if defined(COMPAT_43) || defined(COMPAT_SUNOS) 214df8bae1dSRodney W. Grimes retval[1] = p->p_ucred->cr_groups[0]; 215df8bae1dSRodney W. Grimes #endif 216df8bae1dSRodney W. Grimes return (0); 217df8bae1dSRodney W. Grimes } 218df8bae1dSRodney W. Grimes 219df8bae1dSRodney W. Grimes /* 220df8bae1dSRodney W. Grimes * Get effective group ID. The "egid" is groups[0], and could be obtained 221df8bae1dSRodney W. Grimes * via getgroups. This syscall exists because it is somewhat painful to do 222df8bae1dSRodney W. Grimes * correctly in a library function. 223df8bae1dSRodney W. Grimes */ 224d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 225ad7507e2SSteven Wallace struct getegid_args { 226ad7507e2SSteven Wallace int dummy; 227ad7507e2SSteven Wallace }; 228d2d3e875SBruce Evans #endif 229ad7507e2SSteven Wallace 230df8bae1dSRodney W. Grimes /* ARGSUSED */ 23126f9a767SRodney W. Grimes int 232df8bae1dSRodney W. Grimes getegid(p, uap, retval) 233df8bae1dSRodney W. Grimes struct proc *p; 234ad7507e2SSteven Wallace struct getegid_args *uap; 235df8bae1dSRodney W. Grimes int *retval; 236df8bae1dSRodney W. Grimes { 237df8bae1dSRodney W. Grimes 238df8bae1dSRodney W. Grimes *retval = p->p_ucred->cr_groups[0]; 239df8bae1dSRodney W. Grimes return (0); 240df8bae1dSRodney W. Grimes } 241df8bae1dSRodney W. Grimes 242d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 243df8bae1dSRodney W. Grimes struct getgroups_args { 244df8bae1dSRodney W. Grimes u_int gidsetsize; 245df8bae1dSRodney W. Grimes gid_t *gidset; 246df8bae1dSRodney W. Grimes }; 247d2d3e875SBruce Evans #endif 24826f9a767SRodney W. Grimes int 249df8bae1dSRodney W. Grimes getgroups(p, uap, retval) 250df8bae1dSRodney W. Grimes struct proc *p; 251df8bae1dSRodney W. Grimes register struct getgroups_args *uap; 252df8bae1dSRodney W. Grimes int *retval; 253df8bae1dSRodney W. Grimes { 254df8bae1dSRodney W. Grimes register struct pcred *pc = p->p_cred; 255df8bae1dSRodney W. Grimes register u_int ngrp; 256df8bae1dSRodney W. Grimes int error; 257df8bae1dSRodney W. Grimes 258df8bae1dSRodney W. Grimes if ((ngrp = uap->gidsetsize) == 0) { 259df8bae1dSRodney W. Grimes *retval = pc->pc_ucred->cr_ngroups; 260df8bae1dSRodney W. Grimes return (0); 261df8bae1dSRodney W. Grimes } 262df8bae1dSRodney W. Grimes if (ngrp < pc->pc_ucred->cr_ngroups) 263df8bae1dSRodney W. Grimes return (EINVAL); 264df8bae1dSRodney W. Grimes ngrp = pc->pc_ucred->cr_ngroups; 265bb56ec4aSPoul-Henning Kamp if ((error = copyout((caddr_t)pc->pc_ucred->cr_groups, 266bb56ec4aSPoul-Henning Kamp (caddr_t)uap->gidset, ngrp * sizeof(gid_t)))) 267df8bae1dSRodney W. Grimes return (error); 268df8bae1dSRodney W. Grimes *retval = ngrp; 269df8bae1dSRodney W. Grimes return (0); 270df8bae1dSRodney W. Grimes } 271df8bae1dSRodney W. Grimes 272d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 27382970b81SBruce Evans struct setsid_args { 274ad7507e2SSteven Wallace int dummy; 275ad7507e2SSteven Wallace }; 276d2d3e875SBruce Evans #endif 277ad7507e2SSteven Wallace 278df8bae1dSRodney W. Grimes /* ARGSUSED */ 27926f9a767SRodney W. Grimes int 280df8bae1dSRodney W. Grimes setsid(p, uap, retval) 281df8bae1dSRodney W. Grimes register struct proc *p; 28282970b81SBruce Evans struct setsid_args *uap; 283df8bae1dSRodney W. Grimes int *retval; 284df8bae1dSRodney W. Grimes { 285df8bae1dSRodney W. Grimes 286df8bae1dSRodney W. Grimes if (p->p_pgid == p->p_pid || pgfind(p->p_pid)) { 287df8bae1dSRodney W. Grimes return (EPERM); 288df8bae1dSRodney W. Grimes } else { 289df8bae1dSRodney W. Grimes (void)enterpgrp(p, p->p_pid, 1); 290df8bae1dSRodney W. Grimes *retval = p->p_pid; 291df8bae1dSRodney W. Grimes return (0); 292df8bae1dSRodney W. Grimes } 293df8bae1dSRodney W. Grimes } 294df8bae1dSRodney W. Grimes 295df8bae1dSRodney W. Grimes /* 296df8bae1dSRodney W. Grimes * set process group (setpgid/old setpgrp) 297df8bae1dSRodney W. Grimes * 298df8bae1dSRodney W. Grimes * caller does setpgid(targpid, targpgid) 299df8bae1dSRodney W. Grimes * 300df8bae1dSRodney W. Grimes * pid must be caller or child of caller (ESRCH) 301df8bae1dSRodney W. Grimes * if a child 302df8bae1dSRodney W. Grimes * pid must be in same session (EPERM) 303df8bae1dSRodney W. Grimes * pid can't have done an exec (EACCES) 304df8bae1dSRodney W. Grimes * if pgid != pid 305df8bae1dSRodney W. Grimes * there must exist some pid in same session having pgid (EPERM) 306df8bae1dSRodney W. Grimes * pid must not be session leader (EPERM) 307df8bae1dSRodney W. Grimes */ 308d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 309df8bae1dSRodney W. Grimes struct setpgid_args { 310df8bae1dSRodney W. Grimes int pid; /* target process id */ 311df8bae1dSRodney W. Grimes int pgid; /* target pgrp id */ 312df8bae1dSRodney W. Grimes }; 313d2d3e875SBruce Evans #endif 314df8bae1dSRodney W. Grimes /* ARGSUSED */ 31526f9a767SRodney W. Grimes int 316df8bae1dSRodney W. Grimes setpgid(curp, uap, retval) 317df8bae1dSRodney W. Grimes struct proc *curp; 318df8bae1dSRodney W. Grimes register struct setpgid_args *uap; 319df8bae1dSRodney W. Grimes int *retval; 320df8bae1dSRodney W. Grimes { 321df8bae1dSRodney W. Grimes register struct proc *targp; /* target process */ 322df8bae1dSRodney W. Grimes register struct pgrp *pgrp; /* target pgrp */ 323df8bae1dSRodney W. Grimes 32478f64bccSBruce Evans if (uap->pgid < 0) 32578f64bccSBruce Evans return (EINVAL); 326df8bae1dSRodney W. Grimes if (uap->pid != 0 && uap->pid != curp->p_pid) { 327df8bae1dSRodney W. Grimes if ((targp = pfind(uap->pid)) == 0 || !inferior(targp)) 328df8bae1dSRodney W. Grimes return (ESRCH); 329cd73303cSDavid Greenman if (targp->p_pgrp == NULL || targp->p_session != curp->p_session) 330df8bae1dSRodney W. Grimes return (EPERM); 331df8bae1dSRodney W. Grimes if (targp->p_flag & P_EXEC) 332df8bae1dSRodney W. Grimes return (EACCES); 333df8bae1dSRodney W. Grimes } else 334df8bae1dSRodney W. Grimes targp = curp; 335df8bae1dSRodney W. Grimes if (SESS_LEADER(targp)) 336df8bae1dSRodney W. Grimes return (EPERM); 337df8bae1dSRodney W. Grimes if (uap->pgid == 0) 338df8bae1dSRodney W. Grimes uap->pgid = targp->p_pid; 339df8bae1dSRodney W. Grimes else if (uap->pgid != targp->p_pid) 340df8bae1dSRodney W. Grimes if ((pgrp = pgfind(uap->pgid)) == 0 || 341df8bae1dSRodney W. Grimes pgrp->pg_session != curp->p_session) 342df8bae1dSRodney W. Grimes return (EPERM); 343df8bae1dSRodney W. Grimes return (enterpgrp(targp, uap->pgid, 0)); 344df8bae1dSRodney W. Grimes } 345df8bae1dSRodney W. Grimes 346a08f4bf6SPeter Wemm /* 347a08f4bf6SPeter Wemm * Use the clause in B.4.2.2 that allows setuid/setgid to be 4.2/4.3BSD 348a08f4bf6SPeter Wemm * compatable. It says that setting the uid/gid to euid/egid is a special 349a08f4bf6SPeter Wemm * case of "appropriate privilege". Once the rules are expanded out, this 350a08f4bf6SPeter Wemm * basically means that setuid(nnn) sets all three id's, in all permitted 351a08f4bf6SPeter Wemm * cases unless _POSIX_SAVED_IDS is enabled. In that case, setuid(getuid()) 352a08f4bf6SPeter Wemm * does not set the saved id - this is dangerous for traditional BSD 353a08f4bf6SPeter Wemm * programs. For this reason, we *really* do not want to set 354a08f4bf6SPeter Wemm * _POSIX_SAVED_IDS and do not want to clear POSIX_APPENDIX_B_4_2_2. 355a08f4bf6SPeter Wemm */ 356a08f4bf6SPeter Wemm #define POSIX_APPENDIX_B_4_2_2 357a08f4bf6SPeter Wemm 358d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 359df8bae1dSRodney W. Grimes struct setuid_args { 360df8bae1dSRodney W. Grimes uid_t uid; 361df8bae1dSRodney W. Grimes }; 362d2d3e875SBruce Evans #endif 363df8bae1dSRodney W. Grimes /* ARGSUSED */ 36426f9a767SRodney W. Grimes int 365df8bae1dSRodney W. Grimes setuid(p, uap, retval) 366df8bae1dSRodney W. Grimes struct proc *p; 367df8bae1dSRodney W. Grimes struct setuid_args *uap; 368df8bae1dSRodney W. Grimes int *retval; 369df8bae1dSRodney W. Grimes { 370df8bae1dSRodney W. Grimes register struct pcred *pc = p->p_cred; 371df8bae1dSRodney W. Grimes register uid_t uid; 372df8bae1dSRodney W. Grimes int error; 373df8bae1dSRodney W. Grimes 374a08f4bf6SPeter Wemm /* 375a08f4bf6SPeter Wemm * See if we have "permission" by POSIX 1003.1 rules. 376a08f4bf6SPeter Wemm * 377a08f4bf6SPeter Wemm * Note that setuid(geteuid()) is a special case of 378a08f4bf6SPeter Wemm * "appropriate privileges" in appendix B.4.2.2. We need 379a08f4bf6SPeter Wemm * to use this clause to be compatable with traditional BSD 380a08f4bf6SPeter Wemm * semantics. Basically, it means that "setuid(xx)" sets all 381a08f4bf6SPeter Wemm * three id's (assuming you have privs). 382a08f4bf6SPeter Wemm * 383a08f4bf6SPeter Wemm * Notes on the logic. We do things in three steps. 384a08f4bf6SPeter Wemm * 1: We determine if the euid is going to change, and do EPERM 385a08f4bf6SPeter Wemm * right away. We unconditionally change the euid later if this 386a08f4bf6SPeter Wemm * test is satisfied, simplifying that part of the logic. 387a08f4bf6SPeter Wemm * 2: We determine if the real and/or saved uid's are going to 388a08f4bf6SPeter Wemm * change. Determined by compile options. 389a08f4bf6SPeter Wemm * 3: Change euid last. (after tests in #2 for "appropriate privs") 390a08f4bf6SPeter Wemm */ 391df8bae1dSRodney W. Grimes uid = uap->uid; 392a08f4bf6SPeter Wemm if (uid != pc->p_ruid && /* allow setuid(getuid()) */ 3933f246666SAndrey A. Chernov #ifdef _POSIX_SAVED_IDS 394a08f4bf6SPeter Wemm uid != pc->p_svuid && /* allow setuid(saved gid) */ 395a08f4bf6SPeter Wemm #endif 396a08f4bf6SPeter Wemm #ifdef POSIX_APPENDIX_B_4_2_2 /* Use BSD-compat clause from B.4.2.2 */ 397a08f4bf6SPeter Wemm uid != pc->pc_ucred->cr_uid && /* allow setuid(geteuid()) */ 3983f246666SAndrey A. Chernov #endif 3992c3be6c3SAndrey A. Chernov (error = suser(pc->pc_ucred, &p->p_acflag))) 400df8bae1dSRodney W. Grimes return (error); 401a08f4bf6SPeter Wemm 402a08f4bf6SPeter Wemm #ifdef _POSIX_SAVED_IDS 403df8bae1dSRodney W. Grimes /* 404a08f4bf6SPeter Wemm * Do we have "appropriate privileges" (are we root or uid == euid) 405a08f4bf6SPeter Wemm * If so, we are changing the real uid and/or saved uid. 406df8bae1dSRodney W. Grimes */ 4073f246666SAndrey A. Chernov if ( 408a08f4bf6SPeter Wemm #ifdef POSIX_APPENDIX_B_4_2_2 /* Use the clause from B.4.2.2 */ 409a08f4bf6SPeter Wemm uid == pc->pc_ucred->cr_uid || 4103f246666SAndrey A. Chernov #endif 411a08f4bf6SPeter Wemm suser(pc->pc_ucred, &p->p_acflag) == 0) /* we are using privs */ 412a08f4bf6SPeter Wemm #endif 413a08f4bf6SPeter Wemm { 414a08f4bf6SPeter Wemm /* 415a08f4bf6SPeter Wemm * Transfer proc count to new user. 416a08f4bf6SPeter Wemm */ 417a08f4bf6SPeter Wemm if (uid != pc->p_ruid) { 418df8bae1dSRodney W. Grimes (void)chgproccnt(pc->p_ruid, -1); 419df8bae1dSRodney W. Grimes (void)chgproccnt(uid, 1); 420d3cdb93dSAndrey A. Chernov } 421a08f4bf6SPeter Wemm /* 422a08f4bf6SPeter Wemm * Set real uid 423a08f4bf6SPeter Wemm */ 424a08f4bf6SPeter Wemm if (uid != pc->p_ruid) { 425a08f4bf6SPeter Wemm p->p_flag |= P_SUGID; 426df8bae1dSRodney W. Grimes pc->p_ruid = uid; 427d3cdb93dSAndrey A. Chernov } 428a08f4bf6SPeter Wemm /* 429a08f4bf6SPeter Wemm * Set saved uid 430a08f4bf6SPeter Wemm * 431a08f4bf6SPeter Wemm * XXX always set saved uid even if not _POSIX_SAVED_IDS, as 432a08f4bf6SPeter Wemm * the security of seteuid() depends on it. B.4.2.2 says it 433a08f4bf6SPeter Wemm * is important that we should do this. 434a08f4bf6SPeter Wemm */ 435a08f4bf6SPeter Wemm if (pc->p_svuid != uid) { 436a08f4bf6SPeter Wemm p->p_flag |= P_SUGID; 437a08f4bf6SPeter Wemm pc->p_svuid = uid; 438a08f4bf6SPeter Wemm } 439a08f4bf6SPeter Wemm } 440a08f4bf6SPeter Wemm 441a08f4bf6SPeter Wemm /* 442a08f4bf6SPeter Wemm * In all permitted cases, we are changing the euid. 443a08f4bf6SPeter Wemm * Copy credentials so other references do not see our changes. 444a08f4bf6SPeter Wemm */ 445a08f4bf6SPeter Wemm if (pc->pc_ucred->cr_uid != uid) { 446a08f4bf6SPeter Wemm pc->pc_ucred = crcopy(pc->pc_ucred); 4472c3be6c3SAndrey A. Chernov pc->pc_ucred->cr_uid = uid; 448df8bae1dSRodney W. Grimes p->p_flag |= P_SUGID; 449a08f4bf6SPeter Wemm } 450df8bae1dSRodney W. Grimes return (0); 451df8bae1dSRodney W. Grimes } 452df8bae1dSRodney W. Grimes 453d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 454df8bae1dSRodney W. Grimes struct seteuid_args { 455df8bae1dSRodney W. Grimes uid_t euid; 456df8bae1dSRodney W. Grimes }; 457d2d3e875SBruce Evans #endif 458df8bae1dSRodney W. Grimes /* ARGSUSED */ 45926f9a767SRodney W. Grimes int 460df8bae1dSRodney W. Grimes seteuid(p, uap, retval) 461df8bae1dSRodney W. Grimes struct proc *p; 462df8bae1dSRodney W. Grimes struct seteuid_args *uap; 463df8bae1dSRodney W. Grimes int *retval; 464df8bae1dSRodney W. Grimes { 465df8bae1dSRodney W. Grimes register struct pcred *pc = p->p_cred; 466df8bae1dSRodney W. Grimes register uid_t euid; 467df8bae1dSRodney W. Grimes int error; 468df8bae1dSRodney W. Grimes 469df8bae1dSRodney W. Grimes euid = uap->euid; 470229a15f0SPeter Wemm if (euid != pc->p_ruid && /* allow seteuid(getuid()) */ 471229a15f0SPeter Wemm euid != pc->p_svuid && /* allow seteuid(saved uid) */ 472df8bae1dSRodney W. Grimes (error = suser(pc->pc_ucred, &p->p_acflag))) 473df8bae1dSRodney W. Grimes return (error); 474df8bae1dSRodney W. Grimes /* 475df8bae1dSRodney W. Grimes * Everything's okay, do it. Copy credentials so other references do 476df8bae1dSRodney W. Grimes * not see our changes. 477df8bae1dSRodney W. Grimes */ 478229a15f0SPeter Wemm if (pc->pc_ucred->cr_uid != euid) { 479df8bae1dSRodney W. Grimes pc->pc_ucred = crcopy(pc->pc_ucred); 480df8bae1dSRodney W. Grimes pc->pc_ucred->cr_uid = euid; 481df8bae1dSRodney W. Grimes p->p_flag |= P_SUGID; 482229a15f0SPeter Wemm } 483df8bae1dSRodney W. Grimes return (0); 484df8bae1dSRodney W. Grimes } 485df8bae1dSRodney W. Grimes 486d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 487df8bae1dSRodney W. Grimes struct setgid_args { 488df8bae1dSRodney W. Grimes gid_t gid; 489df8bae1dSRodney W. Grimes }; 490d2d3e875SBruce Evans #endif 491df8bae1dSRodney W. Grimes /* ARGSUSED */ 49226f9a767SRodney W. Grimes int 493df8bae1dSRodney W. Grimes setgid(p, uap, retval) 494df8bae1dSRodney W. Grimes struct proc *p; 495df8bae1dSRodney W. Grimes struct setgid_args *uap; 496df8bae1dSRodney W. Grimes int *retval; 497df8bae1dSRodney W. Grimes { 498df8bae1dSRodney W. Grimes register struct pcred *pc = p->p_cred; 499df8bae1dSRodney W. Grimes register gid_t gid; 500df8bae1dSRodney W. Grimes int error; 501df8bae1dSRodney W. Grimes 502a08f4bf6SPeter Wemm /* 503a08f4bf6SPeter Wemm * See if we have "permission" by POSIX 1003.1 rules. 504a08f4bf6SPeter Wemm * 505a08f4bf6SPeter Wemm * Note that setgid(getegid()) is a special case of 506a08f4bf6SPeter Wemm * "appropriate privileges" in appendix B.4.2.2. We need 507a08f4bf6SPeter Wemm * to use this clause to be compatable with traditional BSD 508a08f4bf6SPeter Wemm * semantics. Basically, it means that "setgid(xx)" sets all 509a08f4bf6SPeter Wemm * three id's (assuming you have privs). 510a08f4bf6SPeter Wemm * 511a08f4bf6SPeter Wemm * For notes on the logic here, see setuid() above. 512a08f4bf6SPeter Wemm */ 513df8bae1dSRodney W. Grimes gid = uap->gid; 514a08f4bf6SPeter Wemm if (gid != pc->p_rgid && /* allow setgid(getgid()) */ 5153f246666SAndrey A. Chernov #ifdef _POSIX_SAVED_IDS 516a08f4bf6SPeter Wemm gid != pc->p_svgid && /* allow setgid(saved gid) */ 517a08f4bf6SPeter Wemm #endif 518a08f4bf6SPeter Wemm #ifdef POSIX_APPENDIX_B_4_2_2 /* Use BSD-compat clause from B.4.2.2 */ 519a08f4bf6SPeter Wemm gid != pc->pc_ucred->cr_groups[0] && /* allow setgid(getegid()) */ 5203f246666SAndrey A. Chernov #endif 5212c3be6c3SAndrey A. Chernov (error = suser(pc->pc_ucred, &p->p_acflag))) 522df8bae1dSRodney W. Grimes return (error); 523a08f4bf6SPeter Wemm 524a08f4bf6SPeter Wemm #ifdef _POSIX_SAVED_IDS 525a08f4bf6SPeter Wemm /* 526a08f4bf6SPeter Wemm * Do we have "appropriate privileges" (are we root or gid == egid) 527a08f4bf6SPeter Wemm * If so, we are changing the real uid and saved gid. 528a08f4bf6SPeter Wemm */ 529a08f4bf6SPeter Wemm if ( 530a08f4bf6SPeter Wemm #ifdef POSIX_APPENDIX_B_4_2_2 /* use the clause from B.4.2.2 */ 531a08f4bf6SPeter Wemm gid == pc->pc_ucred->cr_groups[0] || 532a08f4bf6SPeter Wemm #endif 533a08f4bf6SPeter Wemm suser(pc->pc_ucred, &p->p_acflag) == 0) /* we are using privs */ 534a08f4bf6SPeter Wemm #endif 535a08f4bf6SPeter Wemm { 536a08f4bf6SPeter Wemm /* 537a08f4bf6SPeter Wemm * Set real gid 538a08f4bf6SPeter Wemm */ 539a08f4bf6SPeter Wemm if (pc->p_rgid != gid) { 540a08f4bf6SPeter Wemm p->p_flag |= P_SUGID; 541a08f4bf6SPeter Wemm pc->p_rgid = gid; 542a08f4bf6SPeter Wemm } 543a08f4bf6SPeter Wemm /* 544a08f4bf6SPeter Wemm * Set saved gid 545a08f4bf6SPeter Wemm * 546a08f4bf6SPeter Wemm * XXX always set saved gid even if not _POSIX_SAVED_IDS, as 547a08f4bf6SPeter Wemm * the security of setegid() depends on it. B.4.2.2 says it 548a08f4bf6SPeter Wemm * is important that we should do this. 549a08f4bf6SPeter Wemm */ 550a08f4bf6SPeter Wemm if (pc->p_svgid != gid) { 551a08f4bf6SPeter Wemm p->p_flag |= P_SUGID; 552a08f4bf6SPeter Wemm pc->p_svgid = gid; 553a08f4bf6SPeter Wemm } 554a08f4bf6SPeter Wemm } 555a08f4bf6SPeter Wemm /* 556a08f4bf6SPeter Wemm * In all cases permitted cases, we are changing the egid. 557a08f4bf6SPeter Wemm * Copy credentials so other references do not see our changes. 558a08f4bf6SPeter Wemm */ 559a08f4bf6SPeter Wemm if (pc->pc_ucred->cr_groups[0] != gid) { 560df8bae1dSRodney W. Grimes pc->pc_ucred = crcopy(pc->pc_ucred); 561df8bae1dSRodney W. Grimes pc->pc_ucred->cr_groups[0] = gid; 562df8bae1dSRodney W. Grimes p->p_flag |= P_SUGID; 563a08f4bf6SPeter Wemm } 564df8bae1dSRodney W. Grimes return (0); 565df8bae1dSRodney W. Grimes } 566df8bae1dSRodney W. Grimes 567d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 568df8bae1dSRodney W. Grimes struct setegid_args { 569df8bae1dSRodney W. Grimes gid_t egid; 570df8bae1dSRodney W. Grimes }; 571d2d3e875SBruce Evans #endif 572df8bae1dSRodney W. Grimes /* ARGSUSED */ 57326f9a767SRodney W. Grimes int 574df8bae1dSRodney W. Grimes setegid(p, uap, retval) 575df8bae1dSRodney W. Grimes struct proc *p; 576df8bae1dSRodney W. Grimes struct setegid_args *uap; 577df8bae1dSRodney W. Grimes int *retval; 578df8bae1dSRodney W. Grimes { 579df8bae1dSRodney W. Grimes register struct pcred *pc = p->p_cred; 580df8bae1dSRodney W. Grimes register gid_t egid; 581df8bae1dSRodney W. Grimes int error; 582df8bae1dSRodney W. Grimes 583df8bae1dSRodney W. Grimes egid = uap->egid; 584229a15f0SPeter Wemm if (egid != pc->p_rgid && /* allow setegid(getgid()) */ 585229a15f0SPeter Wemm egid != pc->p_svgid && /* allow setegid(saved gid) */ 586df8bae1dSRodney W. Grimes (error = suser(pc->pc_ucred, &p->p_acflag))) 587df8bae1dSRodney W. Grimes return (error); 588229a15f0SPeter Wemm if (pc->pc_ucred->cr_groups[0] != egid) { 589df8bae1dSRodney W. Grimes pc->pc_ucred = crcopy(pc->pc_ucred); 590df8bae1dSRodney W. Grimes pc->pc_ucred->cr_groups[0] = egid; 591df8bae1dSRodney W. Grimes p->p_flag |= P_SUGID; 592229a15f0SPeter Wemm } 593df8bae1dSRodney W. Grimes return (0); 594df8bae1dSRodney W. Grimes } 595df8bae1dSRodney W. Grimes 596d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 597df8bae1dSRodney W. Grimes struct setgroups_args { 598df8bae1dSRodney W. Grimes u_int gidsetsize; 599df8bae1dSRodney W. Grimes gid_t *gidset; 600df8bae1dSRodney W. Grimes }; 601d2d3e875SBruce Evans #endif 602df8bae1dSRodney W. Grimes /* ARGSUSED */ 60326f9a767SRodney W. Grimes int 604df8bae1dSRodney W. Grimes setgroups(p, uap, retval) 605df8bae1dSRodney W. Grimes struct proc *p; 606df8bae1dSRodney W. Grimes struct setgroups_args *uap; 607df8bae1dSRodney W. Grimes int *retval; 608df8bae1dSRodney W. Grimes { 609df8bae1dSRodney W. Grimes register struct pcred *pc = p->p_cred; 610df8bae1dSRodney W. Grimes register u_int ngrp; 611df8bae1dSRodney W. Grimes int error; 612df8bae1dSRodney W. Grimes 613bb56ec4aSPoul-Henning Kamp if ((error = suser(pc->pc_ucred, &p->p_acflag))) 614df8bae1dSRodney W. Grimes return (error); 6153956a170SDavid Greenman ngrp = uap->gidsetsize; 6168a5d815aSPeter Wemm if (ngrp > NGROUPS) 617df8bae1dSRodney W. Grimes return (EINVAL); 6188a5d815aSPeter Wemm /* 6198a5d815aSPeter Wemm * XXX A little bit lazy here. We could test if anything has 6208a5d815aSPeter Wemm * changed before crcopy() and setting P_SUGID. 6218a5d815aSPeter Wemm */ 622df8bae1dSRodney W. Grimes pc->pc_ucred = crcopy(pc->pc_ucred); 6238a5d815aSPeter Wemm if (ngrp < 1) { 6248a5d815aSPeter Wemm /* 6258a5d815aSPeter Wemm * setgroups(0, NULL) is a legitimate way of clearing the 6268a5d815aSPeter Wemm * groups vector on non-BSD systems (which generally do not 6278a5d815aSPeter Wemm * have the egid in the groups[0]). We risk security holes 6288a5d815aSPeter Wemm * when running non-BSD software if we do not do the same. 6298a5d815aSPeter Wemm */ 6308a5d815aSPeter Wemm pc->pc_ucred->cr_ngroups = 1; 6318a5d815aSPeter Wemm } else { 632bb56ec4aSPoul-Henning Kamp if ((error = copyin((caddr_t)uap->gidset, 633bb56ec4aSPoul-Henning Kamp (caddr_t)pc->pc_ucred->cr_groups, ngrp * sizeof(gid_t)))) 634df8bae1dSRodney W. Grimes return (error); 635df8bae1dSRodney W. Grimes pc->pc_ucred->cr_ngroups = ngrp; 6368a5d815aSPeter Wemm } 637df8bae1dSRodney W. Grimes p->p_flag |= P_SUGID; 638df8bae1dSRodney W. Grimes return (0); 639df8bae1dSRodney W. Grimes } 640df8bae1dSRodney W. Grimes 641d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 642df8bae1dSRodney W. Grimes struct setreuid_args { 64300999cd6SAndrey A. Chernov uid_t ruid; 64400999cd6SAndrey A. Chernov uid_t euid; 645df8bae1dSRodney W. Grimes }; 646d2d3e875SBruce Evans #endif 647df8bae1dSRodney W. Grimes /* ARGSUSED */ 64826f9a767SRodney W. Grimes int 649e876c909SAndrey A. Chernov setreuid(p, uap, retval) 650df8bae1dSRodney W. Grimes register struct proc *p; 651df8bae1dSRodney W. Grimes struct setreuid_args *uap; 652df8bae1dSRodney W. Grimes int *retval; 653df8bae1dSRodney W. Grimes { 654df8bae1dSRodney W. Grimes register struct pcred *pc = p->p_cred; 65500999cd6SAndrey A. Chernov register uid_t ruid, euid; 656611d721eSAndrey A. Chernov int error; 657df8bae1dSRodney W. Grimes 65800999cd6SAndrey A. Chernov ruid = uap->ruid; 65900999cd6SAndrey A. Chernov euid = uap->euid; 66000999cd6SAndrey A. Chernov if ((ruid != (uid_t)-1 && ruid != pc->p_ruid && ruid != pc->p_svuid || 661b79c6a86SPeter Wemm euid != (uid_t)-1 && euid != pc->pc_ucred->cr_uid && 662b79c6a86SPeter Wemm euid != pc->p_ruid && euid != pc->p_svuid) && 663611d721eSAndrey A. Chernov (error = suser(pc->pc_ucred, &p->p_acflag))) 664611d721eSAndrey A. Chernov return (error); 66500999cd6SAndrey A. Chernov 666a89a5370SPeter Wemm if (euid != (uid_t)-1 && pc->pc_ucred->cr_uid != euid) { 66700999cd6SAndrey A. Chernov pc->pc_ucred = crcopy(pc->pc_ucred); 66800999cd6SAndrey A. Chernov pc->pc_ucred->cr_uid = euid; 669a89a5370SPeter Wemm p->p_flag |= P_SUGID; 670a89a5370SPeter Wemm } 671a89a5370SPeter Wemm if (ruid != (uid_t)-1 && pc->p_ruid != ruid) { 6724bc8f31fSAndrey A. Chernov (void)chgproccnt(pc->p_ruid, -1); 67300999cd6SAndrey A. Chernov (void)chgproccnt(ruid, 1); 67400999cd6SAndrey A. Chernov pc->p_ruid = ruid; 675a89a5370SPeter Wemm p->p_flag |= P_SUGID; 67600999cd6SAndrey A. Chernov } 677b79c6a86SPeter Wemm if ((ruid != (uid_t)-1 || pc->pc_ucred->cr_uid != pc->p_ruid) && 678b79c6a86SPeter Wemm pc->p_svuid != pc->pc_ucred->cr_uid) { 6794bc8f31fSAndrey A. Chernov pc->p_svuid = pc->pc_ucred->cr_uid; 6804bc8f31fSAndrey A. Chernov p->p_flag |= P_SUGID; 681a89a5370SPeter Wemm } 682611d721eSAndrey A. Chernov return (0); 683df8bae1dSRodney W. Grimes } 684df8bae1dSRodney W. Grimes 685d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 686df8bae1dSRodney W. Grimes struct setregid_args { 68700999cd6SAndrey A. Chernov gid_t rgid; 68800999cd6SAndrey A. Chernov gid_t egid; 689df8bae1dSRodney W. Grimes }; 690d2d3e875SBruce Evans #endif 691df8bae1dSRodney W. Grimes /* ARGSUSED */ 69226f9a767SRodney W. Grimes int 693e876c909SAndrey A. Chernov setregid(p, uap, retval) 694df8bae1dSRodney W. Grimes register struct proc *p; 695df8bae1dSRodney W. Grimes struct setregid_args *uap; 696df8bae1dSRodney W. Grimes int *retval; 697df8bae1dSRodney W. Grimes { 698df8bae1dSRodney W. Grimes register struct pcred *pc = p->p_cred; 69900999cd6SAndrey A. Chernov register gid_t rgid, egid; 700611d721eSAndrey A. Chernov int error; 701df8bae1dSRodney W. Grimes 70200999cd6SAndrey A. Chernov rgid = uap->rgid; 70300999cd6SAndrey A. Chernov egid = uap->egid; 70400999cd6SAndrey A. Chernov if ((rgid != (gid_t)-1 && rgid != pc->p_rgid && rgid != pc->p_svgid || 705b79c6a86SPeter Wemm egid != (gid_t)-1 && egid != pc->pc_ucred->cr_groups[0] && 706b79c6a86SPeter Wemm egid != pc->p_rgid && egid != pc->p_svgid) && 707611d721eSAndrey A. Chernov (error = suser(pc->pc_ucred, &p->p_acflag))) 708611d721eSAndrey A. Chernov return (error); 70900999cd6SAndrey A. Chernov 710a89a5370SPeter Wemm if (egid != (gid_t)-1 && pc->pc_ucred->cr_groups[0] != egid) { 71100999cd6SAndrey A. Chernov pc->pc_ucred = crcopy(pc->pc_ucred); 71200999cd6SAndrey A. Chernov pc->pc_ucred->cr_groups[0] = egid; 713a89a5370SPeter Wemm p->p_flag |= P_SUGID; 714a89a5370SPeter Wemm } 715a89a5370SPeter Wemm if (rgid != (gid_t)-1 && pc->p_rgid != rgid) { 71600999cd6SAndrey A. Chernov pc->p_rgid = rgid; 717a89a5370SPeter Wemm p->p_flag |= P_SUGID; 718a89a5370SPeter Wemm } 719b79c6a86SPeter Wemm if ((rgid != (gid_t)-1 || pc->pc_ucred->cr_groups[0] != pc->p_rgid) && 720b79c6a86SPeter Wemm pc->p_svgid != pc->pc_ucred->cr_groups[0]) { 7214bc8f31fSAndrey A. Chernov pc->p_svgid = pc->pc_ucred->cr_groups[0]; 7224bc8f31fSAndrey A. Chernov p->p_flag |= P_SUGID; 723a89a5370SPeter Wemm } 724611d721eSAndrey A. Chernov return (0); 725df8bae1dSRodney W. Grimes } 726df8bae1dSRodney W. Grimes 727b67cbc65SPeter Wemm #ifndef _SYS_SYSPROTO_H_ 728b67cbc65SPeter Wemm struct issetugid_args { 729b67cbc65SPeter Wemm int dummy; 730b67cbc65SPeter Wemm }; 731b67cbc65SPeter Wemm #endif 732b67cbc65SPeter Wemm /* ARGSUSED */ 733b67cbc65SPeter Wemm int 734b67cbc65SPeter Wemm issetugid(p, uap, retval) 735b67cbc65SPeter Wemm register struct proc *p; 736b67cbc65SPeter Wemm struct issetugid_args *uap; 737b67cbc65SPeter Wemm int *retval; 738b67cbc65SPeter Wemm { 739b67cbc65SPeter Wemm /* 740b67cbc65SPeter Wemm * Note: OpenBSD sets a P_SUGIDEXEC flag set at execve() time, 741b67cbc65SPeter Wemm * we use P_SUGID because we consider changing the owners as 742b67cbc65SPeter Wemm * "tainting" as well. 743b67cbc65SPeter Wemm * This is significant for procs that start as root and "become" 744b67cbc65SPeter Wemm * a user without an exec - programs cannot know *everything* 745b67cbc65SPeter Wemm * that libc *might* have put in their data segment. 746b67cbc65SPeter Wemm */ 747b67cbc65SPeter Wemm if (p->p_flag & P_SUGID) 748b67cbc65SPeter Wemm return (1); 749b67cbc65SPeter Wemm return (0); 750b67cbc65SPeter Wemm } 751b67cbc65SPeter Wemm 752df8bae1dSRodney W. Grimes /* 753df8bae1dSRodney W. Grimes * Check if gid is a member of the group set. 754df8bae1dSRodney W. Grimes */ 75526f9a767SRodney W. Grimes int 756df8bae1dSRodney W. Grimes groupmember(gid, cred) 757df8bae1dSRodney W. Grimes gid_t gid; 758df8bae1dSRodney W. Grimes register struct ucred *cred; 759df8bae1dSRodney W. Grimes { 760df8bae1dSRodney W. Grimes register gid_t *gp; 761df8bae1dSRodney W. Grimes gid_t *egp; 762df8bae1dSRodney W. Grimes 763df8bae1dSRodney W. Grimes egp = &(cred->cr_groups[cred->cr_ngroups]); 764df8bae1dSRodney W. Grimes for (gp = cred->cr_groups; gp < egp; gp++) 765df8bae1dSRodney W. Grimes if (*gp == gid) 766df8bae1dSRodney W. Grimes return (1); 767df8bae1dSRodney W. Grimes return (0); 768df8bae1dSRodney W. Grimes } 769df8bae1dSRodney W. Grimes 770df8bae1dSRodney W. Grimes /* 771df8bae1dSRodney W. Grimes * Test whether the specified credentials imply "super-user" 772df8bae1dSRodney W. Grimes * privilege; if so, and we have accounting info, set the flag 773df8bae1dSRodney W. Grimes * indicating use of super-powers. 774df8bae1dSRodney W. Grimes * Returns 0 or error. 775df8bae1dSRodney W. Grimes */ 77626f9a767SRodney W. Grimes int 777df8bae1dSRodney W. Grimes suser(cred, acflag) 778df8bae1dSRodney W. Grimes struct ucred *cred; 779453de7daSBruce Evans u_short *acflag; 780df8bae1dSRodney W. Grimes { 781df8bae1dSRodney W. Grimes if (cred->cr_uid == 0) { 782df8bae1dSRodney W. Grimes if (acflag) 783df8bae1dSRodney W. Grimes *acflag |= ASU; 784df8bae1dSRodney W. Grimes return (0); 785df8bae1dSRodney W. Grimes } 786df8bae1dSRodney W. Grimes return (EPERM); 787df8bae1dSRodney W. Grimes } 788df8bae1dSRodney W. Grimes 789df8bae1dSRodney W. Grimes /* 790df8bae1dSRodney W. Grimes * Allocate a zeroed cred structure. 791df8bae1dSRodney W. Grimes */ 792df8bae1dSRodney W. Grimes struct ucred * 793df8bae1dSRodney W. Grimes crget() 794df8bae1dSRodney W. Grimes { 795df8bae1dSRodney W. Grimes register struct ucred *cr; 796df8bae1dSRodney W. Grimes 797df8bae1dSRodney W. Grimes MALLOC(cr, struct ucred *, sizeof(*cr), M_CRED, M_WAITOK); 798df8bae1dSRodney W. Grimes bzero((caddr_t)cr, sizeof(*cr)); 799df8bae1dSRodney W. Grimes cr->cr_ref = 1; 800df8bae1dSRodney W. Grimes return (cr); 801df8bae1dSRodney W. Grimes } 802df8bae1dSRodney W. Grimes 803df8bae1dSRodney W. Grimes /* 804df8bae1dSRodney W. Grimes * Free a cred structure. 805df8bae1dSRodney W. Grimes * Throws away space when ref count gets to 0. 806df8bae1dSRodney W. Grimes */ 80726f9a767SRodney W. Grimes void 808df8bae1dSRodney W. Grimes crfree(cr) 809df8bae1dSRodney W. Grimes struct ucred *cr; 810df8bae1dSRodney W. Grimes { 811df8bae1dSRodney W. Grimes int s; 812df8bae1dSRodney W. Grimes 813df8bae1dSRodney W. Grimes s = splimp(); /* ??? */ 814df8bae1dSRodney W. Grimes if (--cr->cr_ref == 0) 815df8bae1dSRodney W. Grimes FREE((caddr_t)cr, M_CRED); 816df8bae1dSRodney W. Grimes (void) splx(s); 817df8bae1dSRodney W. Grimes } 818df8bae1dSRodney W. Grimes 819df8bae1dSRodney W. Grimes /* 820df8bae1dSRodney W. Grimes * Copy cred structure to a new one and free the old one. 821df8bae1dSRodney W. Grimes */ 822df8bae1dSRodney W. Grimes struct ucred * 823df8bae1dSRodney W. Grimes crcopy(cr) 824df8bae1dSRodney W. Grimes struct ucred *cr; 825df8bae1dSRodney W. Grimes { 826df8bae1dSRodney W. Grimes struct ucred *newcr; 827df8bae1dSRodney W. Grimes 828df8bae1dSRodney W. Grimes if (cr->cr_ref == 1) 829df8bae1dSRodney W. Grimes return (cr); 830df8bae1dSRodney W. Grimes newcr = crget(); 831df8bae1dSRodney W. Grimes *newcr = *cr; 832df8bae1dSRodney W. Grimes crfree(cr); 833df8bae1dSRodney W. Grimes newcr->cr_ref = 1; 834df8bae1dSRodney W. Grimes return (newcr); 835df8bae1dSRodney W. Grimes } 836df8bae1dSRodney W. Grimes 837df8bae1dSRodney W. Grimes /* 838df8bae1dSRodney W. Grimes * Dup cred struct to a new held one. 839df8bae1dSRodney W. Grimes */ 840df8bae1dSRodney W. Grimes struct ucred * 841df8bae1dSRodney W. Grimes crdup(cr) 842df8bae1dSRodney W. Grimes struct ucred *cr; 843df8bae1dSRodney W. Grimes { 844df8bae1dSRodney W. Grimes struct ucred *newcr; 845df8bae1dSRodney W. Grimes 846df8bae1dSRodney W. Grimes newcr = crget(); 847df8bae1dSRodney W. Grimes *newcr = *cr; 848df8bae1dSRodney W. Grimes newcr->cr_ref = 1; 849df8bae1dSRodney W. Grimes return (newcr); 850df8bae1dSRodney W. Grimes } 851df8bae1dSRodney W. Grimes 852df8bae1dSRodney W. Grimes /* 853df8bae1dSRodney W. Grimes * Get login name, if available. 854df8bae1dSRodney W. Grimes */ 855d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 856df8bae1dSRodney W. Grimes struct getlogin_args { 857df8bae1dSRodney W. Grimes char *namebuf; 858df8bae1dSRodney W. Grimes u_int namelen; 859df8bae1dSRodney W. Grimes }; 860d2d3e875SBruce Evans #endif 861df8bae1dSRodney W. Grimes /* ARGSUSED */ 86226f9a767SRodney W. Grimes int 863df8bae1dSRodney W. Grimes getlogin(p, uap, retval) 864df8bae1dSRodney W. Grimes struct proc *p; 865df8bae1dSRodney W. Grimes struct getlogin_args *uap; 866df8bae1dSRodney W. Grimes int *retval; 867df8bae1dSRodney W. Grimes { 868df8bae1dSRodney W. Grimes 86930cf3ac4SAndrey A. Chernov if (uap->namelen > MAXLOGNAME) 87053490b76SAndrey A. Chernov uap->namelen = MAXLOGNAME; 871df8bae1dSRodney W. Grimes return (copyout((caddr_t) p->p_pgrp->pg_session->s_login, 872df8bae1dSRodney W. Grimes (caddr_t) uap->namebuf, uap->namelen)); 873df8bae1dSRodney W. Grimes } 874df8bae1dSRodney W. Grimes 875df8bae1dSRodney W. Grimes /* 876df8bae1dSRodney W. Grimes * Set login name. 877df8bae1dSRodney W. Grimes */ 878d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 879df8bae1dSRodney W. Grimes struct setlogin_args { 880df8bae1dSRodney W. Grimes char *namebuf; 881df8bae1dSRodney W. Grimes }; 882d2d3e875SBruce Evans #endif 883df8bae1dSRodney W. Grimes /* ARGSUSED */ 88426f9a767SRodney W. Grimes int 885df8bae1dSRodney W. Grimes setlogin(p, uap, retval) 886df8bae1dSRodney W. Grimes struct proc *p; 887df8bae1dSRodney W. Grimes struct setlogin_args *uap; 888df8bae1dSRodney W. Grimes int *retval; 889df8bae1dSRodney W. Grimes { 890df8bae1dSRodney W. Grimes int error; 891964ca0caSAndrey A. Chernov char logintmp[MAXLOGNAME]; 892df8bae1dSRodney W. Grimes 893bb56ec4aSPoul-Henning Kamp if ((error = suser(p->p_ucred, &p->p_acflag))) 894df8bae1dSRodney W. Grimes return (error); 895184989c2SDavid Nugent error = copyinstr((caddr_t) uap->namebuf, (caddr_t) logintmp, 896184989c2SDavid Nugent sizeof(logintmp), (u_int *)0); 897df8bae1dSRodney W. Grimes if (error == ENAMETOOLONG) 898df8bae1dSRodney W. Grimes error = EINVAL; 899184989c2SDavid Nugent else if (!error) 900184989c2SDavid Nugent (void) memcpy(p->p_pgrp->pg_session->s_login, logintmp, 901964ca0caSAndrey A. Chernov sizeof(logintmp)); 902df8bae1dSRodney W. Grimes return (error); 903df8bae1dSRodney W. Grimes } 904