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 39611d721eSAndrey A. Chernov * $Id: kern_prot.c,v 1.8 1995/04/27 19:23:24 ache 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> 49df8bae1dSRodney W. Grimes #include <sys/ucred.h> 50df8bae1dSRodney W. Grimes #include <sys/proc.h> 51df8bae1dSRodney W. Grimes #include <sys/timeb.h> 52df8bae1dSRodney W. Grimes #include <sys/times.h> 53df8bae1dSRodney W. Grimes #include <sys/malloc.h> 54df8bae1dSRodney W. Grimes 55df8bae1dSRodney W. Grimes struct args { 56df8bae1dSRodney W. Grimes int dummy; 57df8bae1dSRodney W. Grimes }; 58df8bae1dSRodney W. Grimes 59df8bae1dSRodney W. Grimes /* ARGSUSED */ 6026f9a767SRodney W. Grimes int 61df8bae1dSRodney W. Grimes getpid(p, uap, retval) 62df8bae1dSRodney W. Grimes struct proc *p; 63df8bae1dSRodney W. Grimes struct args *uap; 64df8bae1dSRodney W. Grimes int *retval; 65df8bae1dSRodney W. Grimes { 66df8bae1dSRodney W. Grimes 67df8bae1dSRodney W. Grimes *retval = p->p_pid; 68df8bae1dSRodney W. Grimes #if defined(COMPAT_43) || defined(COMPAT_SUNOS) 69df8bae1dSRodney W. Grimes retval[1] = p->p_pptr->p_pid; 70df8bae1dSRodney W. Grimes #endif 71df8bae1dSRodney W. Grimes return (0); 72df8bae1dSRodney W. Grimes } 73df8bae1dSRodney W. Grimes 74df8bae1dSRodney W. Grimes /* ARGSUSED */ 7526f9a767SRodney W. Grimes int 76df8bae1dSRodney W. Grimes getppid(p, uap, retval) 77df8bae1dSRodney W. Grimes struct proc *p; 78df8bae1dSRodney W. Grimes struct args *uap; 79df8bae1dSRodney W. Grimes int *retval; 80df8bae1dSRodney W. Grimes { 81df8bae1dSRodney W. Grimes 82df8bae1dSRodney W. Grimes *retval = p->p_pptr->p_pid; 83df8bae1dSRodney W. Grimes return (0); 84df8bae1dSRodney W. Grimes } 85df8bae1dSRodney W. Grimes 86df8bae1dSRodney W. Grimes /* Get process group ID; note that POSIX getpgrp takes no parameter */ 8726f9a767SRodney W. Grimes int 88df8bae1dSRodney W. Grimes getpgrp(p, uap, retval) 89df8bae1dSRodney W. Grimes struct proc *p; 90df8bae1dSRodney W. Grimes struct args *uap; 91df8bae1dSRodney W. Grimes int *retval; 92df8bae1dSRodney W. Grimes { 93df8bae1dSRodney W. Grimes 94df8bae1dSRodney W. Grimes *retval = p->p_pgrp->pg_id; 95df8bae1dSRodney W. Grimes return (0); 96df8bae1dSRodney W. Grimes } 97df8bae1dSRodney W. Grimes 98df8bae1dSRodney W. Grimes /* ARGSUSED */ 9926f9a767SRodney W. Grimes int 100df8bae1dSRodney W. Grimes getuid(p, uap, retval) 101df8bae1dSRodney W. Grimes struct proc *p; 102df8bae1dSRodney W. Grimes struct args *uap; 103df8bae1dSRodney W. Grimes int *retval; 104df8bae1dSRodney W. Grimes { 105df8bae1dSRodney W. Grimes 106df8bae1dSRodney W. Grimes *retval = p->p_cred->p_ruid; 107df8bae1dSRodney W. Grimes #if defined(COMPAT_43) || defined(COMPAT_SUNOS) 108df8bae1dSRodney W. Grimes retval[1] = p->p_ucred->cr_uid; 109df8bae1dSRodney W. Grimes #endif 110df8bae1dSRodney W. Grimes return (0); 111df8bae1dSRodney W. Grimes } 112df8bae1dSRodney W. Grimes 113df8bae1dSRodney W. Grimes /* ARGSUSED */ 11426f9a767SRodney W. Grimes int 115df8bae1dSRodney W. Grimes geteuid(p, uap, retval) 116df8bae1dSRodney W. Grimes struct proc *p; 117df8bae1dSRodney W. Grimes struct args *uap; 118df8bae1dSRodney W. Grimes int *retval; 119df8bae1dSRodney W. Grimes { 120df8bae1dSRodney W. Grimes 121df8bae1dSRodney W. Grimes *retval = p->p_ucred->cr_uid; 122df8bae1dSRodney W. Grimes return (0); 123df8bae1dSRodney W. Grimes } 124df8bae1dSRodney W. Grimes 125df8bae1dSRodney W. Grimes /* ARGSUSED */ 12626f9a767SRodney W. Grimes int 127df8bae1dSRodney W. Grimes getgid(p, uap, retval) 128df8bae1dSRodney W. Grimes struct proc *p; 129df8bae1dSRodney W. Grimes struct args *uap; 130df8bae1dSRodney W. Grimes int *retval; 131df8bae1dSRodney W. Grimes { 132df8bae1dSRodney W. Grimes 133df8bae1dSRodney W. Grimes *retval = p->p_cred->p_rgid; 134df8bae1dSRodney W. Grimes #if defined(COMPAT_43) || defined(COMPAT_SUNOS) 135df8bae1dSRodney W. Grimes retval[1] = p->p_ucred->cr_groups[0]; 136df8bae1dSRodney W. Grimes #endif 137df8bae1dSRodney W. Grimes return (0); 138df8bae1dSRodney W. Grimes } 139df8bae1dSRodney W. Grimes 140df8bae1dSRodney W. Grimes /* 141df8bae1dSRodney W. Grimes * Get effective group ID. The "egid" is groups[0], and could be obtained 142df8bae1dSRodney W. Grimes * via getgroups. This syscall exists because it is somewhat painful to do 143df8bae1dSRodney W. Grimes * correctly in a library function. 144df8bae1dSRodney W. Grimes */ 145df8bae1dSRodney W. Grimes /* ARGSUSED */ 14626f9a767SRodney W. Grimes int 147df8bae1dSRodney W. Grimes getegid(p, uap, retval) 148df8bae1dSRodney W. Grimes struct proc *p; 149df8bae1dSRodney W. Grimes struct args *uap; 150df8bae1dSRodney W. Grimes int *retval; 151df8bae1dSRodney W. Grimes { 152df8bae1dSRodney W. Grimes 153df8bae1dSRodney W. Grimes *retval = p->p_ucred->cr_groups[0]; 154df8bae1dSRodney W. Grimes return (0); 155df8bae1dSRodney W. Grimes } 156df8bae1dSRodney W. Grimes 157df8bae1dSRodney W. Grimes struct getgroups_args { 158df8bae1dSRodney W. Grimes u_int gidsetsize; 159df8bae1dSRodney W. Grimes gid_t *gidset; 160df8bae1dSRodney W. Grimes }; 16126f9a767SRodney W. Grimes int 162df8bae1dSRodney W. Grimes getgroups(p, uap, retval) 163df8bae1dSRodney W. Grimes struct proc *p; 164df8bae1dSRodney W. Grimes register struct getgroups_args *uap; 165df8bae1dSRodney W. Grimes int *retval; 166df8bae1dSRodney W. Grimes { 167df8bae1dSRodney W. Grimes register struct pcred *pc = p->p_cred; 168df8bae1dSRodney W. Grimes register u_int ngrp; 169df8bae1dSRodney W. Grimes int error; 170df8bae1dSRodney W. Grimes 171df8bae1dSRodney W. Grimes if ((ngrp = uap->gidsetsize) == 0) { 172df8bae1dSRodney W. Grimes *retval = pc->pc_ucred->cr_ngroups; 173df8bae1dSRodney W. Grimes return (0); 174df8bae1dSRodney W. Grimes } 175df8bae1dSRodney W. Grimes if (ngrp < pc->pc_ucred->cr_ngroups) 176df8bae1dSRodney W. Grimes return (EINVAL); 177df8bae1dSRodney W. Grimes ngrp = pc->pc_ucred->cr_ngroups; 178bb56ec4aSPoul-Henning Kamp if ((error = copyout((caddr_t)pc->pc_ucred->cr_groups, 179bb56ec4aSPoul-Henning Kamp (caddr_t)uap->gidset, ngrp * sizeof(gid_t)))) 180df8bae1dSRodney W. Grimes return (error); 181df8bae1dSRodney W. Grimes *retval = ngrp; 182df8bae1dSRodney W. Grimes return (0); 183df8bae1dSRodney W. Grimes } 184df8bae1dSRodney W. Grimes 185df8bae1dSRodney W. Grimes /* ARGSUSED */ 18626f9a767SRodney W. Grimes int 187df8bae1dSRodney W. Grimes setsid(p, uap, retval) 188df8bae1dSRodney W. Grimes register struct proc *p; 189df8bae1dSRodney W. Grimes struct args *uap; 190df8bae1dSRodney W. Grimes int *retval; 191df8bae1dSRodney W. Grimes { 192df8bae1dSRodney W. Grimes 193df8bae1dSRodney W. Grimes if (p->p_pgid == p->p_pid || pgfind(p->p_pid)) { 194df8bae1dSRodney W. Grimes return (EPERM); 195df8bae1dSRodney W. Grimes } else { 196df8bae1dSRodney W. Grimes (void)enterpgrp(p, p->p_pid, 1); 197df8bae1dSRodney W. Grimes *retval = p->p_pid; 198df8bae1dSRodney W. Grimes return (0); 199df8bae1dSRodney W. Grimes } 200df8bae1dSRodney W. Grimes } 201df8bae1dSRodney W. Grimes 202df8bae1dSRodney W. Grimes /* 203df8bae1dSRodney W. Grimes * set process group (setpgid/old setpgrp) 204df8bae1dSRodney W. Grimes * 205df8bae1dSRodney W. Grimes * caller does setpgid(targpid, targpgid) 206df8bae1dSRodney W. Grimes * 207df8bae1dSRodney W. Grimes * pid must be caller or child of caller (ESRCH) 208df8bae1dSRodney W. Grimes * if a child 209df8bae1dSRodney W. Grimes * pid must be in same session (EPERM) 210df8bae1dSRodney W. Grimes * pid can't have done an exec (EACCES) 211df8bae1dSRodney W. Grimes * if pgid != pid 212df8bae1dSRodney W. Grimes * there must exist some pid in same session having pgid (EPERM) 213df8bae1dSRodney W. Grimes * pid must not be session leader (EPERM) 214df8bae1dSRodney W. Grimes */ 215df8bae1dSRodney W. Grimes struct setpgid_args { 216df8bae1dSRodney W. Grimes int pid; /* target process id */ 217df8bae1dSRodney W. Grimes int pgid; /* target pgrp id */ 218df8bae1dSRodney W. Grimes }; 219df8bae1dSRodney W. Grimes /* ARGSUSED */ 22026f9a767SRodney W. Grimes int 221df8bae1dSRodney W. Grimes setpgid(curp, uap, retval) 222df8bae1dSRodney W. Grimes struct proc *curp; 223df8bae1dSRodney W. Grimes register struct setpgid_args *uap; 224df8bae1dSRodney W. Grimes int *retval; 225df8bae1dSRodney W. Grimes { 226df8bae1dSRodney W. Grimes register struct proc *targp; /* target process */ 227df8bae1dSRodney W. Grimes register struct pgrp *pgrp; /* target pgrp */ 228df8bae1dSRodney W. Grimes 229df8bae1dSRodney W. Grimes if (uap->pid != 0 && uap->pid != curp->p_pid) { 230df8bae1dSRodney W. Grimes if ((targp = pfind(uap->pid)) == 0 || !inferior(targp)) 231df8bae1dSRodney W. Grimes return (ESRCH); 232df8bae1dSRodney W. Grimes if (targp->p_session != curp->p_session) 233df8bae1dSRodney W. Grimes return (EPERM); 234df8bae1dSRodney W. Grimes if (targp->p_flag & P_EXEC) 235df8bae1dSRodney W. Grimes return (EACCES); 236df8bae1dSRodney W. Grimes } else 237df8bae1dSRodney W. Grimes targp = curp; 238df8bae1dSRodney W. Grimes if (SESS_LEADER(targp)) 239df8bae1dSRodney W. Grimes return (EPERM); 240df8bae1dSRodney W. Grimes if (uap->pgid == 0) 241df8bae1dSRodney W. Grimes uap->pgid = targp->p_pid; 242df8bae1dSRodney W. Grimes else if (uap->pgid != targp->p_pid) 243df8bae1dSRodney W. Grimes if ((pgrp = pgfind(uap->pgid)) == 0 || 244df8bae1dSRodney W. Grimes pgrp->pg_session != curp->p_session) 245df8bae1dSRodney W. Grimes return (EPERM); 246df8bae1dSRodney W. Grimes return (enterpgrp(targp, uap->pgid, 0)); 247df8bae1dSRodney W. Grimes } 248df8bae1dSRodney W. Grimes 249df8bae1dSRodney W. Grimes struct setuid_args { 250df8bae1dSRodney W. Grimes uid_t uid; 251df8bae1dSRodney W. Grimes }; 252df8bae1dSRodney W. Grimes /* ARGSUSED */ 25326f9a767SRodney W. Grimes int 254df8bae1dSRodney W. Grimes setuid(p, uap, retval) 255df8bae1dSRodney W. Grimes struct proc *p; 256df8bae1dSRodney W. Grimes struct setuid_args *uap; 257df8bae1dSRodney W. Grimes int *retval; 258df8bae1dSRodney W. Grimes { 259df8bae1dSRodney W. Grimes register struct pcred *pc = p->p_cred; 260df8bae1dSRodney W. Grimes register uid_t uid; 261df8bae1dSRodney W. Grimes int error; 262df8bae1dSRodney W. Grimes 263df8bae1dSRodney W. Grimes uid = uap->uid; 264df8bae1dSRodney W. Grimes if (uid != pc->p_ruid && 265df8bae1dSRodney W. Grimes (error = suser(pc->pc_ucred, &p->p_acflag))) 266df8bae1dSRodney W. Grimes return (error); 267df8bae1dSRodney W. Grimes /* 268df8bae1dSRodney W. Grimes * Everything's okay, do it. 269df8bae1dSRodney W. Grimes * Transfer proc count to new user. 270df8bae1dSRodney W. Grimes * Copy credentials so other references do not see our changes. 271df8bae1dSRodney W. Grimes */ 272df8bae1dSRodney W. Grimes (void)chgproccnt(pc->p_ruid, -1); 273df8bae1dSRodney W. Grimes (void)chgproccnt(uid, 1); 274df8bae1dSRodney W. Grimes pc->pc_ucred = crcopy(pc->pc_ucred); 275df8bae1dSRodney W. Grimes pc->pc_ucred->cr_uid = uid; 276df8bae1dSRodney W. Grimes pc->p_ruid = uid; 277df8bae1dSRodney W. Grimes pc->p_svuid = uid; 278df8bae1dSRodney W. Grimes p->p_flag |= P_SUGID; 279df8bae1dSRodney W. Grimes return (0); 280df8bae1dSRodney W. Grimes } 281df8bae1dSRodney W. Grimes 282df8bae1dSRodney W. Grimes struct seteuid_args { 283df8bae1dSRodney W. Grimes uid_t euid; 284df8bae1dSRodney W. Grimes }; 285df8bae1dSRodney W. Grimes /* ARGSUSED */ 28626f9a767SRodney W. Grimes int 287df8bae1dSRodney W. Grimes seteuid(p, uap, retval) 288df8bae1dSRodney W. Grimes struct proc *p; 289df8bae1dSRodney W. Grimes struct seteuid_args *uap; 290df8bae1dSRodney W. Grimes int *retval; 291df8bae1dSRodney W. Grimes { 292df8bae1dSRodney W. Grimes register struct pcred *pc = p->p_cred; 293df8bae1dSRodney W. Grimes register uid_t euid; 294df8bae1dSRodney W. Grimes int error; 295df8bae1dSRodney W. Grimes 296df8bae1dSRodney W. Grimes euid = uap->euid; 297df8bae1dSRodney W. Grimes if (euid != pc->p_ruid && euid != pc->p_svuid && 298df8bae1dSRodney W. Grimes (error = suser(pc->pc_ucred, &p->p_acflag))) 299df8bae1dSRodney W. Grimes return (error); 300df8bae1dSRodney W. Grimes /* 301df8bae1dSRodney W. Grimes * Everything's okay, do it. Copy credentials so other references do 302df8bae1dSRodney W. Grimes * not see our changes. 303df8bae1dSRodney W. Grimes */ 304df8bae1dSRodney W. Grimes pc->pc_ucred = crcopy(pc->pc_ucred); 305df8bae1dSRodney W. Grimes pc->pc_ucred->cr_uid = euid; 306df8bae1dSRodney W. Grimes p->p_flag |= P_SUGID; 307df8bae1dSRodney W. Grimes return (0); 308df8bae1dSRodney W. Grimes } 309df8bae1dSRodney W. Grimes 310df8bae1dSRodney W. Grimes struct setgid_args { 311df8bae1dSRodney W. Grimes gid_t gid; 312df8bae1dSRodney W. Grimes }; 313df8bae1dSRodney W. Grimes /* ARGSUSED */ 31426f9a767SRodney W. Grimes int 315df8bae1dSRodney W. Grimes setgid(p, uap, retval) 316df8bae1dSRodney W. Grimes struct proc *p; 317df8bae1dSRodney W. Grimes struct setgid_args *uap; 318df8bae1dSRodney W. Grimes int *retval; 319df8bae1dSRodney W. Grimes { 320df8bae1dSRodney W. Grimes register struct pcred *pc = p->p_cred; 321df8bae1dSRodney W. Grimes register gid_t gid; 322df8bae1dSRodney W. Grimes int error; 323df8bae1dSRodney W. Grimes 324df8bae1dSRodney W. Grimes gid = uap->gid; 325df8bae1dSRodney W. Grimes if (gid != pc->p_rgid && (error = suser(pc->pc_ucred, &p->p_acflag))) 326df8bae1dSRodney W. Grimes return (error); 327df8bae1dSRodney W. Grimes pc->pc_ucred = crcopy(pc->pc_ucred); 328df8bae1dSRodney W. Grimes pc->pc_ucred->cr_groups[0] = gid; 329df8bae1dSRodney W. Grimes pc->p_rgid = gid; 330df8bae1dSRodney W. Grimes pc->p_svgid = gid; /* ??? */ 331df8bae1dSRodney W. Grimes p->p_flag |= P_SUGID; 332df8bae1dSRodney W. Grimes return (0); 333df8bae1dSRodney W. Grimes } 334df8bae1dSRodney W. Grimes 335df8bae1dSRodney W. Grimes struct setegid_args { 336df8bae1dSRodney W. Grimes gid_t egid; 337df8bae1dSRodney W. Grimes }; 338df8bae1dSRodney W. Grimes /* ARGSUSED */ 33926f9a767SRodney W. Grimes int 340df8bae1dSRodney W. Grimes setegid(p, uap, retval) 341df8bae1dSRodney W. Grimes struct proc *p; 342df8bae1dSRodney W. Grimes struct setegid_args *uap; 343df8bae1dSRodney W. Grimes int *retval; 344df8bae1dSRodney W. Grimes { 345df8bae1dSRodney W. Grimes register struct pcred *pc = p->p_cred; 346df8bae1dSRodney W. Grimes register gid_t egid; 347df8bae1dSRodney W. Grimes int error; 348df8bae1dSRodney W. Grimes 349df8bae1dSRodney W. Grimes egid = uap->egid; 350df8bae1dSRodney W. Grimes if (egid != pc->p_rgid && egid != pc->p_svgid && 351df8bae1dSRodney W. Grimes (error = suser(pc->pc_ucred, &p->p_acflag))) 352df8bae1dSRodney W. Grimes return (error); 353df8bae1dSRodney W. Grimes pc->pc_ucred = crcopy(pc->pc_ucred); 354df8bae1dSRodney W. Grimes pc->pc_ucred->cr_groups[0] = egid; 355df8bae1dSRodney W. Grimes p->p_flag |= P_SUGID; 356df8bae1dSRodney W. Grimes return (0); 357df8bae1dSRodney W. Grimes } 358df8bae1dSRodney W. Grimes 359df8bae1dSRodney W. Grimes struct setgroups_args { 360df8bae1dSRodney W. Grimes u_int gidsetsize; 361df8bae1dSRodney W. Grimes gid_t *gidset; 362df8bae1dSRodney W. Grimes }; 363df8bae1dSRodney W. Grimes /* ARGSUSED */ 36426f9a767SRodney W. Grimes int 365df8bae1dSRodney W. Grimes setgroups(p, uap, retval) 366df8bae1dSRodney W. Grimes struct proc *p; 367df8bae1dSRodney W. Grimes struct setgroups_args *uap; 368df8bae1dSRodney W. Grimes int *retval; 369df8bae1dSRodney W. Grimes { 370df8bae1dSRodney W. Grimes register struct pcred *pc = p->p_cred; 371df8bae1dSRodney W. Grimes register u_int ngrp; 372df8bae1dSRodney W. Grimes int error; 373df8bae1dSRodney W. Grimes 374bb56ec4aSPoul-Henning Kamp if ((error = suser(pc->pc_ucred, &p->p_acflag))) 375df8bae1dSRodney W. Grimes return (error); 376df8bae1dSRodney W. Grimes if ((ngrp = uap->gidsetsize) > NGROUPS) 377df8bae1dSRodney W. Grimes return (EINVAL); 378df8bae1dSRodney W. Grimes pc->pc_ucred = crcopy(pc->pc_ucred); 379bb56ec4aSPoul-Henning Kamp if ((error = copyin((caddr_t)uap->gidset, 380bb56ec4aSPoul-Henning Kamp (caddr_t)pc->pc_ucred->cr_groups, ngrp * sizeof(gid_t)))) 381df8bae1dSRodney W. Grimes return (error); 382df8bae1dSRodney W. Grimes pc->pc_ucred->cr_ngroups = ngrp; 383df8bae1dSRodney W. Grimes p->p_flag |= P_SUGID; 384df8bae1dSRodney W. Grimes return (0); 385df8bae1dSRodney W. Grimes } 386df8bae1dSRodney W. Grimes 387df8bae1dSRodney W. Grimes struct setreuid_args { 388df8bae1dSRodney W. Grimes int ruid; 389df8bae1dSRodney W. Grimes int euid; 390df8bae1dSRodney W. Grimes }; 391df8bae1dSRodney W. Grimes /* ARGSUSED */ 39226f9a767SRodney W. Grimes int 393e876c909SAndrey A. Chernov setreuid(p, uap, retval) 394df8bae1dSRodney W. Grimes register struct proc *p; 395df8bae1dSRodney W. Grimes struct setreuid_args *uap; 396df8bae1dSRodney W. Grimes int *retval; 397df8bae1dSRodney W. Grimes { 398df8bae1dSRodney W. Grimes register struct pcred *pc = p->p_cred; 399df8bae1dSRodney W. Grimes struct seteuid_args args; 400611d721eSAndrey A. Chernov int error; 401df8bae1dSRodney W. Grimes 402df8bae1dSRodney W. Grimes if (uap->ruid != (uid_t)-1 && uap->ruid != pc->p_ruid && 4034bc8f31fSAndrey A. Chernov uap->ruid != pc->p_svuid && 404611d721eSAndrey A. Chernov (error = suser(pc->pc_ucred, &p->p_acflag))) 405611d721eSAndrey A. Chernov return (error); 4064bc8f31fSAndrey A. Chernov if (uap->euid != (uid_t)-1 && pc->pc_ucred->cr_uid != uap->euid) { 407df8bae1dSRodney W. Grimes args.euid = uap->euid; 408611d721eSAndrey A. Chernov if ((error = seteuid(p, &args, retval))) 409611d721eSAndrey A. Chernov return (error); 410611d721eSAndrey A. Chernov if (pc->pc_ucred->cr_uid != pc->p_ruid) 4114bc8f31fSAndrey A. Chernov pc->p_svuid = pc->pc_ucred->cr_uid; 412611d721eSAndrey A. Chernov } 413611d721eSAndrey A. Chernov if (uap->ruid != (uid_t)-1 && uap->ruid != pc->p_ruid) { 4144bc8f31fSAndrey A. Chernov (void)chgproccnt(pc->p_ruid, -1); 4154bc8f31fSAndrey A. Chernov (void)chgproccnt(uap->ruid, 1); 4164bc8f31fSAndrey A. Chernov pc->p_ruid = uap->ruid; 4174bc8f31fSAndrey A. Chernov pc->p_svuid = pc->pc_ucred->cr_uid; 4184bc8f31fSAndrey A. Chernov p->p_flag |= P_SUGID; 4194bc8f31fSAndrey A. Chernov } 420611d721eSAndrey A. Chernov return (0); 421df8bae1dSRodney W. Grimes } 422df8bae1dSRodney W. Grimes 423df8bae1dSRodney W. Grimes struct setregid_args { 424df8bae1dSRodney W. Grimes int rgid; 425df8bae1dSRodney W. Grimes int egid; 426df8bae1dSRodney W. Grimes }; 427df8bae1dSRodney W. Grimes /* ARGSUSED */ 42826f9a767SRodney W. Grimes int 429e876c909SAndrey A. Chernov setregid(p, uap, retval) 430df8bae1dSRodney W. Grimes register struct proc *p; 431df8bae1dSRodney W. Grimes struct setregid_args *uap; 432df8bae1dSRodney W. Grimes int *retval; 433df8bae1dSRodney W. Grimes { 434df8bae1dSRodney W. Grimes register struct pcred *pc = p->p_cred; 435df8bae1dSRodney W. Grimes struct setegid_args args; 436611d721eSAndrey A. Chernov int error; 437df8bae1dSRodney W. Grimes 438df8bae1dSRodney W. Grimes if (uap->rgid != (gid_t)-1 && uap->rgid != pc->p_rgid && 4394bc8f31fSAndrey A. Chernov uap->rgid != pc->p_svgid && 440611d721eSAndrey A. Chernov (error = suser(pc->pc_ucred, &p->p_acflag))) 441611d721eSAndrey A. Chernov return (error); 4424bc8f31fSAndrey A. Chernov if (uap->egid != (gid_t)-1 && pc->pc_ucred->cr_groups[0] != uap->egid) { 443df8bae1dSRodney W. Grimes args.egid = uap->egid; 444611d721eSAndrey A. Chernov if ((error = setegid(p, &args, retval))) 445611d721eSAndrey A. Chernov return (error); 446611d721eSAndrey A. Chernov if (pc->pc_ucred->cr_groups[0] != pc->p_rgid) 4474bc8f31fSAndrey A. Chernov pc->p_svgid = pc->pc_ucred->cr_groups[0]; 448611d721eSAndrey A. Chernov } 449611d721eSAndrey A. Chernov if (uap->rgid != (gid_t)-1 && uap->rgid != pc->p_rgid) { 4504bc8f31fSAndrey A. Chernov pc->p_rgid = uap->rgid; 4514bc8f31fSAndrey A. Chernov pc->p_svgid = pc->pc_ucred->cr_groups[0]; 4524bc8f31fSAndrey A. Chernov p->p_flag |= P_SUGID; 4534bc8f31fSAndrey A. Chernov } 454611d721eSAndrey A. Chernov return (0); 455df8bae1dSRodney W. Grimes } 456df8bae1dSRodney W. Grimes 457df8bae1dSRodney W. Grimes /* 458df8bae1dSRodney W. Grimes * Check if gid is a member of the group set. 459df8bae1dSRodney W. Grimes */ 46026f9a767SRodney W. Grimes int 461df8bae1dSRodney W. Grimes groupmember(gid, cred) 462df8bae1dSRodney W. Grimes gid_t gid; 463df8bae1dSRodney W. Grimes register struct ucred *cred; 464df8bae1dSRodney W. Grimes { 465df8bae1dSRodney W. Grimes register gid_t *gp; 466df8bae1dSRodney W. Grimes gid_t *egp; 467df8bae1dSRodney W. Grimes 468df8bae1dSRodney W. Grimes egp = &(cred->cr_groups[cred->cr_ngroups]); 469df8bae1dSRodney W. Grimes for (gp = cred->cr_groups; gp < egp; gp++) 470df8bae1dSRodney W. Grimes if (*gp == gid) 471df8bae1dSRodney W. Grimes return (1); 472df8bae1dSRodney W. Grimes return (0); 473df8bae1dSRodney W. Grimes } 474df8bae1dSRodney W. Grimes 475df8bae1dSRodney W. Grimes /* 476df8bae1dSRodney W. Grimes * Test whether the specified credentials imply "super-user" 477df8bae1dSRodney W. Grimes * privilege; if so, and we have accounting info, set the flag 478df8bae1dSRodney W. Grimes * indicating use of super-powers. 479df8bae1dSRodney W. Grimes * Returns 0 or error. 480df8bae1dSRodney W. Grimes */ 48126f9a767SRodney W. Grimes int 482df8bae1dSRodney W. Grimes suser(cred, acflag) 483df8bae1dSRodney W. Grimes struct ucred *cred; 484453de7daSBruce Evans u_short *acflag; 485df8bae1dSRodney W. Grimes { 486df8bae1dSRodney W. Grimes if (cred->cr_uid == 0) { 487df8bae1dSRodney W. Grimes if (acflag) 488df8bae1dSRodney W. Grimes *acflag |= ASU; 489df8bae1dSRodney W. Grimes return (0); 490df8bae1dSRodney W. Grimes } 491df8bae1dSRodney W. Grimes return (EPERM); 492df8bae1dSRodney W. Grimes } 493df8bae1dSRodney W. Grimes 494df8bae1dSRodney W. Grimes /* 495df8bae1dSRodney W. Grimes * Allocate a zeroed cred structure. 496df8bae1dSRodney W. Grimes */ 497df8bae1dSRodney W. Grimes struct ucred * 498df8bae1dSRodney W. Grimes crget() 499df8bae1dSRodney W. Grimes { 500df8bae1dSRodney W. Grimes register struct ucred *cr; 501df8bae1dSRodney W. Grimes 502df8bae1dSRodney W. Grimes MALLOC(cr, struct ucred *, sizeof(*cr), M_CRED, M_WAITOK); 503df8bae1dSRodney W. Grimes bzero((caddr_t)cr, sizeof(*cr)); 504df8bae1dSRodney W. Grimes cr->cr_ref = 1; 505df8bae1dSRodney W. Grimes return (cr); 506df8bae1dSRodney W. Grimes } 507df8bae1dSRodney W. Grimes 508df8bae1dSRodney W. Grimes /* 509df8bae1dSRodney W. Grimes * Free a cred structure. 510df8bae1dSRodney W. Grimes * Throws away space when ref count gets to 0. 511df8bae1dSRodney W. Grimes */ 51226f9a767SRodney W. Grimes void 513df8bae1dSRodney W. Grimes crfree(cr) 514df8bae1dSRodney W. Grimes struct ucred *cr; 515df8bae1dSRodney W. Grimes { 516df8bae1dSRodney W. Grimes int s; 517df8bae1dSRodney W. Grimes 518df8bae1dSRodney W. Grimes s = splimp(); /* ??? */ 519df8bae1dSRodney W. Grimes if (--cr->cr_ref == 0) 520df8bae1dSRodney W. Grimes FREE((caddr_t)cr, M_CRED); 521df8bae1dSRodney W. Grimes (void) splx(s); 522df8bae1dSRodney W. Grimes } 523df8bae1dSRodney W. Grimes 524df8bae1dSRodney W. Grimes /* 525df8bae1dSRodney W. Grimes * Copy cred structure to a new one and free the old one. 526df8bae1dSRodney W. Grimes */ 527df8bae1dSRodney W. Grimes struct ucred * 528df8bae1dSRodney W. Grimes crcopy(cr) 529df8bae1dSRodney W. Grimes struct ucred *cr; 530df8bae1dSRodney W. Grimes { 531df8bae1dSRodney W. Grimes struct ucred *newcr; 532df8bae1dSRodney W. Grimes 533df8bae1dSRodney W. Grimes if (cr->cr_ref == 1) 534df8bae1dSRodney W. Grimes return (cr); 535df8bae1dSRodney W. Grimes newcr = crget(); 536df8bae1dSRodney W. Grimes *newcr = *cr; 537df8bae1dSRodney W. Grimes crfree(cr); 538df8bae1dSRodney W. Grimes newcr->cr_ref = 1; 539df8bae1dSRodney W. Grimes return (newcr); 540df8bae1dSRodney W. Grimes } 541df8bae1dSRodney W. Grimes 542df8bae1dSRodney W. Grimes /* 543df8bae1dSRodney W. Grimes * Dup cred struct to a new held one. 544df8bae1dSRodney W. Grimes */ 545df8bae1dSRodney W. Grimes struct ucred * 546df8bae1dSRodney W. Grimes crdup(cr) 547df8bae1dSRodney W. Grimes struct ucred *cr; 548df8bae1dSRodney W. Grimes { 549df8bae1dSRodney W. Grimes struct ucred *newcr; 550df8bae1dSRodney W. Grimes 551df8bae1dSRodney W. Grimes newcr = crget(); 552df8bae1dSRodney W. Grimes *newcr = *cr; 553df8bae1dSRodney W. Grimes newcr->cr_ref = 1; 554df8bae1dSRodney W. Grimes return (newcr); 555df8bae1dSRodney W. Grimes } 556df8bae1dSRodney W. Grimes 557df8bae1dSRodney W. Grimes /* 558df8bae1dSRodney W. Grimes * Get login name, if available. 559df8bae1dSRodney W. Grimes */ 560df8bae1dSRodney W. Grimes struct getlogin_args { 561df8bae1dSRodney W. Grimes char *namebuf; 562df8bae1dSRodney W. Grimes u_int namelen; 563df8bae1dSRodney W. Grimes }; 564df8bae1dSRodney W. Grimes /* ARGSUSED */ 56526f9a767SRodney W. Grimes int 566df8bae1dSRodney W. Grimes getlogin(p, uap, retval) 567df8bae1dSRodney W. Grimes struct proc *p; 568df8bae1dSRodney W. Grimes struct getlogin_args *uap; 569df8bae1dSRodney W. Grimes int *retval; 570df8bae1dSRodney W. Grimes { 571df8bae1dSRodney W. Grimes 572df8bae1dSRodney W. Grimes if (uap->namelen > sizeof (p->p_pgrp->pg_session->s_login)) 573df8bae1dSRodney W. Grimes uap->namelen = sizeof (p->p_pgrp->pg_session->s_login); 574df8bae1dSRodney W. Grimes return (copyout((caddr_t) p->p_pgrp->pg_session->s_login, 575df8bae1dSRodney W. Grimes (caddr_t) uap->namebuf, uap->namelen)); 576df8bae1dSRodney W. Grimes } 577df8bae1dSRodney W. Grimes 578df8bae1dSRodney W. Grimes /* 579df8bae1dSRodney W. Grimes * Set login name. 580df8bae1dSRodney W. Grimes */ 581df8bae1dSRodney W. Grimes struct setlogin_args { 582df8bae1dSRodney W. Grimes char *namebuf; 583df8bae1dSRodney W. Grimes }; 584df8bae1dSRodney W. Grimes /* ARGSUSED */ 58526f9a767SRodney W. Grimes int 586df8bae1dSRodney W. Grimes setlogin(p, uap, retval) 587df8bae1dSRodney W. Grimes struct proc *p; 588df8bae1dSRodney W. Grimes struct setlogin_args *uap; 589df8bae1dSRodney W. Grimes int *retval; 590df8bae1dSRodney W. Grimes { 591df8bae1dSRodney W. Grimes int error; 592df8bae1dSRodney W. Grimes 593bb56ec4aSPoul-Henning Kamp if ((error = suser(p->p_ucred, &p->p_acflag))) 594df8bae1dSRodney W. Grimes return (error); 595df8bae1dSRodney W. Grimes error = copyinstr((caddr_t) uap->namebuf, 596df8bae1dSRodney W. Grimes (caddr_t) p->p_pgrp->pg_session->s_login, 597df8bae1dSRodney W. Grimes sizeof (p->p_pgrp->pg_session->s_login) - 1, (u_int *)0); 598df8bae1dSRodney W. Grimes if (error == ENAMETOOLONG) 599df8bae1dSRodney W. Grimes error = EINVAL; 600df8bae1dSRodney W. Grimes return (error); 601df8bae1dSRodney W. Grimes } 602