kern_prot.c revision 58717
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
3950477Speter * $FreeBSD: head/sys/kern/kern_prot.c 58717 2000-03-28 07:16:37Z dillon $
401541Srgrimes */
411541Srgrimes
421541Srgrimes/*
431541Srgrimes * System calls related to processes and protection
441541Srgrimes */
451541Srgrimes
4631778Seivind#include "opt_compat.h"
4731778Seivind
481541Srgrimes#include <sys/param.h>
491541Srgrimes#include <sys/acct.h>
501541Srgrimes#include <sys/systm.h>
5112221Sbde#include <sys/sysproto.h>
5241059Speter#include <sys/kernel.h>
531541Srgrimes#include <sys/proc.h>
541541Srgrimes#include <sys/malloc.h>
5531891Ssef#include <sys/pioctl.h>
561541Srgrimes
5730354Sphkstatic MALLOC_DEFINE(M_CRED, "cred", "credentials");
5830354Sphk
5912221Sbde#ifndef _SYS_SYSPROTO_H_
6011332Sswallacestruct getpid_args {
611541Srgrimes	int	dummy;
621541Srgrimes};
6312221Sbde#endif
641541Srgrimes
6558717Sdillon/*
6658717Sdillon * NOT MP SAFE due to p_pptr access
6758717Sdillon */
681541Srgrimes/* ARGSUSED */
691549Srgrimesint
7030994Sphkgetpid(p, uap)
711541Srgrimes	struct proc *p;
7211332Sswallace	struct getpid_args *uap;
731541Srgrimes{
741541Srgrimes
7530994Sphk	p->p_retval[0] = p->p_pid;
761541Srgrimes#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
7730994Sphk	p->p_retval[1] = p->p_pptr->p_pid;
781541Srgrimes#endif
791541Srgrimes	return (0);
801541Srgrimes}
811541Srgrimes
8212221Sbde#ifndef _SYS_SYSPROTO_H_
8311332Sswallacestruct getppid_args {
8411332Sswallace        int     dummy;
8511332Sswallace};
8612221Sbde#endif
871541Srgrimes/* ARGSUSED */
881549Srgrimesint
8930994Sphkgetppid(p, uap)
901541Srgrimes	struct proc *p;
9111332Sswallace	struct getppid_args *uap;
921541Srgrimes{
931541Srgrimes
9430994Sphk	p->p_retval[0] = p->p_pptr->p_pid;
951541Srgrimes	return (0);
961541Srgrimes}
971541Srgrimes
9858717Sdillon/*
9958717Sdillon * Get process group ID; note that POSIX getpgrp takes no parameter
10058717Sdillon *
10158717Sdillon * MP SAFE
10258717Sdillon */
10312221Sbde#ifndef _SYS_SYSPROTO_H_
10411332Sswallacestruct getpgrp_args {
10511332Sswallace        int     dummy;
10611332Sswallace};
10712221Sbde#endif
10811332Sswallace
1091549Srgrimesint
11030994Sphkgetpgrp(p, uap)
1111541Srgrimes	struct proc *p;
11211332Sswallace	struct getpgrp_args *uap;
1131541Srgrimes{
1141541Srgrimes
11530994Sphk	p->p_retval[0] = p->p_pgrp->pg_id;
1161541Srgrimes	return (0);
1171541Srgrimes}
1181541Srgrimes
11928401Speter/* Get an arbitary pid's process group id */
12012221Sbde#ifndef _SYS_SYSPROTO_H_
12128401Speterstruct getpgid_args {
12228401Speter	pid_t	pid;
12328401Speter};
12428401Speter#endif
12528401Speter
12628401Speterint
12730994Sphkgetpgid(p, uap)
12828401Speter	struct proc *p;
12928401Speter	struct getpgid_args *uap;
13028401Speter{
13141726Struckman	struct proc *pt;
13241726Struckman
13341726Struckman	pt = p;
13428401Speter	if (uap->pid == 0)
13528401Speter		goto found;
13628401Speter
13741726Struckman	if ((pt = pfind(uap->pid)) == 0)
13828401Speter		return ESRCH;
13928401Speterfound:
14041726Struckman	p->p_retval[0] = pt->p_pgrp->pg_id;
14128401Speter	return 0;
14228401Speter}
14328401Speter
14428401Speter/*
14528401Speter * Get an arbitary pid's session id.
14628401Speter */
14728401Speter#ifndef _SYS_SYSPROTO_H_
14828401Speterstruct getsid_args {
14928401Speter	pid_t	pid;
15028401Speter};
15128401Speter#endif
15228401Speter
15328401Speterint
15430994Sphkgetsid(p, uap)
15528401Speter	struct proc *p;
15628401Speter	struct getsid_args *uap;
15728401Speter{
15841726Struckman	struct proc *pt;
15941726Struckman
16041726Struckman	pt = p;
16128401Speter	if (uap->pid == 0)
16228401Speter		goto found;
16328401Speter
16441726Struckman	if ((pt == pfind(uap->pid)) == 0)
16528401Speter		return ESRCH;
16628401Speterfound:
16741726Struckman	p->p_retval[0] = pt->p_session->s_sid;
16828401Speter	return 0;
16928401Speter}
17028401Speter
17128401Speter
17228401Speter#ifndef _SYS_SYSPROTO_H_
17311332Sswallacestruct getuid_args {
17411332Sswallace        int     dummy;
17511332Sswallace};
17612221Sbde#endif
17711332Sswallace
17858717Sdillon/*
17958717Sdillon * MP SAFE
18058717Sdillon */
1811541Srgrimes/* ARGSUSED */
1821549Srgrimesint
18330994Sphkgetuid(p, uap)
1841541Srgrimes	struct proc *p;
18511332Sswallace	struct getuid_args *uap;
1861541Srgrimes{
1871541Srgrimes
18830994Sphk	p->p_retval[0] = p->p_cred->p_ruid;
1891541Srgrimes#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
19030994Sphk	p->p_retval[1] = p->p_ucred->cr_uid;
1911541Srgrimes#endif
1921541Srgrimes	return (0);
1931541Srgrimes}
1941541Srgrimes
19512221Sbde#ifndef _SYS_SYSPROTO_H_
19611332Sswallacestruct geteuid_args {
19711332Sswallace        int     dummy;
19811332Sswallace};
19912221Sbde#endif
20011332Sswallace
2011541Srgrimes/* ARGSUSED */
2021549Srgrimesint
20330994Sphkgeteuid(p, uap)
2041541Srgrimes	struct proc *p;
20511332Sswallace	struct geteuid_args *uap;
2061541Srgrimes{
2071541Srgrimes
20830994Sphk	p->p_retval[0] = p->p_ucred->cr_uid;
2091541Srgrimes	return (0);
2101541Srgrimes}
2111541Srgrimes
21212221Sbde#ifndef _SYS_SYSPROTO_H_
21311332Sswallacestruct getgid_args {
21411332Sswallace        int     dummy;
21511332Sswallace};
21612221Sbde#endif
21711332Sswallace
21858717Sdillon/*
21958717Sdillon * MP SAFE
22058717Sdillon */
2211541Srgrimes/* ARGSUSED */
2221549Srgrimesint
22330994Sphkgetgid(p, uap)
2241541Srgrimes	struct proc *p;
22511332Sswallace	struct getgid_args *uap;
2261541Srgrimes{
2271541Srgrimes
22830994Sphk	p->p_retval[0] = p->p_cred->p_rgid;
2291541Srgrimes#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
23030994Sphk	p->p_retval[1] = p->p_ucred->cr_groups[0];
2311541Srgrimes#endif
2321541Srgrimes	return (0);
2331541Srgrimes}
2341541Srgrimes
2351541Srgrimes/*
2361541Srgrimes * Get effective group ID.  The "egid" is groups[0], and could be obtained
2371541Srgrimes * via getgroups.  This syscall exists because it is somewhat painful to do
2381541Srgrimes * correctly in a library function.
2391541Srgrimes */
24012221Sbde#ifndef _SYS_SYSPROTO_H_
24111332Sswallacestruct getegid_args {
24211332Sswallace        int     dummy;
24311332Sswallace};
24412221Sbde#endif
24511332Sswallace
2461541Srgrimes/* ARGSUSED */
2471549Srgrimesint
24830994Sphkgetegid(p, uap)
2491541Srgrimes	struct proc *p;
25011332Sswallace	struct getegid_args *uap;
2511541Srgrimes{
2521541Srgrimes
25330994Sphk	p->p_retval[0] = p->p_ucred->cr_groups[0];
2541541Srgrimes	return (0);
2551541Srgrimes}
2561541Srgrimes
25712221Sbde#ifndef _SYS_SYSPROTO_H_
2581541Srgrimesstruct getgroups_args {
2591541Srgrimes	u_int	gidsetsize;
2601541Srgrimes	gid_t	*gidset;
2611541Srgrimes};
26212221Sbde#endif
2631549Srgrimesint
26430994Sphkgetgroups(p, uap)
2651541Srgrimes	struct proc *p;
2661541Srgrimes	register struct	getgroups_args *uap;
2671541Srgrimes{
2681541Srgrimes	register struct pcred *pc = p->p_cred;
2691541Srgrimes	register u_int ngrp;
2701541Srgrimes	int error;
2711541Srgrimes
2721541Srgrimes	if ((ngrp = uap->gidsetsize) == 0) {
27330994Sphk		p->p_retval[0] = pc->pc_ucred->cr_ngroups;
2741541Srgrimes		return (0);
2751541Srgrimes	}
2761541Srgrimes	if (ngrp < pc->pc_ucred->cr_ngroups)
2771541Srgrimes		return (EINVAL);
2781541Srgrimes	ngrp = pc->pc_ucred->cr_ngroups;
2793098Sphk	if ((error = copyout((caddr_t)pc->pc_ucred->cr_groups,
2803098Sphk	    (caddr_t)uap->gidset, ngrp * sizeof(gid_t))))
2811541Srgrimes		return (error);
28230994Sphk	p->p_retval[0] = ngrp;
2831541Srgrimes	return (0);
2841541Srgrimes}
2851541Srgrimes
28612221Sbde#ifndef _SYS_SYSPROTO_H_
28712207Sbdestruct setsid_args {
28811332Sswallace        int     dummy;
28911332Sswallace};
29012221Sbde#endif
29111332Sswallace
2921541Srgrimes/* ARGSUSED */
2931549Srgrimesint
29430994Sphksetsid(p, uap)
2951541Srgrimes	register struct proc *p;
29612207Sbde	struct setsid_args *uap;
2971541Srgrimes{
2981541Srgrimes
2991541Srgrimes	if (p->p_pgid == p->p_pid || pgfind(p->p_pid)) {
3001541Srgrimes		return (EPERM);
3011541Srgrimes	} else {
3021541Srgrimes		(void)enterpgrp(p, p->p_pid, 1);
30330994Sphk		p->p_retval[0] = p->p_pid;
3041541Srgrimes		return (0);
3051541Srgrimes	}
3061541Srgrimes}
3071541Srgrimes
3081541Srgrimes/*
3091541Srgrimes * set process group (setpgid/old setpgrp)
3101541Srgrimes *
3111541Srgrimes * caller does setpgid(targpid, targpgid)
3121541Srgrimes *
3131541Srgrimes * pid must be caller or child of caller (ESRCH)
3141541Srgrimes * if a child
3151541Srgrimes *	pid must be in same session (EPERM)
3161541Srgrimes *	pid can't have done an exec (EACCES)
3171541Srgrimes * if pgid != pid
3181541Srgrimes * 	there must exist some pid in same session having pgid (EPERM)
3191541Srgrimes * pid must not be session leader (EPERM)
3201541Srgrimes */
32112221Sbde#ifndef _SYS_SYSPROTO_H_
3221541Srgrimesstruct setpgid_args {
3231541Srgrimes	int	pid;	/* target process id */
3241541Srgrimes	int	pgid;	/* target pgrp id */
3251541Srgrimes};
32612221Sbde#endif
3271541Srgrimes/* ARGSUSED */
3281549Srgrimesint
32930994Sphksetpgid(curp, uap)
3301541Srgrimes	struct proc *curp;
3311541Srgrimes	register struct setpgid_args *uap;
3321541Srgrimes{
3331541Srgrimes	register struct proc *targp;		/* target process */
3341541Srgrimes	register struct pgrp *pgrp;		/* target pgrp */
3351541Srgrimes
33620677Sbde	if (uap->pgid < 0)
33720677Sbde		return (EINVAL);
3381541Srgrimes	if (uap->pid != 0 && uap->pid != curp->p_pid) {
3391541Srgrimes		if ((targp = pfind(uap->pid)) == 0 || !inferior(targp))
3401541Srgrimes			return (ESRCH);
34115985Sdg		if (targp->p_pgrp == NULL ||  targp->p_session != curp->p_session)
3421541Srgrimes			return (EPERM);
3431541Srgrimes		if (targp->p_flag & P_EXEC)
3441541Srgrimes			return (EACCES);
3451541Srgrimes	} else
3461541Srgrimes		targp = curp;
3471541Srgrimes	if (SESS_LEADER(targp))
3481541Srgrimes		return (EPERM);
3491541Srgrimes	if (uap->pgid == 0)
3501541Srgrimes		uap->pgid = targp->p_pid;
3511541Srgrimes	else if (uap->pgid != targp->p_pid)
3521541Srgrimes		if ((pgrp = pgfind(uap->pgid)) == 0 ||
3531541Srgrimes	            pgrp->pg_session != curp->p_session)
3541541Srgrimes			return (EPERM);
3551541Srgrimes	return (enterpgrp(targp, uap->pgid, 0));
3561541Srgrimes}
3571541Srgrimes
35824448Speter/*
35924448Speter * Use the clause in B.4.2.2 that allows setuid/setgid to be 4.2/4.3BSD
36024448Speter * compatable.  It says that setting the uid/gid to euid/egid is a special
36124448Speter * case of "appropriate privilege".  Once the rules are expanded out, this
36224448Speter * basically means that setuid(nnn) sets all three id's, in all permitted
36324448Speter * cases unless _POSIX_SAVED_IDS is enabled.  In that case, setuid(getuid())
36424448Speter * does not set the saved id - this is dangerous for traditional BSD
36524448Speter * programs.  For this reason, we *really* do not want to set
36624448Speter * _POSIX_SAVED_IDS and do not want to clear POSIX_APPENDIX_B_4_2_2.
36724448Speter */
36824448Speter#define POSIX_APPENDIX_B_4_2_2
36924448Speter
37012221Sbde#ifndef _SYS_SYSPROTO_H_
3711541Srgrimesstruct setuid_args {
3721541Srgrimes	uid_t	uid;
3731541Srgrimes};
37412221Sbde#endif
3751541Srgrimes/* ARGSUSED */
3761549Srgrimesint
37730994Sphksetuid(p, uap)
3781541Srgrimes	struct proc *p;
3791541Srgrimes	struct setuid_args *uap;
3801541Srgrimes{
3811541Srgrimes	register struct pcred *pc = p->p_cred;
3821541Srgrimes	register uid_t uid;
3831541Srgrimes	int error;
3841541Srgrimes
38524448Speter	/*
38624448Speter	 * See if we have "permission" by POSIX 1003.1 rules.
38724448Speter	 *
38824448Speter	 * Note that setuid(geteuid()) is a special case of
38924448Speter	 * "appropriate privileges" in appendix B.4.2.2.  We need
39024448Speter	 * to use this clause to be compatable with traditional BSD
39124448Speter	 * semantics.  Basically, it means that "setuid(xx)" sets all
39224448Speter	 * three id's (assuming you have privs).
39324448Speter	 *
39424448Speter	 * Notes on the logic.  We do things in three steps.
39524448Speter	 * 1: We determine if the euid is going to change, and do EPERM
39624448Speter	 *    right away.  We unconditionally change the euid later if this
39724448Speter	 *    test is satisfied, simplifying that part of the logic.
39824448Speter	 * 2: We determine if the real and/or saved uid's are going to
39924448Speter	 *    change.  Determined by compile options.
40024448Speter	 * 3: Change euid last. (after tests in #2 for "appropriate privs")
40124448Speter	 */
4021541Srgrimes	uid = uap->uid;
40324448Speter	if (uid != pc->p_ruid &&		/* allow setuid(getuid()) */
40417994Sache#ifdef _POSIX_SAVED_IDS
40524448Speter	    uid != pc->p_svuid &&		/* allow setuid(saved gid) */
40617994Sache#endif
40724448Speter#ifdef POSIX_APPENDIX_B_4_2_2	/* Use BSD-compat clause from B.4.2.2 */
40824448Speter	    uid != pc->pc_ucred->cr_uid &&	/* allow setuid(geteuid()) */
40924448Speter#endif
41046155Sphk	    (error = suser_xxx(0, p, PRISON_ROOT)))
4111541Srgrimes		return (error);
41224448Speter
41324448Speter#ifdef _POSIX_SAVED_IDS
4141541Srgrimes	/*
41524448Speter	 * Do we have "appropriate privileges" (are we root or uid == euid)
41624448Speter	 * If so, we are changing the real uid and/or saved uid.
4171541Srgrimes	 */
41817994Sache	if (
41924448Speter#ifdef POSIX_APPENDIX_B_4_2_2	/* Use the clause from B.4.2.2 */
42024448Speter	    uid == pc->pc_ucred->cr_uid ||
42117994Sache#endif
42246155Sphk	    suser_xxx(0, p, PRISON_ROOT) == 0) /* we are using privs */
42317994Sache#endif
42424448Speter	{
42524448Speter		/*
42624448Speter		 * Transfer proc count to new user.
42724448Speter		 */
42824448Speter		if (uid != pc->p_ruid) {
42924448Speter			(void)chgproccnt(pc->p_ruid, -1);
43024448Speter			(void)chgproccnt(uid, 1);
43124448Speter		}
43224448Speter		/*
43324448Speter		 * Set real uid
43424448Speter		 */
43524448Speter		if (uid != pc->p_ruid) {
43624448Speter			pc->p_ruid = uid;
43731891Ssef			setsugid(p);
43824448Speter		}
43924448Speter		/*
44024448Speter		 * Set saved uid
44124448Speter		 *
44224448Speter		 * XXX always set saved uid even if not _POSIX_SAVED_IDS, as
44324448Speter		 * the security of seteuid() depends on it.  B.4.2.2 says it
44424448Speter		 * is important that we should do this.
44524448Speter		 */
44624448Speter		if (pc->p_svuid != uid) {
44724448Speter			pc->p_svuid = uid;
44831891Ssef			setsugid(p);
44924448Speter		}
4508141Sache	}
45124448Speter
45224448Speter	/*
45324448Speter	 * In all permitted cases, we are changing the euid.
45424448Speter	 * Copy credentials so other references do not see our changes.
45524448Speter	 */
45624448Speter	if (pc->pc_ucred->cr_uid != uid) {
45724448Speter		pc->pc_ucred = crcopy(pc->pc_ucred);
45824448Speter		pc->pc_ucred->cr_uid = uid;
45931891Ssef		setsugid(p);
46024448Speter	}
4611541Srgrimes	return (0);
4621541Srgrimes}
4631541Srgrimes
46412221Sbde#ifndef _SYS_SYSPROTO_H_
4651541Srgrimesstruct seteuid_args {
4661541Srgrimes	uid_t	euid;
4671541Srgrimes};
46812221Sbde#endif
4691541Srgrimes/* ARGSUSED */
4701549Srgrimesint
47130994Sphkseteuid(p, uap)
4721541Srgrimes	struct proc *p;
4731541Srgrimes	struct seteuid_args *uap;
4741541Srgrimes{
4751541Srgrimes	register struct pcred *pc = p->p_cred;
4761541Srgrimes	register uid_t euid;
4771541Srgrimes	int error;
4781541Srgrimes
4791541Srgrimes	euid = uap->euid;
48024449Speter	if (euid != pc->p_ruid &&		/* allow seteuid(getuid()) */
48124449Speter	    euid != pc->p_svuid &&		/* allow seteuid(saved uid) */
48246155Sphk	    (error = suser_xxx(0, p, PRISON_ROOT)))
4831541Srgrimes		return (error);
4841541Srgrimes	/*
4851541Srgrimes	 * Everything's okay, do it.  Copy credentials so other references do
4861541Srgrimes	 * not see our changes.
4871541Srgrimes	 */
48824449Speter	if (pc->pc_ucred->cr_uid != euid) {
48924449Speter		pc->pc_ucred = crcopy(pc->pc_ucred);
49024449Speter		pc->pc_ucred->cr_uid = euid;
49131891Ssef		setsugid(p);
49224449Speter	}
4931541Srgrimes	return (0);
4941541Srgrimes}
4951541Srgrimes
49612221Sbde#ifndef _SYS_SYSPROTO_H_
4971541Srgrimesstruct setgid_args {
4981541Srgrimes	gid_t	gid;
4991541Srgrimes};
50012221Sbde#endif
5011541Srgrimes/* ARGSUSED */
5021549Srgrimesint
50330994Sphksetgid(p, uap)
5041541Srgrimes	struct proc *p;
5051541Srgrimes	struct setgid_args *uap;
5061541Srgrimes{
5071541Srgrimes	register struct pcred *pc = p->p_cred;
5081541Srgrimes	register gid_t gid;
5091541Srgrimes	int error;
5101541Srgrimes
51124448Speter	/*
51224448Speter	 * See if we have "permission" by POSIX 1003.1 rules.
51324448Speter	 *
51424448Speter	 * Note that setgid(getegid()) is a special case of
51524448Speter	 * "appropriate privileges" in appendix B.4.2.2.  We need
51624448Speter	 * to use this clause to be compatable with traditional BSD
51724448Speter	 * semantics.  Basically, it means that "setgid(xx)" sets all
51824448Speter	 * three id's (assuming you have privs).
51924448Speter	 *
52024448Speter	 * For notes on the logic here, see setuid() above.
52124448Speter	 */
5221541Srgrimes	gid = uap->gid;
52324448Speter	if (gid != pc->p_rgid &&		/* allow setgid(getgid()) */
52417994Sache#ifdef _POSIX_SAVED_IDS
52524448Speter	    gid != pc->p_svgid &&		/* allow setgid(saved gid) */
52617994Sache#endif
52724448Speter#ifdef POSIX_APPENDIX_B_4_2_2	/* Use BSD-compat clause from B.4.2.2 */
52824448Speter	    gid != pc->pc_ucred->cr_groups[0] && /* allow setgid(getegid()) */
52924448Speter#endif
53046155Sphk	    (error = suser_xxx(0, p, PRISON_ROOT)))
5311541Srgrimes		return (error);
53224448Speter
53317994Sache#ifdef _POSIX_SAVED_IDS
53424448Speter	/*
53524448Speter	 * Do we have "appropriate privileges" (are we root or gid == egid)
53624448Speter	 * If so, we are changing the real uid and saved gid.
53724448Speter	 */
53824448Speter	if (
53924448Speter#ifdef POSIX_APPENDIX_B_4_2_2	/* use the clause from B.4.2.2 */
54024448Speter	    gid == pc->pc_ucred->cr_groups[0] ||
54117994Sache#endif
54246155Sphk	    suser_xxx(0, p, PRISON_ROOT) == 0) /* we are using privs */
54324448Speter#endif
54424448Speter	{
54524448Speter		/*
54624448Speter		 * Set real gid
54724448Speter		 */
54824448Speter		if (pc->p_rgid != gid) {
54924448Speter			pc->p_rgid = gid;
55031891Ssef			setsugid(p);
55124448Speter		}
55224448Speter		/*
55324448Speter		 * Set saved gid
55424448Speter		 *
55524448Speter		 * XXX always set saved gid even if not _POSIX_SAVED_IDS, as
55624448Speter		 * the security of setegid() depends on it.  B.4.2.2 says it
55724448Speter		 * is important that we should do this.
55824448Speter		 */
55924448Speter		if (pc->p_svgid != gid) {
56024448Speter			pc->p_svgid = gid;
56131891Ssef			setsugid(p);
56224448Speter		}
5638141Sache	}
56424448Speter	/*
56524448Speter	 * In all cases permitted cases, we are changing the egid.
56624448Speter	 * Copy credentials so other references do not see our changes.
56724448Speter	 */
56824448Speter	if (pc->pc_ucred->cr_groups[0] != gid) {
56924448Speter		pc->pc_ucred = crcopy(pc->pc_ucred);
57024448Speter		pc->pc_ucred->cr_groups[0] = gid;
57131891Ssef		setsugid(p);
57224448Speter	}
5731541Srgrimes	return (0);
5741541Srgrimes}
5751541Srgrimes
57612221Sbde#ifndef _SYS_SYSPROTO_H_
5771541Srgrimesstruct setegid_args {
5781541Srgrimes	gid_t	egid;
5791541Srgrimes};
58012221Sbde#endif
5811541Srgrimes/* ARGSUSED */
5821549Srgrimesint
58330994Sphksetegid(p, uap)
5841541Srgrimes	struct proc *p;
5851541Srgrimes	struct setegid_args *uap;
5861541Srgrimes{
5871541Srgrimes	register struct pcred *pc = p->p_cred;
5881541Srgrimes	register gid_t egid;
5891541Srgrimes	int error;
5901541Srgrimes
5911541Srgrimes	egid = uap->egid;
59224449Speter	if (egid != pc->p_rgid &&		/* allow setegid(getgid()) */
59324449Speter	    egid != pc->p_svgid &&		/* allow setegid(saved gid) */
59446155Sphk	    (error = suser_xxx(0, p, PRISON_ROOT)))
5951541Srgrimes		return (error);
59624449Speter	if (pc->pc_ucred->cr_groups[0] != egid) {
59724449Speter		pc->pc_ucred = crcopy(pc->pc_ucred);
59824449Speter		pc->pc_ucred->cr_groups[0] = egid;
59931891Ssef		setsugid(p);
60024449Speter	}
6011541Srgrimes	return (0);
6021541Srgrimes}
6031541Srgrimes
60412221Sbde#ifndef _SYS_SYSPROTO_H_
6051541Srgrimesstruct setgroups_args {
6061541Srgrimes	u_int	gidsetsize;
6071541Srgrimes	gid_t	*gidset;
6081541Srgrimes};
60912221Sbde#endif
6101541Srgrimes/* ARGSUSED */
6111549Srgrimesint
61230994Sphksetgroups(p, uap)
6131541Srgrimes	struct proc *p;
6141541Srgrimes	struct setgroups_args *uap;
6151541Srgrimes{
6161541Srgrimes	register struct pcred *pc = p->p_cred;
6171541Srgrimes	register u_int ngrp;
6181541Srgrimes	int error;
6191541Srgrimes
62046155Sphk	if ((error = suser_xxx(0, p, PRISON_ROOT)))
6211541Srgrimes		return (error);
62212063Sdg	ngrp = uap->gidsetsize;
62324447Speter	if (ngrp > NGROUPS)
6241541Srgrimes		return (EINVAL);
62524447Speter	/*
62624447Speter	 * XXX A little bit lazy here.  We could test if anything has
62724447Speter	 * changed before crcopy() and setting P_SUGID.
62824447Speter	 */
6291541Srgrimes	pc->pc_ucred = crcopy(pc->pc_ucred);
63024447Speter	if (ngrp < 1) {
63124447Speter		/*
63224447Speter		 * setgroups(0, NULL) is a legitimate way of clearing the
63324447Speter		 * groups vector on non-BSD systems (which generally do not
63424447Speter		 * have the egid in the groups[0]).  We risk security holes
63524447Speter		 * when running non-BSD software if we do not do the same.
63624447Speter		 */
63724447Speter		pc->pc_ucred->cr_ngroups = 1;
63824447Speter	} else {
63924447Speter		if ((error = copyin((caddr_t)uap->gidset,
64024447Speter		    (caddr_t)pc->pc_ucred->cr_groups, ngrp * sizeof(gid_t))))
64124447Speter			return (error);
64224447Speter		pc->pc_ucred->cr_ngroups = ngrp;
64324447Speter	}
64431891Ssef	setsugid(p);
6451541Srgrimes	return (0);
6461541Srgrimes}
6471541Srgrimes
64812221Sbde#ifndef _SYS_SYSPROTO_H_
6491541Srgrimesstruct setreuid_args {
6509238Sache	uid_t	ruid;
6519238Sache	uid_t	euid;
6521541Srgrimes};
65312221Sbde#endif
6541541Srgrimes/* ARGSUSED */
6551549Srgrimesint
65630994Sphksetreuid(p, uap)
6571541Srgrimes	register struct proc *p;
6581541Srgrimes	struct setreuid_args *uap;
6591541Srgrimes{
6601541Srgrimes	register struct pcred *pc = p->p_cred;
6619238Sache	register uid_t ruid, euid;
6628135Sache	int error;
6631541Srgrimes
6649238Sache	ruid = uap->ruid;
6659238Sache	euid = uap->euid;
66643311Sdillon	if (((ruid != (uid_t)-1 && ruid != pc->p_ruid && ruid != pc->p_svuid) ||
66743311Sdillon	     (euid != (uid_t)-1 && euid != pc->pc_ucred->cr_uid &&
66843311Sdillon	     euid != pc->p_ruid && euid != pc->p_svuid)) &&
66946155Sphk	    (error = suser_xxx(0, p, PRISON_ROOT)) != 0)
6708135Sache		return (error);
6719238Sache
67224450Speter	if (euid != (uid_t)-1 && pc->pc_ucred->cr_uid != euid) {
67324450Speter		pc->pc_ucred = crcopy(pc->pc_ucred);
6749238Sache		pc->pc_ucred->cr_uid = euid;
67531891Ssef		setsugid(p);
67624450Speter	}
67724450Speter	if (ruid != (uid_t)-1 && pc->p_ruid != ruid) {
6789238Sache		(void)chgproccnt(pc->p_ruid, -1);
6799238Sache		(void)chgproccnt(ruid, 1);
6809238Sache		pc->p_ruid = ruid;
68131891Ssef		setsugid(p);
6828135Sache	}
68324559Speter	if ((ruid != (uid_t)-1 || pc->pc_ucred->cr_uid != pc->p_ruid) &&
68424559Speter	    pc->p_svuid != pc->pc_ucred->cr_uid) {
6858111Sache		pc->p_svuid = pc->pc_ucred->cr_uid;
68631891Ssef		setsugid(p);
68724450Speter	}
6888135Sache	return (0);
6891541Srgrimes}
6901541Srgrimes
69112221Sbde#ifndef _SYS_SYSPROTO_H_
6921541Srgrimesstruct setregid_args {
6939238Sache	gid_t	rgid;
6949238Sache	gid_t	egid;
6951541Srgrimes};
69612221Sbde#endif
6971541Srgrimes/* ARGSUSED */
6981549Srgrimesint
69930994Sphksetregid(p, uap)
7001541Srgrimes	register struct proc *p;
7011541Srgrimes	struct setregid_args *uap;
7021541Srgrimes{
7031541Srgrimes	register struct pcred *pc = p->p_cred;
7049238Sache	register gid_t rgid, egid;
7058135Sache	int error;
7061541Srgrimes
7079238Sache	rgid = uap->rgid;
7089238Sache	egid = uap->egid;
70943311Sdillon	if (((rgid != (gid_t)-1 && rgid != pc->p_rgid && rgid != pc->p_svgid) ||
71043311Sdillon	     (egid != (gid_t)-1 && egid != pc->pc_ucred->cr_groups[0] &&
71143311Sdillon	     egid != pc->p_rgid && egid != pc->p_svgid)) &&
71246155Sphk	    (error = suser_xxx(0, p, PRISON_ROOT)) != 0)
7138135Sache		return (error);
7149238Sache
71524450Speter	if (egid != (gid_t)-1 && pc->pc_ucred->cr_groups[0] != egid) {
71624450Speter		pc->pc_ucred = crcopy(pc->pc_ucred);
7179238Sache		pc->pc_ucred->cr_groups[0] = egid;
71831891Ssef		setsugid(p);
71924450Speter	}
72024450Speter	if (rgid != (gid_t)-1 && pc->p_rgid != rgid) {
7219238Sache		pc->p_rgid = rgid;
72231891Ssef		setsugid(p);
72324450Speter	}
72424559Speter	if ((rgid != (gid_t)-1 || pc->pc_ucred->cr_groups[0] != pc->p_rgid) &&
72524559Speter	    pc->p_svgid != pc->pc_ucred->cr_groups[0]) {
7268111Sache		pc->p_svgid = pc->pc_ucred->cr_groups[0];
72731891Ssef		setsugid(p);
72824450Speter	}
7298135Sache	return (0);
7301541Srgrimes}
7311541Srgrimes
73256115Speter/*
73356115Speter * setresuid(ruid, euid, suid) is like setreuid except control over the
73456115Speter * saved uid is explicit.
73556115Speter */
73656115Speter
73724453Speter#ifndef _SYS_SYSPROTO_H_
73856115Speterstruct setresuid_args {
73956115Speter	uid_t	ruid;
74056115Speter	uid_t	euid;
74156115Speter	uid_t	suid;
74256115Speter};
74356115Speter#endif
74456115Speter/* ARGSUSED */
74556115Speterint
74656115Spetersetresuid(p, uap)
74756115Speter	register struct proc *p;
74856115Speter	struct setresuid_args *uap;
74956115Speter{
75056115Speter	register struct pcred *pc = p->p_cred;
75156115Speter	register uid_t ruid, euid, suid;
75256115Speter	int error;
75356115Speter
75456115Speter	ruid = uap->ruid;
75556115Speter	euid = uap->euid;
75656115Speter	suid = uap->suid;
75756115Speter	if (((ruid != (uid_t)-1 && ruid != pc->p_ruid && ruid != pc->p_svuid &&
75856115Speter	      ruid != pc->pc_ucred->cr_uid) ||
75956115Speter	     (euid != (uid_t)-1 && euid != pc->p_ruid && euid != pc->p_svuid &&
76056115Speter	      euid != pc->pc_ucred->cr_uid) ||
76156115Speter	     (suid != (uid_t)-1 && suid != pc->p_ruid && suid != pc->p_svuid &&
76256115Speter	      suid != pc->pc_ucred->cr_uid)) &&
76356115Speter	    (error = suser_xxx(0, p, PRISON_ROOT)) != 0)
76456115Speter		return (error);
76556115Speter	if (euid != (uid_t)-1 && pc->pc_ucred->cr_uid != euid) {
76656115Speter		pc->pc_ucred = crcopy(pc->pc_ucred);
76756115Speter		pc->pc_ucred->cr_uid = euid;
76856115Speter		setsugid(p);
76956115Speter	}
77056115Speter	if (ruid != (uid_t)-1 && pc->p_ruid != ruid) {
77156115Speter		(void)chgproccnt(pc->p_ruid, -1);
77256115Speter		(void)chgproccnt(ruid, 1);
77356115Speter		pc->p_ruid = ruid;
77456115Speter		setsugid(p);
77556115Speter	}
77656115Speter	if (suid != (uid_t)-1 && pc->p_svuid != suid) {
77756115Speter		pc->p_svuid = suid;
77856115Speter		setsugid(p);
77956115Speter	}
78056115Speter	return (0);
78156115Speter}
78256115Speter
78356115Speter/*
78456115Speter * setresgid(rgid, egid, sgid) is like setregid except control over the
78556115Speter * saved gid is explicit.
78656115Speter */
78756115Speter
78856115Speter#ifndef _SYS_SYSPROTO_H_
78956115Speterstruct setresgid_args {
79056115Speter	gid_t	rgid;
79156115Speter	gid_t	egid;
79256115Speter	gid_t	sgid;
79356115Speter};
79456115Speter#endif
79556115Speter/* ARGSUSED */
79656115Speterint
79756115Spetersetresgid(p, uap)
79856115Speter	register struct proc *p;
79956115Speter	struct setresgid_args *uap;
80056115Speter{
80156115Speter	register struct pcred *pc = p->p_cred;
80256115Speter	register gid_t rgid, egid, sgid;
80356115Speter	int error;
80456115Speter
80556115Speter	rgid = uap->rgid;
80656115Speter	egid = uap->egid;
80756115Speter	sgid = uap->sgid;
80856115Speter	if (((rgid != (gid_t)-1 && rgid != pc->p_rgid && rgid != pc->p_svgid &&
80956115Speter	      rgid != pc->pc_ucred->cr_groups[0]) ||
81056115Speter	     (egid != (gid_t)-1 && egid != pc->p_rgid && egid != pc->p_svgid &&
81156115Speter	      egid != pc->pc_ucred->cr_groups[0]) ||
81256115Speter	     (sgid != (gid_t)-1 && sgid != pc->p_rgid && sgid != pc->p_svgid &&
81356115Speter	      sgid != pc->pc_ucred->cr_groups[0])) &&
81456115Speter	    (error = suser_xxx(0, p, PRISON_ROOT)) != 0)
81556115Speter		return (error);
81656115Speter
81756115Speter	if (egid != (gid_t)-1 && pc->pc_ucred->cr_groups[0] != egid) {
81856115Speter		pc->pc_ucred = crcopy(pc->pc_ucred);
81956115Speter		pc->pc_ucred->cr_groups[0] = egid;
82056115Speter		setsugid(p);
82156115Speter	}
82256115Speter	if (rgid != (gid_t)-1 && pc->p_rgid != rgid) {
82356115Speter		pc->p_rgid = rgid;
82456115Speter		setsugid(p);
82556115Speter	}
82656115Speter	if (sgid != (gid_t)-1 && pc->p_svgid != sgid) {
82756115Speter		pc->p_svgid = sgid;
82856115Speter		setsugid(p);
82956115Speter	}
83056115Speter	return (0);
83156115Speter}
83256115Speter
83356115Speter#ifndef _SYS_SYSPROTO_H_
83456115Speterstruct getresuid_args {
83556115Speter	uid_t	*ruid;
83656115Speter	uid_t	*euid;
83756115Speter	uid_t	*suid;
83856115Speter};
83956115Speter#endif
84056115Speter/* ARGSUSED */
84156115Speterint
84256115Spetergetresuid(p, uap)
84356115Speter	register struct proc *p;
84456115Speter	struct getresuid_args *uap;
84556115Speter{
84656115Speter	struct pcred *pc = p->p_cred;
84756115Speter	int error1 = 0, error2 = 0, error3 = 0;
84856115Speter
84956115Speter	if (uap->ruid)
85056115Speter		error1 = copyout((caddr_t)&pc->p_ruid,
85156115Speter		    (caddr_t)uap->ruid, sizeof(pc->p_ruid));
85256115Speter	if (uap->euid)
85356115Speter		error2 = copyout((caddr_t)&pc->pc_ucred->cr_uid,
85456115Speter		    (caddr_t)uap->euid, sizeof(pc->pc_ucred->cr_uid));
85556115Speter	if (uap->suid)
85656115Speter		error3 = copyout((caddr_t)&pc->p_svuid,
85756115Speter		    (caddr_t)uap->suid, sizeof(pc->p_svuid));
85856115Speter	return error1 ? error1 : (error2 ? error2 : error3);
85956115Speter}
86056115Speter
86156115Speter#ifndef _SYS_SYSPROTO_H_
86256115Speterstruct getresgid_args {
86356115Speter	gid_t	*rgid;
86456115Speter	gid_t	*egid;
86556115Speter	gid_t	*sgid;
86656115Speter};
86756115Speter#endif
86856115Speter/* ARGSUSED */
86956115Speterint
87056115Spetergetresgid(p, uap)
87156115Speter	register struct proc *p;
87256115Speter	struct getresgid_args *uap;
87356115Speter{
87456115Speter	struct pcred *pc = p->p_cred;
87556115Speter	int error1 = 0, error2 = 0, error3 = 0;
87656115Speter
87756115Speter	if (uap->rgid)
87856115Speter		error1 = copyout((caddr_t)&pc->p_rgid,
87956115Speter		    (caddr_t)uap->rgid, sizeof(pc->p_rgid));
88056115Speter	if (uap->egid)
88156115Speter		error2 = copyout((caddr_t)&pc->pc_ucred->cr_groups[0],
88256115Speter		    (caddr_t)uap->egid, sizeof(pc->pc_ucred->cr_groups[0]));
88356115Speter	if (uap->sgid)
88456115Speter		error3 = copyout((caddr_t)&pc->p_svgid,
88556115Speter		    (caddr_t)uap->sgid, sizeof(pc->p_svgid));
88656115Speter	return error1 ? error1 : (error2 ? error2 : error3);
88756115Speter}
88856115Speter
88956115Speter
89056115Speter#ifndef _SYS_SYSPROTO_H_
89124453Speterstruct issetugid_args {
89224453Speter	int dummy;
89324453Speter};
89424453Speter#endif
89524453Speter/* ARGSUSED */
89624453Speterint
89730994Sphkissetugid(p, uap)
89824453Speter	register struct proc *p;
89924453Speter	struct issetugid_args *uap;
90024453Speter{
90124453Speter	/*
90224453Speter	 * Note: OpenBSD sets a P_SUGIDEXEC flag set at execve() time,
90324453Speter	 * we use P_SUGID because we consider changing the owners as
90424453Speter	 * "tainting" as well.
90524453Speter	 * This is significant for procs that start as root and "become"
90624453Speter	 * a user without an exec - programs cannot know *everything*
90724453Speter	 * that libc *might* have put in their data segment.
90824453Speter	 */
90924453Speter	if (p->p_flag & P_SUGID)
91024453Speter		return (1);
91124453Speter	return (0);
91224453Speter}
91324453Speter
9141541Srgrimes/*
9151541Srgrimes * Check if gid is a member of the group set.
9161541Srgrimes */
9171549Srgrimesint
9181541Srgrimesgroupmember(gid, cred)
9191541Srgrimes	gid_t gid;
9201541Srgrimes	register struct ucred *cred;
9211541Srgrimes{
9221541Srgrimes	register gid_t *gp;
9231541Srgrimes	gid_t *egp;
9241541Srgrimes
9251541Srgrimes	egp = &(cred->cr_groups[cred->cr_ngroups]);
9261541Srgrimes	for (gp = cred->cr_groups; gp < egp; gp++)
9271541Srgrimes		if (*gp == gid)
9281541Srgrimes			return (1);
9291541Srgrimes	return (0);
9301541Srgrimes}
9311541Srgrimes
9321541Srgrimes/*
9331541Srgrimes * Test whether the specified credentials imply "super-user"
9341541Srgrimes * privilege; if so, and we have accounting info, set the flag
9351541Srgrimes * indicating use of super-powers.
9361541Srgrimes * Returns 0 or error.
9371541Srgrimes */
9381549Srgrimesint
93946112Sphksuser(p)
94046112Sphk	struct proc *p;
94146112Sphk{
94246155Sphk	return suser_xxx(0, p, 0);
94346112Sphk}
94446112Sphk
94546112Sphkint
94646155Sphksuser_xxx(cred, proc, flag)
9471541Srgrimes	struct ucred *cred;
94846155Sphk	struct proc *proc;
94946155Sphk	int flag;
9501541Srgrimes{
95146155Sphk	if (!cred && !proc) {
95246155Sphk		printf("suser_xxx(): THINK!\n");
95346155Sphk		return (EPERM);
9541541Srgrimes	}
95546155Sphk	if (!cred)
95646155Sphk		cred = proc->p_ucred;
95746155Sphk	if (cred->cr_uid != 0)
95846155Sphk		return (EPERM);
95946155Sphk	if (proc && proc->p_prison && !(flag & PRISON_ROOT))
96046155Sphk		return (EPERM);
96146155Sphk	if (proc)
96246155Sphk		proc->p_acflag |= ASU;
96346155Sphk	return (0);
9641541Srgrimes}
9651541Srgrimes
9661541Srgrimes/*
96753518Sphk * Return zero if p1 can fondle p2, return errno (EPERM/ESRCH) otherwise.
96853518Sphk */
96953518Sphk
97053518Sphkint
97153518Sphkp_trespass(struct proc *p1, struct proc *p2)
97253518Sphk{
97353518Sphk
97453518Sphk	if (p1 == p2)
97553518Sphk		return (0);
97653518Sphk	if (!PRISON_CHECK(p1, p2))
97753518Sphk		return (ESRCH);
97853518Sphk	if (p1->p_cred->p_ruid == p2->p_cred->p_ruid)
97953518Sphk		return (0);
98053518Sphk	if (p1->p_ucred->cr_uid == p2->p_cred->p_ruid)
98153518Sphk		return (0);
98253518Sphk	if (p1->p_cred->p_ruid == p2->p_ucred->cr_uid)
98353518Sphk		return (0);
98453518Sphk	if (p1->p_ucred->cr_uid == p2->p_ucred->cr_uid)
98553518Sphk		return (0);
98653518Sphk	if (!suser_xxx(0, p1, PRISON_ROOT))
98753518Sphk		return (0);
98853518Sphk	return (EPERM);
98953518Sphk}
99053518Sphk
99153518Sphk/*
9921541Srgrimes * Allocate a zeroed cred structure.
9931541Srgrimes */
9941541Srgrimesstruct ucred *
9951541Srgrimescrget()
9961541Srgrimes{
9971541Srgrimes	register struct ucred *cr;
9981541Srgrimes
9991541Srgrimes	MALLOC(cr, struct ucred *, sizeof(*cr), M_CRED, M_WAITOK);
10001541Srgrimes	bzero((caddr_t)cr, sizeof(*cr));
10011541Srgrimes	cr->cr_ref = 1;
10021541Srgrimes	return (cr);
10031541Srgrimes}
10041541Srgrimes
10051541Srgrimes/*
10061541Srgrimes * Free a cred structure.
10071541Srgrimes * Throws away space when ref count gets to 0.
10081541Srgrimes */
10091549Srgrimesvoid
10101541Srgrimescrfree(cr)
10111541Srgrimes	struct ucred *cr;
10121541Srgrimes{
10131541Srgrimes	if (--cr->cr_ref == 0)
10141541Srgrimes		FREE((caddr_t)cr, M_CRED);
10151541Srgrimes}
10161541Srgrimes
10171541Srgrimes/*
10181541Srgrimes * Copy cred structure to a new one and free the old one.
10191541Srgrimes */
10201541Srgrimesstruct ucred *
10211541Srgrimescrcopy(cr)
10221541Srgrimes	struct ucred *cr;
10231541Srgrimes{
10241541Srgrimes	struct ucred *newcr;
10251541Srgrimes
10261541Srgrimes	if (cr->cr_ref == 1)
10271541Srgrimes		return (cr);
10281541Srgrimes	newcr = crget();
10291541Srgrimes	*newcr = *cr;
10301541Srgrimes	crfree(cr);
10311541Srgrimes	newcr->cr_ref = 1;
10321541Srgrimes	return (newcr);
10331541Srgrimes}
10341541Srgrimes
10351541Srgrimes/*
10361541Srgrimes * Dup cred struct to a new held one.
10371541Srgrimes */
10381541Srgrimesstruct ucred *
10391541Srgrimescrdup(cr)
10401541Srgrimes	struct ucred *cr;
10411541Srgrimes{
10421541Srgrimes	struct ucred *newcr;
10431541Srgrimes
10441541Srgrimes	newcr = crget();
10451541Srgrimes	*newcr = *cr;
10461541Srgrimes	newcr->cr_ref = 1;
10471541Srgrimes	return (newcr);
10481541Srgrimes}
10491541Srgrimes
10501541Srgrimes/*
10511541Srgrimes * Get login name, if available.
10521541Srgrimes */
105312221Sbde#ifndef _SYS_SYSPROTO_H_
10541541Srgrimesstruct getlogin_args {
10551541Srgrimes	char	*namebuf;
10561541Srgrimes	u_int	namelen;
10571541Srgrimes};
105812221Sbde#endif
10591541Srgrimes/* ARGSUSED */
10601549Srgrimesint
106130994Sphkgetlogin(p, uap)
10621541Srgrimes	struct proc *p;
10631541Srgrimes	struct getlogin_args *uap;
10641541Srgrimes{
10651541Srgrimes
106623358Sache	if (uap->namelen > MAXLOGNAME)
106723359Sache		uap->namelen = MAXLOGNAME;
10681541Srgrimes	return (copyout((caddr_t) p->p_pgrp->pg_session->s_login,
10691541Srgrimes	    (caddr_t) uap->namebuf, uap->namelen));
10701541Srgrimes}
10711541Srgrimes
10721541Srgrimes/*
10731541Srgrimes * Set login name.
10741541Srgrimes */
107512221Sbde#ifndef _SYS_SYSPROTO_H_
10761541Srgrimesstruct setlogin_args {
10771541Srgrimes	char	*namebuf;
10781541Srgrimes};
107912221Sbde#endif
10801541Srgrimes/* ARGSUSED */
10811549Srgrimesint
108230994Sphksetlogin(p, uap)
10831541Srgrimes	struct proc *p;
10841541Srgrimes	struct setlogin_args *uap;
10851541Srgrimes{
10861541Srgrimes	int error;
108723330Sache	char logintmp[MAXLOGNAME];
10881541Srgrimes
108946155Sphk	if ((error = suser_xxx(0, p, PRISON_ROOT)))
10901541Srgrimes		return (error);
109122522Sdavidn	error = copyinstr((caddr_t) uap->namebuf, (caddr_t) logintmp,
109236845Sdfr	    sizeof(logintmp), (size_t *)0);
10931541Srgrimes	if (error == ENAMETOOLONG)
10941541Srgrimes		error = EINVAL;
109522522Sdavidn	else if (!error)
109622522Sdavidn		(void) memcpy(p->p_pgrp->pg_session->s_login, logintmp,
109723330Sache		    sizeof(logintmp));
10981541Srgrimes	return (error);
10991541Srgrimes}
110031891Ssef
110131891Ssefvoid
110231891Ssefsetsugid(p)
110355338Sphk	struct proc *p;
110431891Ssef{
110531891Ssef	p->p_flag |= P_SUGID;
110655707Ssef	if (!(p->p_pfsflags & PF_ISUGID))
110731891Ssef		p->p_stops = 0;
110831891Ssef}
1109