kern_prot.c revision 15985
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
3915985Sdg * $Id: kern_prot.c,v 1.16 1995/11/12 06:42:58 bde Exp $
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>
551541Srgrimes
5612221Sbde#ifndef _SYS_SYSPROTO_H_
5711332Sswallacestruct getpid_args {
581541Srgrimes	int	dummy;
591541Srgrimes};
6012221Sbde#endif
611541Srgrimes
621541Srgrimes/* ARGSUSED */
631549Srgrimesint
641541Srgrimesgetpid(p, uap, retval)
651541Srgrimes	struct proc *p;
6611332Sswallace	struct getpid_args *uap;
671541Srgrimes	int *retval;
681541Srgrimes{
691541Srgrimes
701541Srgrimes	*retval = p->p_pid;
711541Srgrimes#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
721541Srgrimes	retval[1] = p->p_pptr->p_pid;
731541Srgrimes#endif
741541Srgrimes	return (0);
751541Srgrimes}
761541Srgrimes
7712221Sbde#ifndef _SYS_SYSPROTO_H_
7811332Sswallacestruct getppid_args {
7911332Sswallace        int     dummy;
8011332Sswallace};
8112221Sbde#endif
821541Srgrimes/* ARGSUSED */
831549Srgrimesint
841541Srgrimesgetppid(p, uap, retval)
851541Srgrimes	struct proc *p;
8611332Sswallace	struct getppid_args *uap;
871541Srgrimes	int *retval;
881541Srgrimes{
891541Srgrimes
901541Srgrimes	*retval = p->p_pptr->p_pid;
911541Srgrimes	return (0);
921541Srgrimes}
931541Srgrimes
941541Srgrimes/* Get process group ID; note that POSIX getpgrp takes no parameter */
9512221Sbde#ifndef _SYS_SYSPROTO_H_
9611332Sswallacestruct getpgrp_args {
9711332Sswallace        int     dummy;
9811332Sswallace};
9912221Sbde#endif
10011332Sswallace
1011549Srgrimesint
1021541Srgrimesgetpgrp(p, uap, retval)
1031541Srgrimes	struct proc *p;
10411332Sswallace	struct getpgrp_args *uap;
1051541Srgrimes	int *retval;
1061541Srgrimes{
1071541Srgrimes
1081541Srgrimes	*retval = p->p_pgrp->pg_id;
1091541Srgrimes	return (0);
1101541Srgrimes}
1111541Srgrimes
11212221Sbde#ifndef _SYS_SYSPROTO_H_
11311332Sswallacestruct getuid_args {
11411332Sswallace        int     dummy;
11511332Sswallace};
11612221Sbde#endif
11711332Sswallace
1181541Srgrimes/* ARGSUSED */
1191549Srgrimesint
1201541Srgrimesgetuid(p, uap, retval)
1211541Srgrimes	struct proc *p;
12211332Sswallace	struct getuid_args *uap;
1231541Srgrimes	int *retval;
1241541Srgrimes{
1251541Srgrimes
1261541Srgrimes	*retval = p->p_cred->p_ruid;
1271541Srgrimes#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1281541Srgrimes	retval[1] = p->p_ucred->cr_uid;
1291541Srgrimes#endif
1301541Srgrimes	return (0);
1311541Srgrimes}
1321541Srgrimes
13312221Sbde#ifndef _SYS_SYSPROTO_H_
13411332Sswallacestruct geteuid_args {
13511332Sswallace        int     dummy;
13611332Sswallace};
13712221Sbde#endif
13811332Sswallace
1391541Srgrimes/* ARGSUSED */
1401549Srgrimesint
1411541Srgrimesgeteuid(p, uap, retval)
1421541Srgrimes	struct proc *p;
14311332Sswallace	struct geteuid_args *uap;
1441541Srgrimes	int *retval;
1451541Srgrimes{
1461541Srgrimes
1471541Srgrimes	*retval = p->p_ucred->cr_uid;
1481541Srgrimes	return (0);
1491541Srgrimes}
1501541Srgrimes
15112221Sbde#ifndef _SYS_SYSPROTO_H_
15211332Sswallacestruct getgid_args {
15311332Sswallace        int     dummy;
15411332Sswallace};
15512221Sbde#endif
15611332Sswallace
1571541Srgrimes/* ARGSUSED */
1581549Srgrimesint
1591541Srgrimesgetgid(p, uap, retval)
1601541Srgrimes	struct proc *p;
16111332Sswallace	struct getgid_args *uap;
1621541Srgrimes	int *retval;
1631541Srgrimes{
1641541Srgrimes
1651541Srgrimes	*retval = p->p_cred->p_rgid;
1661541Srgrimes#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1671541Srgrimes	retval[1] = p->p_ucred->cr_groups[0];
1681541Srgrimes#endif
1691541Srgrimes	return (0);
1701541Srgrimes}
1711541Srgrimes
1721541Srgrimes/*
1731541Srgrimes * Get effective group ID.  The "egid" is groups[0], and could be obtained
1741541Srgrimes * via getgroups.  This syscall exists because it is somewhat painful to do
1751541Srgrimes * correctly in a library function.
1761541Srgrimes */
17712221Sbde#ifndef _SYS_SYSPROTO_H_
17811332Sswallacestruct getegid_args {
17911332Sswallace        int     dummy;
18011332Sswallace};
18112221Sbde#endif
18211332Sswallace
1831541Srgrimes/* ARGSUSED */
1841549Srgrimesint
1851541Srgrimesgetegid(p, uap, retval)
1861541Srgrimes	struct proc *p;
18711332Sswallace	struct getegid_args *uap;
1881541Srgrimes	int *retval;
1891541Srgrimes{
1901541Srgrimes
1911541Srgrimes	*retval = p->p_ucred->cr_groups[0];
1921541Srgrimes	return (0);
1931541Srgrimes}
1941541Srgrimes
19512221Sbde#ifndef _SYS_SYSPROTO_H_
1961541Srgrimesstruct getgroups_args {
1971541Srgrimes	u_int	gidsetsize;
1981541Srgrimes	gid_t	*gidset;
1991541Srgrimes};
20012221Sbde#endif
2011549Srgrimesint
2021541Srgrimesgetgroups(p, uap, retval)
2031541Srgrimes	struct proc *p;
2041541Srgrimes	register struct	getgroups_args *uap;
2051541Srgrimes	int *retval;
2061541Srgrimes{
2071541Srgrimes	register struct pcred *pc = p->p_cred;
2081541Srgrimes	register u_int ngrp;
2091541Srgrimes	int error;
2101541Srgrimes
2111541Srgrimes	if ((ngrp = uap->gidsetsize) == 0) {
2121541Srgrimes		*retval = pc->pc_ucred->cr_ngroups;
2131541Srgrimes		return (0);
2141541Srgrimes	}
2151541Srgrimes	if (ngrp < pc->pc_ucred->cr_ngroups)
2161541Srgrimes		return (EINVAL);
2171541Srgrimes	ngrp = pc->pc_ucred->cr_ngroups;
2183098Sphk	if ((error = copyout((caddr_t)pc->pc_ucred->cr_groups,
2193098Sphk	    (caddr_t)uap->gidset, ngrp * sizeof(gid_t))))
2201541Srgrimes		return (error);
2211541Srgrimes	*retval = ngrp;
2221541Srgrimes	return (0);
2231541Srgrimes}
2241541Srgrimes
22512221Sbde#ifndef _SYS_SYSPROTO_H_
22612207Sbdestruct setsid_args {
22711332Sswallace        int     dummy;
22811332Sswallace};
22912221Sbde#endif
23011332Sswallace
2311541Srgrimes/* ARGSUSED */
2321549Srgrimesint
2331541Srgrimessetsid(p, uap, retval)
2341541Srgrimes	register struct proc *p;
23512207Sbde	struct setsid_args *uap;
2361541Srgrimes	int *retval;
2371541Srgrimes{
2381541Srgrimes
2391541Srgrimes	if (p->p_pgid == p->p_pid || pgfind(p->p_pid)) {
2401541Srgrimes		return (EPERM);
2411541Srgrimes	} else {
2421541Srgrimes		(void)enterpgrp(p, p->p_pid, 1);
2431541Srgrimes		*retval = p->p_pid;
2441541Srgrimes		return (0);
2451541Srgrimes	}
2461541Srgrimes}
2471541Srgrimes
2481541Srgrimes/*
2491541Srgrimes * set process group (setpgid/old setpgrp)
2501541Srgrimes *
2511541Srgrimes * caller does setpgid(targpid, targpgid)
2521541Srgrimes *
2531541Srgrimes * pid must be caller or child of caller (ESRCH)
2541541Srgrimes * if a child
2551541Srgrimes *	pid must be in same session (EPERM)
2561541Srgrimes *	pid can't have done an exec (EACCES)
2571541Srgrimes * if pgid != pid
2581541Srgrimes * 	there must exist some pid in same session having pgid (EPERM)
2591541Srgrimes * pid must not be session leader (EPERM)
2601541Srgrimes */
26112221Sbde#ifndef _SYS_SYSPROTO_H_
2621541Srgrimesstruct setpgid_args {
2631541Srgrimes	int	pid;	/* target process id */
2641541Srgrimes	int	pgid;	/* target pgrp id */
2651541Srgrimes};
26612221Sbde#endif
2671541Srgrimes/* ARGSUSED */
2681549Srgrimesint
2691541Srgrimessetpgid(curp, uap, retval)
2701541Srgrimes	struct proc *curp;
2711541Srgrimes	register struct setpgid_args *uap;
2721541Srgrimes	int *retval;
2731541Srgrimes{
2741541Srgrimes	register struct proc *targp;		/* target process */
2751541Srgrimes	register struct pgrp *pgrp;		/* target pgrp */
2761541Srgrimes
2771541Srgrimes	if (uap->pid != 0 && uap->pid != curp->p_pid) {
2781541Srgrimes		if ((targp = pfind(uap->pid)) == 0 || !inferior(targp))
2791541Srgrimes			return (ESRCH);
28015985Sdg		if (targp->p_pgrp == NULL ||  targp->p_session != curp->p_session)
2811541Srgrimes			return (EPERM);
2821541Srgrimes		if (targp->p_flag & P_EXEC)
2831541Srgrimes			return (EACCES);
2841541Srgrimes	} else
2851541Srgrimes		targp = curp;
2861541Srgrimes	if (SESS_LEADER(targp))
2871541Srgrimes		return (EPERM);
2881541Srgrimes	if (uap->pgid == 0)
2891541Srgrimes		uap->pgid = targp->p_pid;
2901541Srgrimes	else if (uap->pgid != targp->p_pid)
2911541Srgrimes		if ((pgrp = pgfind(uap->pgid)) == 0 ||
2921541Srgrimes	            pgrp->pg_session != curp->p_session)
2931541Srgrimes			return (EPERM);
2941541Srgrimes	return (enterpgrp(targp, uap->pgid, 0));
2951541Srgrimes}
2961541Srgrimes
29712221Sbde#ifndef _SYS_SYSPROTO_H_
2981541Srgrimesstruct setuid_args {
2991541Srgrimes	uid_t	uid;
3001541Srgrimes};
30112221Sbde#endif
3021541Srgrimes/* ARGSUSED */
3031549Srgrimesint
3041541Srgrimessetuid(p, uap, retval)
3051541Srgrimes	struct proc *p;
3061541Srgrimes	struct setuid_args *uap;
3071541Srgrimes	int *retval;
3081541Srgrimes{
3091541Srgrimes	register struct pcred *pc = p->p_cred;
3101541Srgrimes	register uid_t uid;
3111541Srgrimes	int error;
3121541Srgrimes
3131541Srgrimes	uid = uap->uid;
3148162Sache	if (uid != pc->p_ruid && uid != pc->p_svuid &&
3158162Sache	    (error = suser(pc->pc_ucred, &p->p_acflag)))
3161541Srgrimes		return (error);
3171541Srgrimes	/*
3181541Srgrimes	 * Everything's okay, do it.
3191541Srgrimes	 * Transfer proc count to new user.
3201541Srgrimes	 * Copy credentials so other references do not see our changes.
3211541Srgrimes	 */
3228162Sache	if (pc->pc_ucred->cr_uid == 0 && uid != pc->p_ruid) {
3238141Sache		(void)chgproccnt(pc->p_ruid, -1);
3248141Sache		(void)chgproccnt(uid, 1);
3258141Sache	}
3261541Srgrimes	pc->pc_ucred = crcopy(pc->pc_ucred);
3278162Sache	if (pc->pc_ucred->cr_uid == 0) {
3288141Sache		pc->p_ruid = uid;
3298141Sache		pc->p_svuid = uid;
3308141Sache	}
3318162Sache	pc->pc_ucred->cr_uid = uid;
3321541Srgrimes	p->p_flag |= P_SUGID;
3331541Srgrimes	return (0);
3341541Srgrimes}
3351541Srgrimes
33612221Sbde#ifndef _SYS_SYSPROTO_H_
3371541Srgrimesstruct seteuid_args {
3381541Srgrimes	uid_t	euid;
3391541Srgrimes};
34012221Sbde#endif
3411541Srgrimes/* ARGSUSED */
3421549Srgrimesint
3431541Srgrimesseteuid(p, uap, retval)
3441541Srgrimes	struct proc *p;
3451541Srgrimes	struct seteuid_args *uap;
3461541Srgrimes	int *retval;
3471541Srgrimes{
3481541Srgrimes	register struct pcred *pc = p->p_cred;
3491541Srgrimes	register uid_t euid;
3501541Srgrimes	int error;
3511541Srgrimes
3521541Srgrimes	euid = uap->euid;
3531541Srgrimes	if (euid != pc->p_ruid && euid != pc->p_svuid &&
3541541Srgrimes	    (error = suser(pc->pc_ucred, &p->p_acflag)))
3551541Srgrimes		return (error);
3561541Srgrimes	/*
3571541Srgrimes	 * Everything's okay, do it.  Copy credentials so other references do
3581541Srgrimes	 * not see our changes.
3591541Srgrimes	 */
3601541Srgrimes	pc->pc_ucred = crcopy(pc->pc_ucred);
3611541Srgrimes	pc->pc_ucred->cr_uid = euid;
3621541Srgrimes	p->p_flag |= P_SUGID;
3631541Srgrimes	return (0);
3641541Srgrimes}
3651541Srgrimes
36612221Sbde#ifndef _SYS_SYSPROTO_H_
3671541Srgrimesstruct setgid_args {
3681541Srgrimes	gid_t	gid;
3691541Srgrimes};
37012221Sbde#endif
3711541Srgrimes/* ARGSUSED */
3721549Srgrimesint
3731541Srgrimessetgid(p, uap, retval)
3741541Srgrimes	struct proc *p;
3751541Srgrimes	struct setgid_args *uap;
3761541Srgrimes	int *retval;
3771541Srgrimes{
3781541Srgrimes	register struct pcred *pc = p->p_cred;
3791541Srgrimes	register gid_t gid;
3801541Srgrimes	int error;
3811541Srgrimes
3821541Srgrimes	gid = uap->gid;
3838162Sache	if (gid != pc->p_rgid && gid != pc->p_svgid &&
3848162Sache	    (error = suser(pc->pc_ucred, &p->p_acflag)))
3851541Srgrimes		return (error);
3861541Srgrimes	pc->pc_ucred = crcopy(pc->pc_ucred);
3871541Srgrimes	pc->pc_ucred->cr_groups[0] = gid;
3888162Sache	if (pc->pc_ucred->cr_uid == 0) {
3898141Sache		pc->p_rgid = gid;
3908141Sache		pc->p_svgid = gid;
3918141Sache	}
3921541Srgrimes	p->p_flag |= P_SUGID;
3931541Srgrimes	return (0);
3941541Srgrimes}
3951541Srgrimes
39612221Sbde#ifndef _SYS_SYSPROTO_H_
3971541Srgrimesstruct setegid_args {
3981541Srgrimes	gid_t	egid;
3991541Srgrimes};
40012221Sbde#endif
4011541Srgrimes/* ARGSUSED */
4021549Srgrimesint
4031541Srgrimessetegid(p, uap, retval)
4041541Srgrimes	struct proc *p;
4051541Srgrimes	struct setegid_args *uap;
4061541Srgrimes	int *retval;
4071541Srgrimes{
4081541Srgrimes	register struct pcred *pc = p->p_cred;
4091541Srgrimes	register gid_t egid;
4101541Srgrimes	int error;
4111541Srgrimes
4121541Srgrimes	egid = uap->egid;
4131541Srgrimes	if (egid != pc->p_rgid && egid != pc->p_svgid &&
4141541Srgrimes	    (error = suser(pc->pc_ucred, &p->p_acflag)))
4151541Srgrimes		return (error);
4161541Srgrimes	pc->pc_ucred = crcopy(pc->pc_ucred);
4171541Srgrimes	pc->pc_ucred->cr_groups[0] = egid;
4181541Srgrimes	p->p_flag |= P_SUGID;
4191541Srgrimes	return (0);
4201541Srgrimes}
4211541Srgrimes
42212221Sbde#ifndef _SYS_SYSPROTO_H_
4231541Srgrimesstruct setgroups_args {
4241541Srgrimes	u_int	gidsetsize;
4251541Srgrimes	gid_t	*gidset;
4261541Srgrimes};
42712221Sbde#endif
4281541Srgrimes/* ARGSUSED */
4291549Srgrimesint
4301541Srgrimessetgroups(p, uap, retval)
4311541Srgrimes	struct proc *p;
4321541Srgrimes	struct setgroups_args *uap;
4331541Srgrimes	int *retval;
4341541Srgrimes{
4351541Srgrimes	register struct pcred *pc = p->p_cred;
4361541Srgrimes	register u_int ngrp;
4371541Srgrimes	int error;
4381541Srgrimes
4393098Sphk	if ((error = suser(pc->pc_ucred, &p->p_acflag)))
4401541Srgrimes		return (error);
44112063Sdg	ngrp = uap->gidsetsize;
44212063Sdg	if (ngrp < 1 || ngrp > NGROUPS)
4431541Srgrimes		return (EINVAL);
4441541Srgrimes	pc->pc_ucred = crcopy(pc->pc_ucred);
4453098Sphk	if ((error = copyin((caddr_t)uap->gidset,
4463098Sphk	    (caddr_t)pc->pc_ucred->cr_groups, ngrp * sizeof(gid_t))))
4471541Srgrimes		return (error);
4481541Srgrimes	pc->pc_ucred->cr_ngroups = ngrp;
4491541Srgrimes	p->p_flag |= P_SUGID;
4501541Srgrimes	return (0);
4511541Srgrimes}
4521541Srgrimes
45312221Sbde#ifndef _SYS_SYSPROTO_H_
4541541Srgrimesstruct setreuid_args {
4559238Sache	uid_t	ruid;
4569238Sache	uid_t	euid;
4571541Srgrimes};
45812221Sbde#endif
4591541Srgrimes/* ARGSUSED */
4601549Srgrimesint
4618019Sachesetreuid(p, uap, retval)
4621541Srgrimes	register struct proc *p;
4631541Srgrimes	struct setreuid_args *uap;
4641541Srgrimes	int *retval;
4651541Srgrimes{
4661541Srgrimes	register struct pcred *pc = p->p_cred;
4679238Sache	register uid_t ruid, euid;
4688135Sache	int error;
4691541Srgrimes
4709238Sache	ruid = uap->ruid;
4719238Sache	euid = uap->euid;
4729238Sache	if ((ruid != (uid_t)-1 && ruid != pc->p_ruid && ruid != pc->p_svuid ||
4739238Sache	     euid != (uid_t)-1 && euid != pc->p_ruid && euid != pc->p_svuid) &&
4748135Sache	    (error = suser(pc->pc_ucred, &p->p_acflag)))
4758135Sache		return (error);
4769238Sache
4779238Sache	pc->pc_ucred = crcopy(pc->pc_ucred);
4789238Sache	if (euid != (uid_t)-1)
4799238Sache		pc->pc_ucred->cr_uid = euid;
4809238Sache	if (ruid != (uid_t)-1 && ruid != pc->p_ruid) {
4819238Sache		(void)chgproccnt(pc->p_ruid, -1);
4829238Sache		(void)chgproccnt(ruid, 1);
4839238Sache		pc->p_ruid = ruid;
4848135Sache	}
4859238Sache	if (ruid != (uid_t)-1 || pc->pc_ucred->cr_uid != pc->p_ruid)
4868111Sache		pc->p_svuid = pc->pc_ucred->cr_uid;
4879238Sache	p->p_flag |= P_SUGID;
4888135Sache	return (0);
4891541Srgrimes}
4901541Srgrimes
49112221Sbde#ifndef _SYS_SYSPROTO_H_
4921541Srgrimesstruct setregid_args {
4939238Sache	gid_t	rgid;
4949238Sache	gid_t	egid;
4951541Srgrimes};
49612221Sbde#endif
4971541Srgrimes/* ARGSUSED */
4981549Srgrimesint
4998019Sachesetregid(p, uap, retval)
5001541Srgrimes	register struct proc *p;
5011541Srgrimes	struct setregid_args *uap;
5021541Srgrimes	int *retval;
5031541Srgrimes{
5041541Srgrimes	register struct pcred *pc = p->p_cred;
5059238Sache	register gid_t rgid, egid;
5068135Sache	int error;
5071541Srgrimes
5089238Sache	rgid = uap->rgid;
5099238Sache	egid = uap->egid;
5109238Sache	if ((rgid != (gid_t)-1 && rgid != pc->p_rgid && rgid != pc->p_svgid ||
5119238Sache	     egid != (gid_t)-1 && egid != pc->p_rgid && egid != pc->p_svgid) &&
5128135Sache	    (error = suser(pc->pc_ucred, &p->p_acflag)))
5138135Sache		return (error);
5149238Sache
5159238Sache	pc->pc_ucred = crcopy(pc->pc_ucred);
5169238Sache	if (egid != (gid_t)-1)
5179238Sache		pc->pc_ucred->cr_groups[0] = egid;
5189238Sache	if (rgid != (gid_t)-1)
5199238Sache		pc->p_rgid = rgid;
5209238Sache	if (rgid != (gid_t)-1 || pc->pc_ucred->cr_groups[0] != pc->p_rgid)
5218111Sache		pc->p_svgid = pc->pc_ucred->cr_groups[0];
5229238Sache	p->p_flag |= P_SUGID;
5238135Sache	return (0);
5241541Srgrimes}
5251541Srgrimes
5261541Srgrimes/*
5271541Srgrimes * Check if gid is a member of the group set.
5281541Srgrimes */
5291549Srgrimesint
5301541Srgrimesgroupmember(gid, cred)
5311541Srgrimes	gid_t gid;
5321541Srgrimes	register struct ucred *cred;
5331541Srgrimes{
5341541Srgrimes	register gid_t *gp;
5351541Srgrimes	gid_t *egp;
5361541Srgrimes
5371541Srgrimes	egp = &(cred->cr_groups[cred->cr_ngroups]);
5381541Srgrimes	for (gp = cred->cr_groups; gp < egp; gp++)
5391541Srgrimes		if (*gp == gid)
5401541Srgrimes			return (1);
5411541Srgrimes	return (0);
5421541Srgrimes}
5431541Srgrimes
5441541Srgrimes/*
5451541Srgrimes * Test whether the specified credentials imply "super-user"
5461541Srgrimes * privilege; if so, and we have accounting info, set the flag
5471541Srgrimes * indicating use of super-powers.
5481541Srgrimes * Returns 0 or error.
5491541Srgrimes */
5501549Srgrimesint
5511541Srgrimessuser(cred, acflag)
5521541Srgrimes	struct ucred *cred;
5538011Sbde	u_short *acflag;
5541541Srgrimes{
5551541Srgrimes	if (cred->cr_uid == 0) {
5561541Srgrimes		if (acflag)
5571541Srgrimes			*acflag |= ASU;
5581541Srgrimes		return (0);
5591541Srgrimes	}
5601541Srgrimes	return (EPERM);
5611541Srgrimes}
5621541Srgrimes
5631541Srgrimes/*
5641541Srgrimes * Allocate a zeroed cred structure.
5651541Srgrimes */
5661541Srgrimesstruct ucred *
5671541Srgrimescrget()
5681541Srgrimes{
5691541Srgrimes	register struct ucred *cr;
5701541Srgrimes
5711541Srgrimes	MALLOC(cr, struct ucred *, sizeof(*cr), M_CRED, M_WAITOK);
5721541Srgrimes	bzero((caddr_t)cr, sizeof(*cr));
5731541Srgrimes	cr->cr_ref = 1;
5741541Srgrimes	return (cr);
5751541Srgrimes}
5761541Srgrimes
5771541Srgrimes/*
5781541Srgrimes * Free a cred structure.
5791541Srgrimes * Throws away space when ref count gets to 0.
5801541Srgrimes */
5811549Srgrimesvoid
5821541Srgrimescrfree(cr)
5831541Srgrimes	struct ucred *cr;
5841541Srgrimes{
5851541Srgrimes	int s;
5861541Srgrimes
5871541Srgrimes	s = splimp();				/* ??? */
5881541Srgrimes	if (--cr->cr_ref == 0)
5891541Srgrimes		FREE((caddr_t)cr, M_CRED);
5901541Srgrimes	(void) splx(s);
5911541Srgrimes}
5921541Srgrimes
5931541Srgrimes/*
5941541Srgrimes * Copy cred structure to a new one and free the old one.
5951541Srgrimes */
5961541Srgrimesstruct ucred *
5971541Srgrimescrcopy(cr)
5981541Srgrimes	struct ucred *cr;
5991541Srgrimes{
6001541Srgrimes	struct ucred *newcr;
6011541Srgrimes
6021541Srgrimes	if (cr->cr_ref == 1)
6031541Srgrimes		return (cr);
6041541Srgrimes	newcr = crget();
6051541Srgrimes	*newcr = *cr;
6061541Srgrimes	crfree(cr);
6071541Srgrimes	newcr->cr_ref = 1;
6081541Srgrimes	return (newcr);
6091541Srgrimes}
6101541Srgrimes
6111541Srgrimes/*
6121541Srgrimes * Dup cred struct to a new held one.
6131541Srgrimes */
6141541Srgrimesstruct ucred *
6151541Srgrimescrdup(cr)
6161541Srgrimes	struct ucred *cr;
6171541Srgrimes{
6181541Srgrimes	struct ucred *newcr;
6191541Srgrimes
6201541Srgrimes	newcr = crget();
6211541Srgrimes	*newcr = *cr;
6221541Srgrimes	newcr->cr_ref = 1;
6231541Srgrimes	return (newcr);
6241541Srgrimes}
6251541Srgrimes
6261541Srgrimes/*
6271541Srgrimes * Get login name, if available.
6281541Srgrimes */
62912221Sbde#ifndef _SYS_SYSPROTO_H_
6301541Srgrimesstruct getlogin_args {
6311541Srgrimes	char	*namebuf;
6321541Srgrimes	u_int	namelen;
6331541Srgrimes};
63412221Sbde#endif
6351541Srgrimes/* ARGSUSED */
6361549Srgrimesint
6371541Srgrimesgetlogin(p, uap, retval)
6381541Srgrimes	struct proc *p;
6391541Srgrimes	struct getlogin_args *uap;
6401541Srgrimes	int *retval;
6411541Srgrimes{
6421541Srgrimes
6431541Srgrimes	if (uap->namelen > sizeof (p->p_pgrp->pg_session->s_login))
6441541Srgrimes		uap->namelen = sizeof (p->p_pgrp->pg_session->s_login);
6451541Srgrimes	return (copyout((caddr_t) p->p_pgrp->pg_session->s_login,
6461541Srgrimes	    (caddr_t) uap->namebuf, uap->namelen));
6471541Srgrimes}
6481541Srgrimes
6491541Srgrimes/*
6501541Srgrimes * Set login name.
6511541Srgrimes */
65212221Sbde#ifndef _SYS_SYSPROTO_H_
6531541Srgrimesstruct setlogin_args {
6541541Srgrimes	char	*namebuf;
6551541Srgrimes};
65612221Sbde#endif
6571541Srgrimes/* ARGSUSED */
6581549Srgrimesint
6591541Srgrimessetlogin(p, uap, retval)
6601541Srgrimes	struct proc *p;
6611541Srgrimes	struct setlogin_args *uap;
6621541Srgrimes	int *retval;
6631541Srgrimes{
6641541Srgrimes	int error;
6651541Srgrimes
6663098Sphk	if ((error = suser(p->p_ucred, &p->p_acflag)))
6671541Srgrimes		return (error);
6681541Srgrimes	error = copyinstr((caddr_t) uap->namebuf,
6691541Srgrimes	    (caddr_t) p->p_pgrp->pg_session->s_login,
6701541Srgrimes	    sizeof (p->p_pgrp->pg_session->s_login) - 1, (u_int *)0);
6711541Srgrimes	if (error == ENAMETOOLONG)
6721541Srgrimes		error = EINVAL;
6731541Srgrimes	return (error);
6741541Srgrimes}
675