kern_prot.c revision 22522
11541Srgrimes/* 21541Srgrimes * Copyright (c) 1982, 1986, 1989, 1990, 1991, 1993 31541Srgrimes * The Regents of the University of California. All rights reserved. 41541Srgrimes * (c) UNIX System Laboratories, Inc. 51541Srgrimes * All or some portions of this file are derived from material licensed 61541Srgrimes * to the University of California by American Telephone and Telegraph 71541Srgrimes * Co. or Unix System Laboratories, Inc. and are reproduced herein with 81541Srgrimes * the permission of UNIX System Laboratories, Inc. 91541Srgrimes * 101541Srgrimes * Redistribution and use in source and binary forms, with or without 111541Srgrimes * modification, are permitted provided that the following conditions 121541Srgrimes * are met: 131541Srgrimes * 1. Redistributions of source code must retain the above copyright 141541Srgrimes * notice, this list of conditions and the following disclaimer. 151541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 161541Srgrimes * notice, this list of conditions and the following disclaimer in the 171541Srgrimes * documentation and/or other materials provided with the distribution. 181541Srgrimes * 3. All advertising materials mentioning features or use of this software 191541Srgrimes * must display the following acknowledgement: 201541Srgrimes * This product includes software developed by the University of 211541Srgrimes * California, Berkeley and its contributors. 221541Srgrimes * 4. Neither the name of the University nor the names of its contributors 231541Srgrimes * may be used to endorse or promote products derived from this software 241541Srgrimes * without specific prior written permission. 251541Srgrimes * 261541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 271541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 281541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 291541Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 301541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 311541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 321541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 331541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 341541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 351541Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 361541Srgrimes * SUCH DAMAGE. 371541Srgrimes * 381541Srgrimes * @(#)kern_prot.c 8.6 (Berkeley) 1/21/94 3921673Sjkh * $FreeBSD: head/sys/kern/kern_prot.c 22522 1997-02-10 06:18:20Z davidn $ 401541Srgrimes */ 411541Srgrimes 421541Srgrimes/* 431541Srgrimes * System calls related to processes and protection 441541Srgrimes */ 451541Srgrimes 461541Srgrimes#include <sys/param.h> 471541Srgrimes#include <sys/acct.h> 481541Srgrimes#include <sys/systm.h> 4912221Sbde#include <sys/sysproto.h> 501541Srgrimes#include <sys/ucred.h> 511541Srgrimes#include <sys/proc.h> 521541Srgrimes#include <sys/timeb.h> 531541Srgrimes#include <sys/times.h> 541541Srgrimes#include <sys/malloc.h> 5518013Sbde#include <sys/unistd.h> 561541Srgrimes 5712221Sbde#ifndef _SYS_SYSPROTO_H_ 5811332Sswallacestruct getpid_args { 591541Srgrimes int dummy; 601541Srgrimes}; 6112221Sbde#endif 621541Srgrimes 631541Srgrimes/* ARGSUSED */ 641549Srgrimesint 651541Srgrimesgetpid(p, uap, retval) 661541Srgrimes struct proc *p; 6711332Sswallace struct getpid_args *uap; 681541Srgrimes int *retval; 691541Srgrimes{ 701541Srgrimes 711541Srgrimes *retval = p->p_pid; 721541Srgrimes#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 731541Srgrimes retval[1] = p->p_pptr->p_pid; 741541Srgrimes#endif 751541Srgrimes return (0); 761541Srgrimes} 771541Srgrimes 7812221Sbde#ifndef _SYS_SYSPROTO_H_ 7911332Sswallacestruct getppid_args { 8011332Sswallace int dummy; 8111332Sswallace}; 8212221Sbde#endif 831541Srgrimes/* ARGSUSED */ 841549Srgrimesint 851541Srgrimesgetppid(p, uap, retval) 861541Srgrimes struct proc *p; 8711332Sswallace struct getppid_args *uap; 881541Srgrimes int *retval; 891541Srgrimes{ 901541Srgrimes 911541Srgrimes *retval = p->p_pptr->p_pid; 921541Srgrimes return (0); 931541Srgrimes} 941541Srgrimes 951541Srgrimes/* Get process group ID; note that POSIX getpgrp takes no parameter */ 9612221Sbde#ifndef _SYS_SYSPROTO_H_ 9711332Sswallacestruct getpgrp_args { 9811332Sswallace int dummy; 9911332Sswallace}; 10012221Sbde#endif 10111332Sswallace 1021549Srgrimesint 1031541Srgrimesgetpgrp(p, uap, retval) 1041541Srgrimes struct proc *p; 10511332Sswallace struct getpgrp_args *uap; 1061541Srgrimes int *retval; 1071541Srgrimes{ 1081541Srgrimes 1091541Srgrimes *retval = p->p_pgrp->pg_id; 1101541Srgrimes return (0); 1111541Srgrimes} 1121541Srgrimes 11312221Sbde#ifndef _SYS_SYSPROTO_H_ 11411332Sswallacestruct getuid_args { 11511332Sswallace int dummy; 11611332Sswallace}; 11712221Sbde#endif 11811332Sswallace 1191541Srgrimes/* ARGSUSED */ 1201549Srgrimesint 1211541Srgrimesgetuid(p, uap, retval) 1221541Srgrimes struct proc *p; 12311332Sswallace struct getuid_args *uap; 1241541Srgrimes int *retval; 1251541Srgrimes{ 1261541Srgrimes 1271541Srgrimes *retval = p->p_cred->p_ruid; 1281541Srgrimes#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 1291541Srgrimes retval[1] = p->p_ucred->cr_uid; 1301541Srgrimes#endif 1311541Srgrimes return (0); 1321541Srgrimes} 1331541Srgrimes 13412221Sbde#ifndef _SYS_SYSPROTO_H_ 13511332Sswallacestruct geteuid_args { 13611332Sswallace int dummy; 13711332Sswallace}; 13812221Sbde#endif 13911332Sswallace 1401541Srgrimes/* ARGSUSED */ 1411549Srgrimesint 1421541Srgrimesgeteuid(p, uap, retval) 1431541Srgrimes struct proc *p; 14411332Sswallace struct geteuid_args *uap; 1451541Srgrimes int *retval; 1461541Srgrimes{ 1471541Srgrimes 1481541Srgrimes *retval = p->p_ucred->cr_uid; 1491541Srgrimes return (0); 1501541Srgrimes} 1511541Srgrimes 15212221Sbde#ifndef _SYS_SYSPROTO_H_ 15311332Sswallacestruct getgid_args { 15411332Sswallace int dummy; 15511332Sswallace}; 15612221Sbde#endif 15711332Sswallace 1581541Srgrimes/* ARGSUSED */ 1591549Srgrimesint 1601541Srgrimesgetgid(p, uap, retval) 1611541Srgrimes struct proc *p; 16211332Sswallace struct getgid_args *uap; 1631541Srgrimes int *retval; 1641541Srgrimes{ 1651541Srgrimes 1661541Srgrimes *retval = p->p_cred->p_rgid; 1671541Srgrimes#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 1681541Srgrimes retval[1] = p->p_ucred->cr_groups[0]; 1691541Srgrimes#endif 1701541Srgrimes return (0); 1711541Srgrimes} 1721541Srgrimes 1731541Srgrimes/* 1741541Srgrimes * Get effective group ID. The "egid" is groups[0], and could be obtained 1751541Srgrimes * via getgroups. This syscall exists because it is somewhat painful to do 1761541Srgrimes * correctly in a library function. 1771541Srgrimes */ 17812221Sbde#ifndef _SYS_SYSPROTO_H_ 17911332Sswallacestruct getegid_args { 18011332Sswallace int dummy; 18111332Sswallace}; 18212221Sbde#endif 18311332Sswallace 1841541Srgrimes/* ARGSUSED */ 1851549Srgrimesint 1861541Srgrimesgetegid(p, uap, retval) 1871541Srgrimes struct proc *p; 18811332Sswallace struct getegid_args *uap; 1891541Srgrimes int *retval; 1901541Srgrimes{ 1911541Srgrimes 1921541Srgrimes *retval = p->p_ucred->cr_groups[0]; 1931541Srgrimes return (0); 1941541Srgrimes} 1951541Srgrimes 19612221Sbde#ifndef _SYS_SYSPROTO_H_ 1971541Srgrimesstruct getgroups_args { 1981541Srgrimes u_int gidsetsize; 1991541Srgrimes gid_t *gidset; 2001541Srgrimes}; 20112221Sbde#endif 2021549Srgrimesint 2031541Srgrimesgetgroups(p, uap, retval) 2041541Srgrimes struct proc *p; 2051541Srgrimes register struct getgroups_args *uap; 2061541Srgrimes int *retval; 2071541Srgrimes{ 2081541Srgrimes register struct pcred *pc = p->p_cred; 2091541Srgrimes register u_int ngrp; 2101541Srgrimes int error; 2111541Srgrimes 2121541Srgrimes if ((ngrp = uap->gidsetsize) == 0) { 2131541Srgrimes *retval = pc->pc_ucred->cr_ngroups; 2141541Srgrimes return (0); 2151541Srgrimes } 2161541Srgrimes if (ngrp < pc->pc_ucred->cr_ngroups) 2171541Srgrimes return (EINVAL); 2181541Srgrimes ngrp = pc->pc_ucred->cr_ngroups; 2193098Sphk if ((error = copyout((caddr_t)pc->pc_ucred->cr_groups, 2203098Sphk (caddr_t)uap->gidset, ngrp * sizeof(gid_t)))) 2211541Srgrimes return (error); 2221541Srgrimes *retval = ngrp; 2231541Srgrimes return (0); 2241541Srgrimes} 2251541Srgrimes 22612221Sbde#ifndef _SYS_SYSPROTO_H_ 22712207Sbdestruct setsid_args { 22811332Sswallace int dummy; 22911332Sswallace}; 23012221Sbde#endif 23111332Sswallace 2321541Srgrimes/* ARGSUSED */ 2331549Srgrimesint 2341541Srgrimessetsid(p, uap, retval) 2351541Srgrimes register struct proc *p; 23612207Sbde struct setsid_args *uap; 2371541Srgrimes int *retval; 2381541Srgrimes{ 2391541Srgrimes 2401541Srgrimes if (p->p_pgid == p->p_pid || pgfind(p->p_pid)) { 2411541Srgrimes return (EPERM); 2421541Srgrimes } else { 2431541Srgrimes (void)enterpgrp(p, p->p_pid, 1); 2441541Srgrimes *retval = p->p_pid; 2451541Srgrimes return (0); 2461541Srgrimes } 2471541Srgrimes} 2481541Srgrimes 2491541Srgrimes/* 2501541Srgrimes * set process group (setpgid/old setpgrp) 2511541Srgrimes * 2521541Srgrimes * caller does setpgid(targpid, targpgid) 2531541Srgrimes * 2541541Srgrimes * pid must be caller or child of caller (ESRCH) 2551541Srgrimes * if a child 2561541Srgrimes * pid must be in same session (EPERM) 2571541Srgrimes * pid can't have done an exec (EACCES) 2581541Srgrimes * if pgid != pid 2591541Srgrimes * there must exist some pid in same session having pgid (EPERM) 2601541Srgrimes * pid must not be session leader (EPERM) 2611541Srgrimes */ 26212221Sbde#ifndef _SYS_SYSPROTO_H_ 2631541Srgrimesstruct setpgid_args { 2641541Srgrimes int pid; /* target process id */ 2651541Srgrimes int pgid; /* target pgrp id */ 2661541Srgrimes}; 26712221Sbde#endif 2681541Srgrimes/* ARGSUSED */ 2691549Srgrimesint 2701541Srgrimessetpgid(curp, uap, retval) 2711541Srgrimes struct proc *curp; 2721541Srgrimes register struct setpgid_args *uap; 2731541Srgrimes int *retval; 2741541Srgrimes{ 2751541Srgrimes register struct proc *targp; /* target process */ 2761541Srgrimes register struct pgrp *pgrp; /* target pgrp */ 2771541Srgrimes 27820677Sbde if (uap->pgid < 0) 27920677Sbde return (EINVAL); 2801541Srgrimes if (uap->pid != 0 && uap->pid != curp->p_pid) { 2811541Srgrimes if ((targp = pfind(uap->pid)) == 0 || !inferior(targp)) 2821541Srgrimes return (ESRCH); 28315985Sdg if (targp->p_pgrp == NULL || targp->p_session != curp->p_session) 2841541Srgrimes return (EPERM); 2851541Srgrimes if (targp->p_flag & P_EXEC) 2861541Srgrimes return (EACCES); 2871541Srgrimes } else 2881541Srgrimes targp = curp; 2891541Srgrimes if (SESS_LEADER(targp)) 2901541Srgrimes return (EPERM); 2911541Srgrimes if (uap->pgid == 0) 2921541Srgrimes uap->pgid = targp->p_pid; 2931541Srgrimes else if (uap->pgid != targp->p_pid) 2941541Srgrimes if ((pgrp = pgfind(uap->pgid)) == 0 || 2951541Srgrimes pgrp->pg_session != curp->p_session) 2961541Srgrimes return (EPERM); 2971541Srgrimes return (enterpgrp(targp, uap->pgid, 0)); 2981541Srgrimes} 2991541Srgrimes 30012221Sbde#ifndef _SYS_SYSPROTO_H_ 3011541Srgrimesstruct setuid_args { 3021541Srgrimes uid_t uid; 3031541Srgrimes}; 30412221Sbde#endif 3051541Srgrimes/* ARGSUSED */ 3061549Srgrimesint 3071541Srgrimessetuid(p, uap, retval) 3081541Srgrimes struct proc *p; 3091541Srgrimes struct setuid_args *uap; 3101541Srgrimes int *retval; 3111541Srgrimes{ 3121541Srgrimes register struct pcred *pc = p->p_cred; 3131541Srgrimes register uid_t uid; 3141541Srgrimes int error; 3151541Srgrimes 3161541Srgrimes uid = uap->uid; 31717994Sache if (uid != pc->p_ruid && 31817994Sache#ifdef _POSIX_SAVED_IDS 31917994Sache uid != pc->p_svuid && 32017994Sache#endif 3218162Sache (error = suser(pc->pc_ucred, &p->p_acflag))) 3221541Srgrimes return (error); 3231541Srgrimes /* 3241541Srgrimes * Everything's okay, do it. 3251541Srgrimes * Transfer proc count to new user. 3261541Srgrimes * Copy credentials so other references do not see our changes. 3271541Srgrimes */ 32817994Sache if ( 32917994Sache#ifdef _POSIX_SAVED_IDS 33017994Sache pc->pc_ucred->cr_uid == 0 && 33117994Sache#endif 33217994Sache uid != pc->p_ruid) { 3338141Sache (void)chgproccnt(pc->p_ruid, -1); 3348141Sache (void)chgproccnt(uid, 1); 3358141Sache } 3361541Srgrimes pc->pc_ucred = crcopy(pc->pc_ucred); 33717994Sache#ifdef _POSIX_SAVED_IDS 3388162Sache if (pc->pc_ucred->cr_uid == 0) { 33917994Sache#endif 3408141Sache pc->p_ruid = uid; 3418141Sache pc->p_svuid = uid; 34217994Sache#ifdef _POSIX_SAVED_IDS 3438141Sache } 34417994Sache#endif 3458162Sache pc->pc_ucred->cr_uid = uid; 3461541Srgrimes p->p_flag |= P_SUGID; 3471541Srgrimes return (0); 3481541Srgrimes} 3491541Srgrimes 35012221Sbde#ifndef _SYS_SYSPROTO_H_ 3511541Srgrimesstruct seteuid_args { 3521541Srgrimes uid_t euid; 3531541Srgrimes}; 35412221Sbde#endif 3551541Srgrimes/* ARGSUSED */ 3561549Srgrimesint 3571541Srgrimesseteuid(p, uap, retval) 3581541Srgrimes struct proc *p; 3591541Srgrimes struct seteuid_args *uap; 3601541Srgrimes int *retval; 3611541Srgrimes{ 3621541Srgrimes register struct pcred *pc = p->p_cred; 3631541Srgrimes register uid_t euid; 3641541Srgrimes int error; 3651541Srgrimes 3661541Srgrimes euid = uap->euid; 3671541Srgrimes if (euid != pc->p_ruid && euid != pc->p_svuid && 3681541Srgrimes (error = suser(pc->pc_ucred, &p->p_acflag))) 3691541Srgrimes return (error); 3701541Srgrimes /* 3711541Srgrimes * Everything's okay, do it. Copy credentials so other references do 3721541Srgrimes * not see our changes. 3731541Srgrimes */ 3741541Srgrimes pc->pc_ucred = crcopy(pc->pc_ucred); 3751541Srgrimes pc->pc_ucred->cr_uid = euid; 3761541Srgrimes p->p_flag |= P_SUGID; 3771541Srgrimes return (0); 3781541Srgrimes} 3791541Srgrimes 38012221Sbde#ifndef _SYS_SYSPROTO_H_ 3811541Srgrimesstruct setgid_args { 3821541Srgrimes gid_t gid; 3831541Srgrimes}; 38412221Sbde#endif 3851541Srgrimes/* ARGSUSED */ 3861549Srgrimesint 3871541Srgrimessetgid(p, uap, retval) 3881541Srgrimes struct proc *p; 3891541Srgrimes struct setgid_args *uap; 3901541Srgrimes int *retval; 3911541Srgrimes{ 3921541Srgrimes register struct pcred *pc = p->p_cred; 3931541Srgrimes register gid_t gid; 3941541Srgrimes int error; 3951541Srgrimes 3961541Srgrimes gid = uap->gid; 39717994Sache if (gid != pc->p_rgid && 39817994Sache#ifdef _POSIX_SAVED_IDS 39917994Sache gid != pc->p_svgid && 40017994Sache#endif 4018162Sache (error = suser(pc->pc_ucred, &p->p_acflag))) 4021541Srgrimes return (error); 4031541Srgrimes pc->pc_ucred = crcopy(pc->pc_ucred); 4041541Srgrimes pc->pc_ucred->cr_groups[0] = gid; 40517994Sache#ifdef _POSIX_SAVED_IDS 4068162Sache if (pc->pc_ucred->cr_uid == 0) { 40717994Sache#endif 4088141Sache pc->p_rgid = gid; 4098141Sache pc->p_svgid = gid; 41017994Sache#ifdef _POSIX_SAVED_IDS 4118141Sache } 41217994Sache#endif 4131541Srgrimes p->p_flag |= P_SUGID; 4141541Srgrimes return (0); 4151541Srgrimes} 4161541Srgrimes 41712221Sbde#ifndef _SYS_SYSPROTO_H_ 4181541Srgrimesstruct setegid_args { 4191541Srgrimes gid_t egid; 4201541Srgrimes}; 42112221Sbde#endif 4221541Srgrimes/* ARGSUSED */ 4231549Srgrimesint 4241541Srgrimessetegid(p, uap, retval) 4251541Srgrimes struct proc *p; 4261541Srgrimes struct setegid_args *uap; 4271541Srgrimes int *retval; 4281541Srgrimes{ 4291541Srgrimes register struct pcred *pc = p->p_cred; 4301541Srgrimes register gid_t egid; 4311541Srgrimes int error; 4321541Srgrimes 4331541Srgrimes egid = uap->egid; 4341541Srgrimes if (egid != pc->p_rgid && egid != pc->p_svgid && 4351541Srgrimes (error = suser(pc->pc_ucred, &p->p_acflag))) 4361541Srgrimes return (error); 4371541Srgrimes pc->pc_ucred = crcopy(pc->pc_ucred); 4381541Srgrimes pc->pc_ucred->cr_groups[0] = egid; 4391541Srgrimes p->p_flag |= P_SUGID; 4401541Srgrimes return (0); 4411541Srgrimes} 4421541Srgrimes 44312221Sbde#ifndef _SYS_SYSPROTO_H_ 4441541Srgrimesstruct setgroups_args { 4451541Srgrimes u_int gidsetsize; 4461541Srgrimes gid_t *gidset; 4471541Srgrimes}; 44812221Sbde#endif 4491541Srgrimes/* ARGSUSED */ 4501549Srgrimesint 4511541Srgrimessetgroups(p, uap, retval) 4521541Srgrimes struct proc *p; 4531541Srgrimes struct setgroups_args *uap; 4541541Srgrimes int *retval; 4551541Srgrimes{ 4561541Srgrimes register struct pcred *pc = p->p_cred; 4571541Srgrimes register u_int ngrp; 4581541Srgrimes int error; 4591541Srgrimes 4603098Sphk if ((error = suser(pc->pc_ucred, &p->p_acflag))) 4611541Srgrimes return (error); 46212063Sdg ngrp = uap->gidsetsize; 46312063Sdg if (ngrp < 1 || ngrp > NGROUPS) 4641541Srgrimes return (EINVAL); 4651541Srgrimes pc->pc_ucred = crcopy(pc->pc_ucred); 4663098Sphk if ((error = copyin((caddr_t)uap->gidset, 4673098Sphk (caddr_t)pc->pc_ucred->cr_groups, ngrp * sizeof(gid_t)))) 4681541Srgrimes return (error); 4691541Srgrimes pc->pc_ucred->cr_ngroups = ngrp; 4701541Srgrimes p->p_flag |= P_SUGID; 4711541Srgrimes return (0); 4721541Srgrimes} 4731541Srgrimes 47412221Sbde#ifndef _SYS_SYSPROTO_H_ 4751541Srgrimesstruct setreuid_args { 4769238Sache uid_t ruid; 4779238Sache uid_t euid; 4781541Srgrimes}; 47912221Sbde#endif 4801541Srgrimes/* ARGSUSED */ 4811549Srgrimesint 4828019Sachesetreuid(p, uap, retval) 4831541Srgrimes register struct proc *p; 4841541Srgrimes struct setreuid_args *uap; 4851541Srgrimes int *retval; 4861541Srgrimes{ 4871541Srgrimes register struct pcred *pc = p->p_cred; 4889238Sache register uid_t ruid, euid; 4898135Sache int error; 4901541Srgrimes 4919238Sache ruid = uap->ruid; 4929238Sache euid = uap->euid; 4939238Sache if ((ruid != (uid_t)-1 && ruid != pc->p_ruid && ruid != pc->p_svuid || 4949238Sache euid != (uid_t)-1 && euid != pc->p_ruid && euid != pc->p_svuid) && 4958135Sache (error = suser(pc->pc_ucred, &p->p_acflag))) 4968135Sache return (error); 4979238Sache 4989238Sache pc->pc_ucred = crcopy(pc->pc_ucred); 4999238Sache if (euid != (uid_t)-1) 5009238Sache pc->pc_ucred->cr_uid = euid; 5019238Sache if (ruid != (uid_t)-1 && ruid != pc->p_ruid) { 5029238Sache (void)chgproccnt(pc->p_ruid, -1); 5039238Sache (void)chgproccnt(ruid, 1); 5049238Sache pc->p_ruid = ruid; 5058135Sache } 5069238Sache if (ruid != (uid_t)-1 || pc->pc_ucred->cr_uid != pc->p_ruid) 5078111Sache pc->p_svuid = pc->pc_ucred->cr_uid; 5089238Sache p->p_flag |= P_SUGID; 5098135Sache return (0); 5101541Srgrimes} 5111541Srgrimes 51212221Sbde#ifndef _SYS_SYSPROTO_H_ 5131541Srgrimesstruct setregid_args { 5149238Sache gid_t rgid; 5159238Sache gid_t egid; 5161541Srgrimes}; 51712221Sbde#endif 5181541Srgrimes/* ARGSUSED */ 5191549Srgrimesint 5208019Sachesetregid(p, uap, retval) 5211541Srgrimes register struct proc *p; 5221541Srgrimes struct setregid_args *uap; 5231541Srgrimes int *retval; 5241541Srgrimes{ 5251541Srgrimes register struct pcred *pc = p->p_cred; 5269238Sache register gid_t rgid, egid; 5278135Sache int error; 5281541Srgrimes 5299238Sache rgid = uap->rgid; 5309238Sache egid = uap->egid; 5319238Sache if ((rgid != (gid_t)-1 && rgid != pc->p_rgid && rgid != pc->p_svgid || 5329238Sache egid != (gid_t)-1 && egid != pc->p_rgid && egid != pc->p_svgid) && 5338135Sache (error = suser(pc->pc_ucred, &p->p_acflag))) 5348135Sache return (error); 5359238Sache 5369238Sache pc->pc_ucred = crcopy(pc->pc_ucred); 5379238Sache if (egid != (gid_t)-1) 5389238Sache pc->pc_ucred->cr_groups[0] = egid; 5399238Sache if (rgid != (gid_t)-1) 5409238Sache pc->p_rgid = rgid; 5419238Sache if (rgid != (gid_t)-1 || pc->pc_ucred->cr_groups[0] != pc->p_rgid) 5428111Sache pc->p_svgid = pc->pc_ucred->cr_groups[0]; 5439238Sache p->p_flag |= P_SUGID; 5448135Sache return (0); 5451541Srgrimes} 5461541Srgrimes 5471541Srgrimes/* 5481541Srgrimes * Check if gid is a member of the group set. 5491541Srgrimes */ 5501549Srgrimesint 5511541Srgrimesgroupmember(gid, cred) 5521541Srgrimes gid_t gid; 5531541Srgrimes register struct ucred *cred; 5541541Srgrimes{ 5551541Srgrimes register gid_t *gp; 5561541Srgrimes gid_t *egp; 5571541Srgrimes 5581541Srgrimes egp = &(cred->cr_groups[cred->cr_ngroups]); 5591541Srgrimes for (gp = cred->cr_groups; gp < egp; gp++) 5601541Srgrimes if (*gp == gid) 5611541Srgrimes return (1); 5621541Srgrimes return (0); 5631541Srgrimes} 5641541Srgrimes 5651541Srgrimes/* 5661541Srgrimes * Test whether the specified credentials imply "super-user" 5671541Srgrimes * privilege; if so, and we have accounting info, set the flag 5681541Srgrimes * indicating use of super-powers. 5691541Srgrimes * Returns 0 or error. 5701541Srgrimes */ 5711549Srgrimesint 5721541Srgrimessuser(cred, acflag) 5731541Srgrimes struct ucred *cred; 5748011Sbde u_short *acflag; 5751541Srgrimes{ 5761541Srgrimes if (cred->cr_uid == 0) { 5771541Srgrimes if (acflag) 5781541Srgrimes *acflag |= ASU; 5791541Srgrimes return (0); 5801541Srgrimes } 5811541Srgrimes return (EPERM); 5821541Srgrimes} 5831541Srgrimes 5841541Srgrimes/* 5851541Srgrimes * Allocate a zeroed cred structure. 5861541Srgrimes */ 5871541Srgrimesstruct ucred * 5881541Srgrimescrget() 5891541Srgrimes{ 5901541Srgrimes register struct ucred *cr; 5911541Srgrimes 5921541Srgrimes MALLOC(cr, struct ucred *, sizeof(*cr), M_CRED, M_WAITOK); 5931541Srgrimes bzero((caddr_t)cr, sizeof(*cr)); 5941541Srgrimes cr->cr_ref = 1; 5951541Srgrimes return (cr); 5961541Srgrimes} 5971541Srgrimes 5981541Srgrimes/* 5991541Srgrimes * Free a cred structure. 6001541Srgrimes * Throws away space when ref count gets to 0. 6011541Srgrimes */ 6021549Srgrimesvoid 6031541Srgrimescrfree(cr) 6041541Srgrimes struct ucred *cr; 6051541Srgrimes{ 6061541Srgrimes int s; 6071541Srgrimes 6081541Srgrimes s = splimp(); /* ??? */ 6091541Srgrimes if (--cr->cr_ref == 0) 6101541Srgrimes FREE((caddr_t)cr, M_CRED); 6111541Srgrimes (void) splx(s); 6121541Srgrimes} 6131541Srgrimes 6141541Srgrimes/* 6151541Srgrimes * Copy cred structure to a new one and free the old one. 6161541Srgrimes */ 6171541Srgrimesstruct ucred * 6181541Srgrimescrcopy(cr) 6191541Srgrimes struct ucred *cr; 6201541Srgrimes{ 6211541Srgrimes struct ucred *newcr; 6221541Srgrimes 6231541Srgrimes if (cr->cr_ref == 1) 6241541Srgrimes return (cr); 6251541Srgrimes newcr = crget(); 6261541Srgrimes *newcr = *cr; 6271541Srgrimes crfree(cr); 6281541Srgrimes newcr->cr_ref = 1; 6291541Srgrimes return (newcr); 6301541Srgrimes} 6311541Srgrimes 6321541Srgrimes/* 6331541Srgrimes * Dup cred struct to a new held one. 6341541Srgrimes */ 6351541Srgrimesstruct ucred * 6361541Srgrimescrdup(cr) 6371541Srgrimes struct ucred *cr; 6381541Srgrimes{ 6391541Srgrimes struct ucred *newcr; 6401541Srgrimes 6411541Srgrimes newcr = crget(); 6421541Srgrimes *newcr = *cr; 6431541Srgrimes newcr->cr_ref = 1; 6441541Srgrimes return (newcr); 6451541Srgrimes} 6461541Srgrimes 6471541Srgrimes/* 6481541Srgrimes * Get login name, if available. 6491541Srgrimes */ 65012221Sbde#ifndef _SYS_SYSPROTO_H_ 6511541Srgrimesstruct getlogin_args { 6521541Srgrimes char *namebuf; 6531541Srgrimes u_int namelen; 6541541Srgrimes}; 65512221Sbde#endif 6561541Srgrimes/* ARGSUSED */ 6571549Srgrimesint 6581541Srgrimesgetlogin(p, uap, retval) 6591541Srgrimes struct proc *p; 6601541Srgrimes struct getlogin_args *uap; 6611541Srgrimes int *retval; 6621541Srgrimes{ 6631541Srgrimes 6641541Srgrimes if (uap->namelen > sizeof (p->p_pgrp->pg_session->s_login)) 6651541Srgrimes uap->namelen = sizeof (p->p_pgrp->pg_session->s_login); 6661541Srgrimes return (copyout((caddr_t) p->p_pgrp->pg_session->s_login, 6671541Srgrimes (caddr_t) uap->namebuf, uap->namelen)); 6681541Srgrimes} 6691541Srgrimes 6701541Srgrimes/* 6711541Srgrimes * Set login name. 6721541Srgrimes */ 67312221Sbde#ifndef _SYS_SYSPROTO_H_ 6741541Srgrimesstruct setlogin_args { 6751541Srgrimes char *namebuf; 6761541Srgrimes}; 67712221Sbde#endif 6781541Srgrimes/* ARGSUSED */ 6791549Srgrimesint 6801541Srgrimessetlogin(p, uap, retval) 6811541Srgrimes struct proc *p; 6821541Srgrimes struct setlogin_args *uap; 6831541Srgrimes int *retval; 6841541Srgrimes{ 6851541Srgrimes int error; 68622522Sdavidn char logintmp[sizeof(p->p_pgrp->pg_session->s_login)]; 6871541Srgrimes 6883098Sphk if ((error = suser(p->p_ucred, &p->p_acflag))) 6891541Srgrimes return (error); 69022522Sdavidn error = copyinstr((caddr_t) uap->namebuf, (caddr_t) logintmp, 69122522Sdavidn sizeof(logintmp), (u_int *)0); 6921541Srgrimes if (error == ENAMETOOLONG) 6931541Srgrimes error = EINVAL; 69422522Sdavidn else if (!error) 69522522Sdavidn (void) memcpy(p->p_pgrp->pg_session->s_login, logintmp, 69622522Sdavidn sizeof(p->p_pgrp->pg_session->s_login)); 6971541Srgrimes return (error); 6981541Srgrimes} 699