kern_prot.c revision 12063
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
3912063Sdg * $Id: kern_prot.c,v 1.13 1995/10/08 00:06:07 swallace 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>
491541Srgrimes#include <sys/ucred.h>
501541Srgrimes#include <sys/proc.h>
511541Srgrimes#include <sys/timeb.h>
521541Srgrimes#include <sys/times.h>
531541Srgrimes#include <sys/malloc.h>
541541Srgrimes
5511332Sswallacestruct getpid_args {
561541Srgrimes	int	dummy;
571541Srgrimes};
581541Srgrimes
591541Srgrimes/* ARGSUSED */
601549Srgrimesint
611541Srgrimesgetpid(p, uap, retval)
621541Srgrimes	struct proc *p;
6311332Sswallace	struct getpid_args *uap;
641541Srgrimes	int *retval;
651541Srgrimes{
661541Srgrimes
671541Srgrimes	*retval = p->p_pid;
681541Srgrimes#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
691541Srgrimes	retval[1] = p->p_pptr->p_pid;
701541Srgrimes#endif
711541Srgrimes	return (0);
721541Srgrimes}
731541Srgrimes
7411332Sswallacestruct getppid_args {
7511332Sswallace        int     dummy;
7611332Sswallace};
771541Srgrimes/* ARGSUSED */
781549Srgrimesint
791541Srgrimesgetppid(p, uap, retval)
801541Srgrimes	struct proc *p;
8111332Sswallace	struct getppid_args *uap;
821541Srgrimes	int *retval;
831541Srgrimes{
841541Srgrimes
851541Srgrimes	*retval = p->p_pptr->p_pid;
861541Srgrimes	return (0);
871541Srgrimes}
881541Srgrimes
891541Srgrimes/* Get process group ID; note that POSIX getpgrp takes no parameter */
9011332Sswallacestruct getpgrp_args {
9111332Sswallace        int     dummy;
9211332Sswallace};
9311332Sswallace
941549Srgrimesint
951541Srgrimesgetpgrp(p, uap, retval)
961541Srgrimes	struct proc *p;
9711332Sswallace	struct getpgrp_args *uap;
981541Srgrimes	int *retval;
991541Srgrimes{
1001541Srgrimes
1011541Srgrimes	*retval = p->p_pgrp->pg_id;
1021541Srgrimes	return (0);
1031541Srgrimes}
1041541Srgrimes
10511332Sswallacestruct getuid_args {
10611332Sswallace        int     dummy;
10711332Sswallace};
10811332Sswallace
1091541Srgrimes/* ARGSUSED */
1101549Srgrimesint
1111541Srgrimesgetuid(p, uap, retval)
1121541Srgrimes	struct proc *p;
11311332Sswallace	struct getuid_args *uap;
1141541Srgrimes	int *retval;
1151541Srgrimes{
1161541Srgrimes
1171541Srgrimes	*retval = p->p_cred->p_ruid;
1181541Srgrimes#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1191541Srgrimes	retval[1] = p->p_ucred->cr_uid;
1201541Srgrimes#endif
1211541Srgrimes	return (0);
1221541Srgrimes}
1231541Srgrimes
12411332Sswallacestruct geteuid_args {
12511332Sswallace        int     dummy;
12611332Sswallace};
12711332Sswallace
1281541Srgrimes/* ARGSUSED */
1291549Srgrimesint
1301541Srgrimesgeteuid(p, uap, retval)
1311541Srgrimes	struct proc *p;
13211332Sswallace	struct geteuid_args *uap;
1331541Srgrimes	int *retval;
1341541Srgrimes{
1351541Srgrimes
1361541Srgrimes	*retval = p->p_ucred->cr_uid;
1371541Srgrimes	return (0);
1381541Srgrimes}
1391541Srgrimes
14011332Sswallacestruct getgid_args {
14111332Sswallace        int     dummy;
14211332Sswallace};
14311332Sswallace
1441541Srgrimes/* ARGSUSED */
1451549Srgrimesint
1461541Srgrimesgetgid(p, uap, retval)
1471541Srgrimes	struct proc *p;
14811332Sswallace	struct getgid_args *uap;
1491541Srgrimes	int *retval;
1501541Srgrimes{
1511541Srgrimes
1521541Srgrimes	*retval = p->p_cred->p_rgid;
1531541Srgrimes#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1541541Srgrimes	retval[1] = p->p_ucred->cr_groups[0];
1551541Srgrimes#endif
1561541Srgrimes	return (0);
1571541Srgrimes}
1581541Srgrimes
1591541Srgrimes/*
1601541Srgrimes * Get effective group ID.  The "egid" is groups[0], and could be obtained
1611541Srgrimes * via getgroups.  This syscall exists because it is somewhat painful to do
1621541Srgrimes * correctly in a library function.
1631541Srgrimes */
16411332Sswallacestruct getegid_args {
16511332Sswallace        int     dummy;
16611332Sswallace};
16711332Sswallace
1681541Srgrimes/* ARGSUSED */
1691549Srgrimesint
1701541Srgrimesgetegid(p, uap, retval)
1711541Srgrimes	struct proc *p;
17211332Sswallace	struct getegid_args *uap;
1731541Srgrimes	int *retval;
1741541Srgrimes{
1751541Srgrimes
1761541Srgrimes	*retval = p->p_ucred->cr_groups[0];
1771541Srgrimes	return (0);
1781541Srgrimes}
1791541Srgrimes
1801541Srgrimesstruct getgroups_args {
1811541Srgrimes	u_int	gidsetsize;
1821541Srgrimes	gid_t	*gidset;
1831541Srgrimes};
1841549Srgrimesint
1851541Srgrimesgetgroups(p, uap, retval)
1861541Srgrimes	struct proc *p;
1871541Srgrimes	register struct	getgroups_args *uap;
1881541Srgrimes	int *retval;
1891541Srgrimes{
1901541Srgrimes	register struct pcred *pc = p->p_cred;
1911541Srgrimes	register u_int ngrp;
1921541Srgrimes	int error;
1931541Srgrimes
1941541Srgrimes	if ((ngrp = uap->gidsetsize) == 0) {
1951541Srgrimes		*retval = pc->pc_ucred->cr_ngroups;
1961541Srgrimes		return (0);
1971541Srgrimes	}
1981541Srgrimes	if (ngrp < pc->pc_ucred->cr_ngroups)
1991541Srgrimes		return (EINVAL);
2001541Srgrimes	ngrp = pc->pc_ucred->cr_ngroups;
2013098Sphk	if ((error = copyout((caddr_t)pc->pc_ucred->cr_groups,
2023098Sphk	    (caddr_t)uap->gidset, ngrp * sizeof(gid_t))))
2031541Srgrimes		return (error);
2041541Srgrimes	*retval = ngrp;
2051541Srgrimes	return (0);
2061541Srgrimes}
2071541Srgrimes
20811332Sswallacestruct getsid_args {
20911332Sswallace        int     dummy;
21011332Sswallace};
21111332Sswallace
2121541Srgrimes/* ARGSUSED */
2131549Srgrimesint
2141541Srgrimessetsid(p, uap, retval)
2151541Srgrimes	register struct proc *p;
21611332Sswallace	struct getsid_args *uap;
2171541Srgrimes	int *retval;
2181541Srgrimes{
2191541Srgrimes
2201541Srgrimes	if (p->p_pgid == p->p_pid || pgfind(p->p_pid)) {
2211541Srgrimes		return (EPERM);
2221541Srgrimes	} else {
2231541Srgrimes		(void)enterpgrp(p, p->p_pid, 1);
2241541Srgrimes		*retval = p->p_pid;
2251541Srgrimes		return (0);
2261541Srgrimes	}
2271541Srgrimes}
2281541Srgrimes
2291541Srgrimes/*
2301541Srgrimes * set process group (setpgid/old setpgrp)
2311541Srgrimes *
2321541Srgrimes * caller does setpgid(targpid, targpgid)
2331541Srgrimes *
2341541Srgrimes * pid must be caller or child of caller (ESRCH)
2351541Srgrimes * if a child
2361541Srgrimes *	pid must be in same session (EPERM)
2371541Srgrimes *	pid can't have done an exec (EACCES)
2381541Srgrimes * if pgid != pid
2391541Srgrimes * 	there must exist some pid in same session having pgid (EPERM)
2401541Srgrimes * pid must not be session leader (EPERM)
2411541Srgrimes */
2421541Srgrimesstruct setpgid_args {
2431541Srgrimes	int	pid;	/* target process id */
2441541Srgrimes	int	pgid;	/* target pgrp id */
2451541Srgrimes};
2461541Srgrimes/* ARGSUSED */
2471549Srgrimesint
2481541Srgrimessetpgid(curp, uap, retval)
2491541Srgrimes	struct proc *curp;
2501541Srgrimes	register struct setpgid_args *uap;
2511541Srgrimes	int *retval;
2521541Srgrimes{
2531541Srgrimes	register struct proc *targp;		/* target process */
2541541Srgrimes	register struct pgrp *pgrp;		/* target pgrp */
2551541Srgrimes
2561541Srgrimes	if (uap->pid != 0 && uap->pid != curp->p_pid) {
2571541Srgrimes		if ((targp = pfind(uap->pid)) == 0 || !inferior(targp))
2581541Srgrimes			return (ESRCH);
2591541Srgrimes		if (targp->p_session != curp->p_session)
2601541Srgrimes			return (EPERM);
2611541Srgrimes		if (targp->p_flag & P_EXEC)
2621541Srgrimes			return (EACCES);
2631541Srgrimes	} else
2641541Srgrimes		targp = curp;
2651541Srgrimes	if (SESS_LEADER(targp))
2661541Srgrimes		return (EPERM);
2671541Srgrimes	if (uap->pgid == 0)
2681541Srgrimes		uap->pgid = targp->p_pid;
2691541Srgrimes	else if (uap->pgid != targp->p_pid)
2701541Srgrimes		if ((pgrp = pgfind(uap->pgid)) == 0 ||
2711541Srgrimes	            pgrp->pg_session != curp->p_session)
2721541Srgrimes			return (EPERM);
2731541Srgrimes	return (enterpgrp(targp, uap->pgid, 0));
2741541Srgrimes}
2751541Srgrimes
2761541Srgrimesstruct setuid_args {
2771541Srgrimes	uid_t	uid;
2781541Srgrimes};
2791541Srgrimes/* ARGSUSED */
2801549Srgrimesint
2811541Srgrimessetuid(p, uap, retval)
2821541Srgrimes	struct proc *p;
2831541Srgrimes	struct setuid_args *uap;
2841541Srgrimes	int *retval;
2851541Srgrimes{
2861541Srgrimes	register struct pcred *pc = p->p_cred;
2871541Srgrimes	register uid_t uid;
2881541Srgrimes	int error;
2891541Srgrimes
2901541Srgrimes	uid = uap->uid;
2918162Sache	if (uid != pc->p_ruid && uid != pc->p_svuid &&
2928162Sache	    (error = suser(pc->pc_ucred, &p->p_acflag)))
2931541Srgrimes		return (error);
2941541Srgrimes	/*
2951541Srgrimes	 * Everything's okay, do it.
2961541Srgrimes	 * Transfer proc count to new user.
2971541Srgrimes	 * Copy credentials so other references do not see our changes.
2981541Srgrimes	 */
2998162Sache	if (pc->pc_ucred->cr_uid == 0 && uid != pc->p_ruid) {
3008141Sache		(void)chgproccnt(pc->p_ruid, -1);
3018141Sache		(void)chgproccnt(uid, 1);
3028141Sache	}
3031541Srgrimes	pc->pc_ucred = crcopy(pc->pc_ucred);
3048162Sache	if (pc->pc_ucred->cr_uid == 0) {
3058141Sache		pc->p_ruid = uid;
3068141Sache		pc->p_svuid = uid;
3078141Sache	}
3088162Sache	pc->pc_ucred->cr_uid = uid;
3091541Srgrimes	p->p_flag |= P_SUGID;
3101541Srgrimes	return (0);
3111541Srgrimes}
3121541Srgrimes
3131541Srgrimesstruct seteuid_args {
3141541Srgrimes	uid_t	euid;
3151541Srgrimes};
3161541Srgrimes/* ARGSUSED */
3171549Srgrimesint
3181541Srgrimesseteuid(p, uap, retval)
3191541Srgrimes	struct proc *p;
3201541Srgrimes	struct seteuid_args *uap;
3211541Srgrimes	int *retval;
3221541Srgrimes{
3231541Srgrimes	register struct pcred *pc = p->p_cred;
3241541Srgrimes	register uid_t euid;
3251541Srgrimes	int error;
3261541Srgrimes
3271541Srgrimes	euid = uap->euid;
3281541Srgrimes	if (euid != pc->p_ruid && euid != pc->p_svuid &&
3291541Srgrimes	    (error = suser(pc->pc_ucred, &p->p_acflag)))
3301541Srgrimes		return (error);
3311541Srgrimes	/*
3321541Srgrimes	 * Everything's okay, do it.  Copy credentials so other references do
3331541Srgrimes	 * not see our changes.
3341541Srgrimes	 */
3351541Srgrimes	pc->pc_ucred = crcopy(pc->pc_ucred);
3361541Srgrimes	pc->pc_ucred->cr_uid = euid;
3371541Srgrimes	p->p_flag |= P_SUGID;
3381541Srgrimes	return (0);
3391541Srgrimes}
3401541Srgrimes
3411541Srgrimesstruct setgid_args {
3421541Srgrimes	gid_t	gid;
3431541Srgrimes};
3441541Srgrimes/* ARGSUSED */
3451549Srgrimesint
3461541Srgrimessetgid(p, uap, retval)
3471541Srgrimes	struct proc *p;
3481541Srgrimes	struct setgid_args *uap;
3491541Srgrimes	int *retval;
3501541Srgrimes{
3511541Srgrimes	register struct pcred *pc = p->p_cred;
3521541Srgrimes	register gid_t gid;
3531541Srgrimes	int error;
3541541Srgrimes
3551541Srgrimes	gid = uap->gid;
3568162Sache	if (gid != pc->p_rgid && gid != pc->p_svgid &&
3578162Sache	    (error = suser(pc->pc_ucred, &p->p_acflag)))
3581541Srgrimes		return (error);
3591541Srgrimes	pc->pc_ucred = crcopy(pc->pc_ucred);
3601541Srgrimes	pc->pc_ucred->cr_groups[0] = gid;
3618162Sache	if (pc->pc_ucred->cr_uid == 0) {
3628141Sache		pc->p_rgid = gid;
3638141Sache		pc->p_svgid = gid;
3648141Sache	}
3651541Srgrimes	p->p_flag |= P_SUGID;
3661541Srgrimes	return (0);
3671541Srgrimes}
3681541Srgrimes
3691541Srgrimesstruct setegid_args {
3701541Srgrimes	gid_t	egid;
3711541Srgrimes};
3721541Srgrimes/* ARGSUSED */
3731549Srgrimesint
3741541Srgrimessetegid(p, uap, retval)
3751541Srgrimes	struct proc *p;
3761541Srgrimes	struct setegid_args *uap;
3771541Srgrimes	int *retval;
3781541Srgrimes{
3791541Srgrimes	register struct pcred *pc = p->p_cred;
3801541Srgrimes	register gid_t egid;
3811541Srgrimes	int error;
3821541Srgrimes
3831541Srgrimes	egid = uap->egid;
3841541Srgrimes	if (egid != pc->p_rgid && egid != pc->p_svgid &&
3851541Srgrimes	    (error = suser(pc->pc_ucred, &p->p_acflag)))
3861541Srgrimes		return (error);
3871541Srgrimes	pc->pc_ucred = crcopy(pc->pc_ucred);
3881541Srgrimes	pc->pc_ucred->cr_groups[0] = egid;
3891541Srgrimes	p->p_flag |= P_SUGID;
3901541Srgrimes	return (0);
3911541Srgrimes}
3921541Srgrimes
3931541Srgrimesstruct setgroups_args {
3941541Srgrimes	u_int	gidsetsize;
3951541Srgrimes	gid_t	*gidset;
3961541Srgrimes};
3971541Srgrimes/* ARGSUSED */
3981549Srgrimesint
3991541Srgrimessetgroups(p, uap, retval)
4001541Srgrimes	struct proc *p;
4011541Srgrimes	struct setgroups_args *uap;
4021541Srgrimes	int *retval;
4031541Srgrimes{
4041541Srgrimes	register struct pcred *pc = p->p_cred;
4051541Srgrimes	register u_int ngrp;
4061541Srgrimes	int error;
4071541Srgrimes
4083098Sphk	if ((error = suser(pc->pc_ucred, &p->p_acflag)))
4091541Srgrimes		return (error);
41012063Sdg	ngrp = uap->gidsetsize;
41112063Sdg	if (ngrp < 1 || ngrp > NGROUPS)
4121541Srgrimes		return (EINVAL);
4131541Srgrimes	pc->pc_ucred = crcopy(pc->pc_ucred);
4143098Sphk	if ((error = copyin((caddr_t)uap->gidset,
4153098Sphk	    (caddr_t)pc->pc_ucred->cr_groups, ngrp * sizeof(gid_t))))
4161541Srgrimes		return (error);
4171541Srgrimes	pc->pc_ucred->cr_ngroups = ngrp;
4181541Srgrimes	p->p_flag |= P_SUGID;
4191541Srgrimes	return (0);
4201541Srgrimes}
4211541Srgrimes
4221541Srgrimesstruct setreuid_args {
4239238Sache	uid_t	ruid;
4249238Sache	uid_t	euid;
4251541Srgrimes};
4261541Srgrimes/* ARGSUSED */
4271549Srgrimesint
4288019Sachesetreuid(p, uap, retval)
4291541Srgrimes	register struct proc *p;
4301541Srgrimes	struct setreuid_args *uap;
4311541Srgrimes	int *retval;
4321541Srgrimes{
4331541Srgrimes	register struct pcred *pc = p->p_cred;
4349238Sache	register uid_t ruid, euid;
4358135Sache	int error;
4361541Srgrimes
4379238Sache	ruid = uap->ruid;
4389238Sache	euid = uap->euid;
4399238Sache	if ((ruid != (uid_t)-1 && ruid != pc->p_ruid && ruid != pc->p_svuid ||
4409238Sache	     euid != (uid_t)-1 && euid != pc->p_ruid && euid != pc->p_svuid) &&
4418135Sache	    (error = suser(pc->pc_ucred, &p->p_acflag)))
4428135Sache		return (error);
4439238Sache
4449238Sache	pc->pc_ucred = crcopy(pc->pc_ucred);
4459238Sache	if (euid != (uid_t)-1)
4469238Sache		pc->pc_ucred->cr_uid = euid;
4479238Sache	if (ruid != (uid_t)-1 && ruid != pc->p_ruid) {
4489238Sache		(void)chgproccnt(pc->p_ruid, -1);
4499238Sache		(void)chgproccnt(ruid, 1);
4509238Sache		pc->p_ruid = ruid;
4518135Sache	}
4529238Sache	if (ruid != (uid_t)-1 || pc->pc_ucred->cr_uid != pc->p_ruid)
4538111Sache		pc->p_svuid = pc->pc_ucred->cr_uid;
4549238Sache	p->p_flag |= P_SUGID;
4558135Sache	return (0);
4561541Srgrimes}
4571541Srgrimes
4581541Srgrimesstruct setregid_args {
4599238Sache	gid_t	rgid;
4609238Sache	gid_t	egid;
4611541Srgrimes};
4621541Srgrimes/* ARGSUSED */
4631549Srgrimesint
4648019Sachesetregid(p, uap, retval)
4651541Srgrimes	register struct proc *p;
4661541Srgrimes	struct setregid_args *uap;
4671541Srgrimes	int *retval;
4681541Srgrimes{
4691541Srgrimes	register struct pcred *pc = p->p_cred;
4709238Sache	register gid_t rgid, egid;
4718135Sache	int error;
4721541Srgrimes
4739238Sache	rgid = uap->rgid;
4749238Sache	egid = uap->egid;
4759238Sache	if ((rgid != (gid_t)-1 && rgid != pc->p_rgid && rgid != pc->p_svgid ||
4769238Sache	     egid != (gid_t)-1 && egid != pc->p_rgid && egid != pc->p_svgid) &&
4778135Sache	    (error = suser(pc->pc_ucred, &p->p_acflag)))
4788135Sache		return (error);
4799238Sache
4809238Sache	pc->pc_ucred = crcopy(pc->pc_ucred);
4819238Sache	if (egid != (gid_t)-1)
4829238Sache		pc->pc_ucred->cr_groups[0] = egid;
4839238Sache	if (rgid != (gid_t)-1)
4849238Sache		pc->p_rgid = rgid;
4859238Sache	if (rgid != (gid_t)-1 || pc->pc_ucred->cr_groups[0] != pc->p_rgid)
4868111Sache		pc->p_svgid = pc->pc_ucred->cr_groups[0];
4879238Sache	p->p_flag |= P_SUGID;
4888135Sache	return (0);
4891541Srgrimes}
4901541Srgrimes
4911541Srgrimes/*
4921541Srgrimes * Check if gid is a member of the group set.
4931541Srgrimes */
4941549Srgrimesint
4951541Srgrimesgroupmember(gid, cred)
4961541Srgrimes	gid_t gid;
4971541Srgrimes	register struct ucred *cred;
4981541Srgrimes{
4991541Srgrimes	register gid_t *gp;
5001541Srgrimes	gid_t *egp;
5011541Srgrimes
5021541Srgrimes	egp = &(cred->cr_groups[cred->cr_ngroups]);
5031541Srgrimes	for (gp = cred->cr_groups; gp < egp; gp++)
5041541Srgrimes		if (*gp == gid)
5051541Srgrimes			return (1);
5061541Srgrimes	return (0);
5071541Srgrimes}
5081541Srgrimes
5091541Srgrimes/*
5101541Srgrimes * Test whether the specified credentials imply "super-user"
5111541Srgrimes * privilege; if so, and we have accounting info, set the flag
5121541Srgrimes * indicating use of super-powers.
5131541Srgrimes * Returns 0 or error.
5141541Srgrimes */
5151549Srgrimesint
5161541Srgrimessuser(cred, acflag)
5171541Srgrimes	struct ucred *cred;
5188011Sbde	u_short *acflag;
5191541Srgrimes{
5201541Srgrimes	if (cred->cr_uid == 0) {
5211541Srgrimes		if (acflag)
5221541Srgrimes			*acflag |= ASU;
5231541Srgrimes		return (0);
5241541Srgrimes	}
5251541Srgrimes	return (EPERM);
5261541Srgrimes}
5271541Srgrimes
5281541Srgrimes/*
5291541Srgrimes * Allocate a zeroed cred structure.
5301541Srgrimes */
5311541Srgrimesstruct ucred *
5321541Srgrimescrget()
5331541Srgrimes{
5341541Srgrimes	register struct ucred *cr;
5351541Srgrimes
5361541Srgrimes	MALLOC(cr, struct ucred *, sizeof(*cr), M_CRED, M_WAITOK);
5371541Srgrimes	bzero((caddr_t)cr, sizeof(*cr));
5381541Srgrimes	cr->cr_ref = 1;
5391541Srgrimes	return (cr);
5401541Srgrimes}
5411541Srgrimes
5421541Srgrimes/*
5431541Srgrimes * Free a cred structure.
5441541Srgrimes * Throws away space when ref count gets to 0.
5451541Srgrimes */
5461549Srgrimesvoid
5471541Srgrimescrfree(cr)
5481541Srgrimes	struct ucred *cr;
5491541Srgrimes{
5501541Srgrimes	int s;
5511541Srgrimes
5521541Srgrimes	s = splimp();				/* ??? */
5531541Srgrimes	if (--cr->cr_ref == 0)
5541541Srgrimes		FREE((caddr_t)cr, M_CRED);
5551541Srgrimes	(void) splx(s);
5561541Srgrimes}
5571541Srgrimes
5581541Srgrimes/*
5591541Srgrimes * Copy cred structure to a new one and free the old one.
5601541Srgrimes */
5611541Srgrimesstruct ucred *
5621541Srgrimescrcopy(cr)
5631541Srgrimes	struct ucred *cr;
5641541Srgrimes{
5651541Srgrimes	struct ucred *newcr;
5661541Srgrimes
5671541Srgrimes	if (cr->cr_ref == 1)
5681541Srgrimes		return (cr);
5691541Srgrimes	newcr = crget();
5701541Srgrimes	*newcr = *cr;
5711541Srgrimes	crfree(cr);
5721541Srgrimes	newcr->cr_ref = 1;
5731541Srgrimes	return (newcr);
5741541Srgrimes}
5751541Srgrimes
5761541Srgrimes/*
5771541Srgrimes * Dup cred struct to a new held one.
5781541Srgrimes */
5791541Srgrimesstruct ucred *
5801541Srgrimescrdup(cr)
5811541Srgrimes	struct ucred *cr;
5821541Srgrimes{
5831541Srgrimes	struct ucred *newcr;
5841541Srgrimes
5851541Srgrimes	newcr = crget();
5861541Srgrimes	*newcr = *cr;
5871541Srgrimes	newcr->cr_ref = 1;
5881541Srgrimes	return (newcr);
5891541Srgrimes}
5901541Srgrimes
5911541Srgrimes/*
5921541Srgrimes * Get login name, if available.
5931541Srgrimes */
5941541Srgrimesstruct getlogin_args {
5951541Srgrimes	char	*namebuf;
5961541Srgrimes	u_int	namelen;
5971541Srgrimes};
5981541Srgrimes/* ARGSUSED */
5991549Srgrimesint
6001541Srgrimesgetlogin(p, uap, retval)
6011541Srgrimes	struct proc *p;
6021541Srgrimes	struct getlogin_args *uap;
6031541Srgrimes	int *retval;
6041541Srgrimes{
6051541Srgrimes
6061541Srgrimes	if (uap->namelen > sizeof (p->p_pgrp->pg_session->s_login))
6071541Srgrimes		uap->namelen = sizeof (p->p_pgrp->pg_session->s_login);
6081541Srgrimes	return (copyout((caddr_t) p->p_pgrp->pg_session->s_login,
6091541Srgrimes	    (caddr_t) uap->namebuf, uap->namelen));
6101541Srgrimes}
6111541Srgrimes
6121541Srgrimes/*
6131541Srgrimes * Set login name.
6141541Srgrimes */
6151541Srgrimesstruct setlogin_args {
6161541Srgrimes	char	*namebuf;
6171541Srgrimes};
6181541Srgrimes/* ARGSUSED */
6191549Srgrimesint
6201541Srgrimessetlogin(p, uap, retval)
6211541Srgrimes	struct proc *p;
6221541Srgrimes	struct setlogin_args *uap;
6231541Srgrimes	int *retval;
6241541Srgrimes{
6251541Srgrimes	int error;
6261541Srgrimes
6273098Sphk	if ((error = suser(p->p_ucred, &p->p_acflag)))
6281541Srgrimes		return (error);
6291541Srgrimes	error = copyinstr((caddr_t) uap->namebuf,
6301541Srgrimes	    (caddr_t) p->p_pgrp->pg_session->s_login,
6311541Srgrimes	    sizeof (p->p_pgrp->pg_session->s_login) - 1, (u_int *)0);
6321541Srgrimes	if (error == ENAMETOOLONG)
6331541Srgrimes		error = EINVAL;
6341541Srgrimes	return (error);
6351541Srgrimes}
636