kern_prot.c revision 76166
11541Srgrimes/*
210937Swollman * 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)
3310937Swollman * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3450477Speter * 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.
372169Spaul *
382169Spaul *	@(#)kern_prot.c	8.6 (Berkeley) 1/21/94
3986764Sjlemon * $FreeBSD: head/sys/kern/kern_prot.c 76166 2001-05-01 08:13:21Z markm $
4086764Sjlemon */
4198102Shsu
4286764Sjlemon/*
431541Srgrimes * System calls related to processes and protection
441541Srgrimes */
451541Srgrimes
4686764Sjlemon#include "opt_compat.h"
4786764Sjlemon#include "opt_global.h"
481541Srgrimes
4955679Sshin#include <sys/param.h>
5055679Sshin#include <sys/systm.h>
5160938Sjake#include <sys/acct.h>
5255679Sshin#include <sys/kernel.h>
5355679Sshin#include <sys/lock.h>
5455679Sshin#include <sys/mutex.h>
5555679Sshin#include <sys/proc.h>
5660938Sjake#include <sys/sysproto.h>
5755679Sshin#include <sys/malloc.h>
5855679Sshin#include <sys/pioctl.h>
5955679Sshin#include <sys/resourcevar.h>
6055679Sshin#include <sys/sysctl.h>
6155679Sshin#include <sys/jail.h>
6255679Sshin
6355679Sshinstatic MALLOC_DEFINE(M_CRED, "cred", "credentials");
6455679Sshin
6555679Sshin#ifndef _SYS_SYSPROTO_H_
6655679Sshinstruct getpid_args {
6755679Sshin	int	dummy;
681541Srgrimes};
691541Srgrimes#endif
7032821Sdg
711541Srgrimes/*
721541Srgrimes * getpid - MP SAFE
7355679Sshin */
7432821Sdg
7578642Ssilby/* ARGSUSED */
7632821Sdgint
7750673Sjlemongetpid(p, uap)
7850673Sjlemon	struct proc *p;
7950673Sjlemon	struct getpid_args *uap;
8050673Sjlemon{
8150673Sjlemon
8232821Sdg	p->p_retval[0] = p->p_pid;
8332821Sdg#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
8411187Swollman	PROC_LOCK(p);
8511187Swollman	p->p_retval[1] = p->p_pptr->p_pid;
86117650Shsu	PROC_UNLOCK(p);
87117650Shsu#endif
88117650Shsu	return (0);
89117650Shsu}
90117650Shsu
91117650Shsu/*
92117650Shsu * getppid - MP SAFE
93117650Shsu */
94117650Shsu
95117650Shsu#ifndef _SYS_SYSPROTO_H_
96117650Shsustruct getppid_args {
97117650Shsu        int     dummy;
98117650Shsu};
99117650Shsu#endif
100117650Shsu/* ARGSUSED */
101117650Shsuint
102117650Shsugetppid(p, uap)
103117650Shsu	struct proc *p;
104117650Shsu	struct getppid_args *uap;
105117650Shsu{
106117650Shsu
107117650Shsu	PROC_LOCK(p);
10832821Sdg	p->p_retval[0] = p->p_pptr->p_pid;
1091541Srgrimes	PROC_UNLOCK(p);
1101541Srgrimes	return (0);
11132821Sdg}
11232821Sdg
11332821Sdg/*
1141541Srgrimes * Get process group ID; note that POSIX getpgrp takes no parameter
1151541Srgrimes *
11632821Sdg * MP SAFE
1171541Srgrimes */
1181541Srgrimes#ifndef _SYS_SYSPROTO_H_
1191541Srgrimesstruct getpgrp_args {
12032821Sdg        int     dummy;
12132821Sdg};
12232821Sdg#endif
12332821Sdg
1241541Srgrimesint
1251541Srgrimesgetpgrp(p, uap)
12632821Sdg	struct proc *p;
12732821Sdg	struct getpgrp_args *uap;
1281541Srgrimes{
129102017Sdillon
13013765Smpp	p->p_retval[0] = p->p_pgrp->pg_id;
1311541Srgrimes	return (0);
1321541Srgrimes}
1331541Srgrimes
134102017Sdillon/* Get an arbitary pid's process group id */
135109175Shsu#ifndef _SYS_SYSPROTO_H_
13660067Sjlemonstruct getpgid_args {
13732821Sdg	pid_t	pid;
13832821Sdg};
13950673Sjlemon#endif
14050673Sjlemon
14150673Sjlemonint
1421541Srgrimesgetpgid(p, uap)
14332821Sdg	struct proc *p;
144102017Sdillon	struct getpgid_args *uap;
145102017Sdillon{
146102017Sdillon	struct proc *pt;
14750673Sjlemon	int error;
14832821Sdg
14911187Swollman	if (uap->pid == 0)
15011187Swollman		p->p_retval[0] = p->p_pgrp->pg_id;
15132821Sdg	else {
15232821Sdg		if ((pt = pfind(uap->pid)) == NULL)
15311187Swollman			return ESRCH;
154102017Sdillon		if ((error = p_can(p, pt, P_CAN_SEE, NULL))) {
15532821Sdg			PROC_UNLOCK(pt);
1561541Srgrimes			return (error);
1571541Srgrimes		}
15832821Sdg		p->p_retval[0] = pt->p_pgrp->pg_id;
1591541Srgrimes		PROC_UNLOCK(pt);
1601541Srgrimes	}
1611541Srgrimes	return 0;
1621541Srgrimes}
1631541Srgrimes
1641541Srgrimes/*
1651541Srgrimes * Get an arbitary pid's session id.
1661541Srgrimes */
1671541Srgrimes#ifndef _SYS_SYSPROTO_H_
1681541Srgrimesstruct getsid_args {
1691541Srgrimes	pid_t	pid;
17032821Sdg};
1711541Srgrimes#endif
1721541Srgrimes
1736247Swollmanint
1746247Swollmangetsid(p, uap)
1756247Swollman	struct proc *p;
17650673Sjlemon	struct getsid_args *uap;
17750673Sjlemon{
17850673Sjlemon	struct proc *pt;
179117650Shsu	int error;
18050673Sjlemon
181112957Shsu	if (uap->pid == 0)
1821541Srgrimes		p->p_retval[0] = p->p_session->s_sid;
1831541Srgrimes	else {
184117650Shsu		if ((pt = pfind(uap->pid)) == NULL)
185117650Shsu			return ESRCH;
186117650Shsu		if ((error = p_can(p, pt, P_CAN_SEE, NULL))) {
187117650Shsu			PROC_UNLOCK(pt);
1886247Swollman			return (error);
1896247Swollman		}
1906247Swollman		p->p_retval[0] = pt->p_session->s_sid;
1916247Swollman		PROC_UNLOCK(pt);
1926247Swollman	}
1936247Swollman	return 0;
1946247Swollman}
19586764Sjlemon
1966247Swollman
1976247Swollman/*
1986247Swollman * getuid() - MP SAFE
1996247Swollman */
20086764Sjlemon#ifndef _SYS_SYSPROTO_H_
20186764Sjlemonstruct getuid_args {
20286764Sjlemon        int     dummy;
20386764Sjlemon};
20486764Sjlemon#endif
20586764Sjlemon
20686764Sjlemon/* ARGSUSED */
20786764Sjlemonint
20886764Sjlemongetuid(p, uap)
2096247Swollman	struct proc *p;
2106247Swollman	struct getuid_args *uap;
21186764Sjlemon{
21286764Sjlemon
21386764Sjlemon	p->p_retval[0] = p->p_cred->p_ruid;
21486764Sjlemon#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
21586764Sjlemon	p->p_retval[1] = p->p_ucred->cr_uid;
21686764Sjlemon#endif
21786764Sjlemon	return (0);
21886764Sjlemon}
21986764Sjlemon
22086764Sjlemon/*
22186764Sjlemon * geteuid() - MP SAFE
22286764Sjlemon */
22386764Sjlemon#ifndef _SYS_SYSPROTO_H_
22486764Sjlemonstruct geteuid_args {
22586764Sjlemon        int     dummy;
22686764Sjlemon};
22786764Sjlemon#endif
22886764Sjlemon
22986764Sjlemon/* ARGSUSED */
23086764Sjlemonint
23186764Sjlemongeteuid(p, uap)
23286764Sjlemon	struct proc *p;
23386764Sjlemon	struct geteuid_args *uap;
23486764Sjlemon{
23586764Sjlemon
23686764Sjlemon	p->p_retval[0] = p->p_ucred->cr_uid;
23786764Sjlemon	return (0);
23886764Sjlemon}
23986764Sjlemon
24086764Sjlemon/*
24186764Sjlemon * getgid() - MP SAFE
24286764Sjlemon */
24386764Sjlemon#ifndef _SYS_SYSPROTO_H_
244111145Sjlemonstruct getgid_args {
245111145Sjlemon        int     dummy;
246111145Sjlemon};
247111145Sjlemon#endif
248111145Sjlemon
249121850Ssilby/* ARGSUSED */
250111145Sjlemonint
251111145Sjlemongetgid(p, uap)
252111145Sjlemon	struct proc *p;
253111145Sjlemon	struct getgid_args *uap;
254111145Sjlemon{
255111145Sjlemon
256111145Sjlemon	p->p_retval[0] = p->p_cred->p_rgid;
257112009Sjlemon#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
258112009Sjlemon	p->p_retval[1] = p->p_ucred->cr_groups[0];
259111145Sjlemon#endif
26086764Sjlemon	return (0);
2616247Swollman}
2626247Swollman
2636247Swollman/*
2646247Swollman * Get effective group ID.  The "egid" is groups[0], and could be obtained
2656247Swollman * via getgroups.  This syscall exists because it is somewhat painful to do
2666247Swollman * correctly in a library function.
2676247Swollman */
2686247Swollman#ifndef _SYS_SYSPROTO_H_
2696247Swollmanstruct getegid_args {
2706247Swollman        int     dummy;
2716247Swollman};
2726247Swollman#endif
2736247Swollman
2746247Swollman/* ARGSUSED */
2756247Swollmanint
2766283Swollmangetegid(p, uap)
2776247Swollman	struct proc *p;
2781541Srgrimes	struct getegid_args *uap;
279111145Sjlemon{
2801541Srgrimes
2811541Srgrimes	p->p_retval[0] = p->p_ucred->cr_groups[0];
2821541Srgrimes	return (0);
2831541Srgrimes}
2841541Srgrimes
2851541Srgrimes#ifndef _SYS_SYSPROTO_H_
2861541Srgrimesstruct getgroups_args {
2871541Srgrimes	u_int	gidsetsize;
2881541Srgrimes	gid_t	*gidset;
2891541Srgrimes};
2901541Srgrimes#endif
29114753Swollmanint
29214753Swollmangetgroups(p, uap)
29314753Swollman	struct proc *p;
29414753Swollman	register struct	getgroups_args *uap;
29514753Swollman{
2961541Srgrimes	register struct pcred *pc = p->p_cred;
2971541Srgrimes	register u_int ngrp;
2981541Srgrimes	int error;
2991541Srgrimes
3001541Srgrimes	if ((ngrp = uap->gidsetsize) == 0) {
3011541Srgrimes		p->p_retval[0] = pc->pc_ucred->cr_ngroups;
3021541Srgrimes		return (0);
3031541Srgrimes	}
3041541Srgrimes	if (ngrp < pc->pc_ucred->cr_ngroups)
3051541Srgrimes		return (EINVAL);
3061541Srgrimes	ngrp = pc->pc_ucred->cr_ngroups;
30714753Swollman	if ((error = copyout((caddr_t)pc->pc_ucred->cr_groups,
30814753Swollman	    (caddr_t)uap->gidset, ngrp * sizeof(gid_t))))
30914753Swollman		return (error);
31014753Swollman	p->p_retval[0] = ngrp;
31114753Swollman	return (0);
3121541Srgrimes}
3131541Srgrimes
31435419Sdg#ifndef _SYS_SYSPROTO_H_
31516141Swollmanstruct setsid_args {
3161541Srgrimes        int     dummy;
3171541Srgrimes};
3181541Srgrimes#endif
3191541Srgrimes
3201541Srgrimes/* ARGSUSED */
3211541Srgrimesint
3221541Srgrimessetsid(p, uap)
3231541Srgrimes	register struct proc *p;
3241541Srgrimes	struct setsid_args *uap;
3251541Srgrimes{
3261541Srgrimes
3271541Srgrimes	if (p->p_pgid == p->p_pid || pgfind(p->p_pid)) {
3281541Srgrimes		return (EPERM);
3291541Srgrimes	} else {
3301541Srgrimes		(void)enterpgrp(p, p->p_pid, 1);
3311541Srgrimes		p->p_retval[0] = p->p_pid;
3321541Srgrimes		return (0);
3331541Srgrimes	}
3341541Srgrimes}
3351541Srgrimes
3361541Srgrimes/*
3371541Srgrimes * set process group (setpgid/old setpgrp)
3381541Srgrimes *
3391541Srgrimes * caller does setpgid(targpid, targpgid)
3401541Srgrimes *
3411541Srgrimes * pid must be caller or child of caller (ESRCH)
3421541Srgrimes * if a child
3431541Srgrimes *	pid must be in same session (EPERM)
344100373Sdillon *	pid can't have done an exec (EACCES)
3451541Srgrimes * if pgid != pid
3461541Srgrimes * 	there must exist some pid in same session having pgid (EPERM)
3471541Srgrimes * pid must not be session leader (EPERM)
3481541Srgrimes */
3491541Srgrimes#ifndef _SYS_SYSPROTO_H_
3501541Srgrimesstruct setpgid_args {
3511541Srgrimes	int	pid;	/* target process id */
3521541Srgrimes	int	pgid;	/* target pgrp id */
3531541Srgrimes};
3541541Srgrimes#endif
3551541Srgrimes/* ARGSUSED */
35652904Sshinint
3571541Srgrimessetpgid(curp, uap)
3581541Srgrimes	struct proc *curp;
3591541Srgrimes	register struct setpgid_args *uap;
3601541Srgrimes{
3611541Srgrimes	register struct proc *targp;		/* target process */
3621541Srgrimes	register struct pgrp *pgrp;		/* target pgrp */
3631541Srgrimes	int error;
3641541Srgrimes
3651541Srgrimes	if (uap->pgid < 0)
3661541Srgrimes		return (EINVAL);
3671541Srgrimes	if (uap->pid != 0 && uap->pid != curp->p_pid) {
3681541Srgrimes		if ((targp = pfind(uap->pid)) == NULL || !inferior(targp)) {
3691541Srgrimes			if (targp)
3701541Srgrimes				PROC_UNLOCK(targp);
3711541Srgrimes			return (ESRCH);
3721541Srgrimes		}
3731541Srgrimes		if ((error = p_can(curproc, targp, P_CAN_SEE, NULL))) {
3741541Srgrimes			PROC_UNLOCK(targp);
3751541Srgrimes			return (error);
3761541Srgrimes		}
3779263Swollman		if (targp->p_pgrp == NULL ||
3789263Swollman		    targp->p_session != curp->p_session) {
3799263Swollman			PROC_UNLOCK(targp);
3809470Swollman			return (EPERM);
3819470Swollman		}
3829470Swollman		if (targp->p_flag & P_EXEC) {
38310937Swollman			PROC_UNLOCK(targp);
38410937Swollman			return (EACCES);
38511415Swollman		}
38614281Sbde	} else {
38786764Sjlemon		targp = curp;
38886764Sjlemon		PROC_LOCK(curp);	/* XXX: not needed */
38986764Sjlemon	}
39086764Sjlemon	if (SESS_LEADER(targp)) {
39186764Sjlemon		PROC_UNLOCK(targp);
39286764Sjlemon		return (EPERM);
39386764Sjlemon	}
39486764Sjlemon	if (uap->pgid == 0)
39586764Sjlemon		uap->pgid = targp->p_pid;
39686764Sjlemon	else if (uap->pgid != targp->p_pid)
39786764Sjlemon		if ((pgrp = pgfind(uap->pgid)) == 0 ||
39886764Sjlemon	            pgrp->pg_session != curp->p_session) {
39986764Sjlemon			PROC_UNLOCK(targp);
40086764Sjlemon			return (EPERM);
40186764Sjlemon		}
40286764Sjlemon	/* XXX: We should probably hold the lock across enterpgrp. */
4031541Srgrimes	PROC_UNLOCK(targp);
4041541Srgrimes	return (enterpgrp(targp, uap->pgid, 0));
4056247Swollman}
40636079Swollman
40737183Sjhay/*
40837183Sjhay * Use the clause in B.4.2.2 that allows setuid/setgid to be 4.2/4.3BSD
40936079Swollman * compatible.  It says that setting the uid/gid to euid/egid is a special
41037183Sjhay * case of "appropriate privilege".  Once the rules are expanded out, this
41136079Swollman * basically means that setuid(nnn) sets all three id's, in all permitted
41236079Swollman * cases unless _POSIX_SAVED_IDS is enabled.  In that case, setuid(getuid())
41336079Swollman * does not set the saved id - this is dangerous for traditional BSD
41436079Swollman * programs.  For this reason, we *really* do not want to set
41536079Swollman * _POSIX_SAVED_IDS and do not want to clear POSIX_APPENDIX_B_4_2_2.
41636079Swollman */
41736079Swollman#define POSIX_APPENDIX_B_4_2_2
41836079Swollman
41936079Swollman#ifndef _SYS_SYSPROTO_H_
42036079Swollmanstruct setuid_args {
4216247Swollman	uid_t	uid;
4226247Swollman};
4236247Swollman#endif
4246247Swollman/* ARGSUSED */
4256247Swollmanint
4266472Swollmansetuid(p, uap)
4276472Swollman	struct proc *p;
4286472Swollman	struct setuid_args *uap;
4296472Swollman{
43018281Spst	register struct pcred *pc = p->p_cred;
43118281Spst	register uid_t uid;
43263431Ssheldonh	int error;
43336079Swollman
43450673Sjlemon	/*
43552904Sshin	 * See if we have "permission" by POSIX 1003.1 rules.
43652904Sshin	 *
4376247Swollman	 * Note that setuid(geteuid()) is a special case of
4386247Swollman	 * "appropriate privileges" in appendix B.4.2.2.  We need
4396247Swollman	 * to use this clause to be compatible with traditional BSD
4406348Swollman	 * semantics.  Basically, it means that "setuid(xx)" sets all
4416348Swollman	 * three id's (assuming you have privs).
4426247Swollman	 *
4436472Swollman	 * Notes on the logic.  We do things in three steps.
4446472Swollman	 * 1: We determine if the euid is going to change, and do EPERM
4456472Swollman	 *    right away.  We unconditionally change the euid later if this
4466472Swollman	 *    test is satisfied, simplifying that part of the logic.
4476472Swollman	 * 2: We determine if the real and/or saved uid's are going to
4486472Swollman	 *    change.  Determined by compile options.
44918281Spst	 * 3: Change euid last. (after tests in #2 for "appropriate privs")
45036079Swollman	 */
45150673Sjlemon	uid = uap->uid;
45252904Sshin	if (uid != pc->p_ruid &&		/* allow setuid(getuid()) */
4536247Swollman#ifdef _POSIX_SAVED_IDS
4546247Swollman	    uid != pc->p_svuid &&		/* allow setuid(saved gid) */
45544078Sdfr#endif
45655205Speter#ifdef POSIX_APPENDIX_B_4_2_2	/* Use BSD-compat clause from B.4.2.2 */
45744078Sdfr	    uid != pc->pc_ucred->cr_uid &&	/* allow setuid(geteuid()) */
45844078Sdfr#endif
45944078Sdfr	    (error = suser_xxx(0, p, PRISON_ROOT)))
46044078Sdfr		return (error);
4617684Sdg
4627684Sdg#ifdef _POSIX_SAVED_IDS
4636348Swollman	/*
4647090Sbde	 * Do we have "appropriate privileges" (are we root or uid == euid)
46533846Sdg	 * If so, we are changing the real uid and/or saved uid.
46660067Sjlemon	 */
46798204Ssilby	if (
46850673Sjlemon#ifdef POSIX_APPENDIX_B_4_2_2	/* Use the clause from B.4.2.2 */
46950673Sjlemon	    uid == pc->pc_ucred->cr_uid ||
4701541Srgrimes#endif
47192723Salfred	    suser_xxx(0, p, PRISON_ROOT) == 0) /* we are using privs */
4721541Srgrimes#endif
47392723Salfred	{
474111145Sjlemon		/*
475121850Ssilby		 * Set the real uid and transfer proc count to new user.
476112009Sjlemon		 */
477112009Sjlemon		if (uid != pc->p_ruid) {
47892723Salfred			change_ruid(p, uid);
47992723Salfred			setsugid(p);
4801541Srgrimes		}
48192723Salfred		/*
48292723Salfred		 * Set saved uid
48392723Salfred		 *
4846247Swollman		 * XXX always set saved uid even if not _POSIX_SAVED_IDS, as
48592723Salfred		 * the security of seteuid() depends on it.  B.4.2.2 says it
48692723Salfred		 * is important that we should do this.
48792723Salfred		 */
48892723Salfred		if (pc->p_svuid != uid) {
48992723Salfred			pc->p_svuid = uid;
49098211Shsu			setsugid(p);
49198211Shsu		}
49298211Shsu	}
49398211Shsu
4941541Srgrimes	/*
49592723Salfred	 * In all permitted cases, we are changing the euid.
49692723Salfred	 * Copy credentials so other references do not see our changes.
49798211Shsu	 */
49898211Shsu	if (pc->pc_ucred->cr_uid != uid) {
49992723Salfred		change_euid(p, uid);
50092723Salfred		setsugid(p);
501114794Srwatson	}
5026247Swollman	return (0);
50392723Salfred}
50492723Salfred
50592723Salfred#ifndef _SYS_SYSPROTO_H_
50655679Sshinstruct seteuid_args {
507111144Sjlemon	uid_t	euid;
508111144Sjlemon};
5091541Srgrimes#endif
51092723Salfred/* ARGSUSED */
51192723Salfredint
512102017Sdillonseteuid(p, uap)
51386764Sjlemon	struct proc *p;
51486764Sjlemon	struct seteuid_args *uap;
51586764Sjlemon{
51686764Sjlemon	register struct pcred *pc = p->p_cred;
51786764Sjlemon	register uid_t euid;
51886764Sjlemon	int error;
51986764Sjlemon
52086764Sjlemon	euid = uap->euid;
5219470Swollman	if (euid != pc->p_ruid &&		/* allow seteuid(getuid()) */
52217096Swollman	    euid != pc->p_svuid &&		/* allow seteuid(saved uid) */
5239470Swollman	    (error = suser_xxx(0, p, PRISON_ROOT)))
5249470Swollman		return (error);
52592723Salfred	/*
5269470Swollman	 * Everything's okay, do it.  Copy credentials so other references do
52755205Speter	 * not see our changes.
5282169Spaul	 */
5296348Swollman	if (pc->pc_ucred->cr_uid != euid) {
530		change_euid(p, euid);
531		setsugid(p);
532	}
533	return (0);
534}
535
536#ifndef _SYS_SYSPROTO_H_
537struct setgid_args {
538	gid_t	gid;
539};
540#endif
541/* ARGSUSED */
542int
543setgid(p, uap)
544	struct proc *p;
545	struct setgid_args *uap;
546{
547	register struct pcred *pc = p->p_cred;
548	register gid_t gid;
549	int error;
550
551	/*
552	 * See if we have "permission" by POSIX 1003.1 rules.
553	 *
554	 * Note that setgid(getegid()) is a special case of
555	 * "appropriate privileges" in appendix B.4.2.2.  We need
556	 * to use this clause to be compatible with traditional BSD
557	 * semantics.  Basically, it means that "setgid(xx)" sets all
558	 * three id's (assuming you have privs).
559	 *
560	 * For notes on the logic here, see setuid() above.
561	 */
562	gid = uap->gid;
563	if (gid != pc->p_rgid &&		/* allow setgid(getgid()) */
564#ifdef _POSIX_SAVED_IDS
565	    gid != pc->p_svgid &&		/* allow setgid(saved gid) */
566#endif
567#ifdef POSIX_APPENDIX_B_4_2_2	/* Use BSD-compat clause from B.4.2.2 */
568	    gid != pc->pc_ucred->cr_groups[0] && /* allow setgid(getegid()) */
569#endif
570	    (error = suser_xxx(0, p, PRISON_ROOT)))
571		return (error);
572
573#ifdef _POSIX_SAVED_IDS
574	/*
575	 * Do we have "appropriate privileges" (are we root or gid == egid)
576	 * If so, we are changing the real uid and saved gid.
577	 */
578	if (
579#ifdef POSIX_APPENDIX_B_4_2_2	/* use the clause from B.4.2.2 */
580	    gid == pc->pc_ucred->cr_groups[0] ||
581#endif
582	    suser_xxx(0, p, PRISON_ROOT) == 0) /* we are using privs */
583#endif
584	{
585		/*
586		 * Set real gid
587		 */
588		if (pc->p_rgid != gid) {
589			pc->p_rgid = gid;
590			setsugid(p);
591		}
592		/*
593		 * Set saved gid
594		 *
595		 * XXX always set saved gid even if not _POSIX_SAVED_IDS, as
596		 * the security of setegid() depends on it.  B.4.2.2 says it
597		 * is important that we should do this.
598		 */
599		if (pc->p_svgid != gid) {
600			pc->p_svgid = gid;
601			setsugid(p);
602		}
603	}
604	/*
605	 * In all cases permitted cases, we are changing the egid.
606	 * Copy credentials so other references do not see our changes.
607	 */
608	if (pc->pc_ucred->cr_groups[0] != gid) {
609		pc->pc_ucred = crcopy(pc->pc_ucred);
610		pc->pc_ucred->cr_groups[0] = gid;
611		setsugid(p);
612	}
613	return (0);
614}
615
616#ifndef _SYS_SYSPROTO_H_
617struct setegid_args {
618	gid_t	egid;
619};
620#endif
621/* ARGSUSED */
622int
623setegid(p, uap)
624	struct proc *p;
625	struct setegid_args *uap;
626{
627	register struct pcred *pc = p->p_cred;
628	register gid_t egid;
629	int error;
630
631	egid = uap->egid;
632	if (egid != pc->p_rgid &&		/* allow setegid(getgid()) */
633	    egid != pc->p_svgid &&		/* allow setegid(saved gid) */
634	    (error = suser_xxx(0, p, PRISON_ROOT)))
635		return (error);
636	if (pc->pc_ucred->cr_groups[0] != egid) {
637		pc->pc_ucred = crcopy(pc->pc_ucred);
638		pc->pc_ucred->cr_groups[0] = egid;
639		setsugid(p);
640	}
641	return (0);
642}
643
644#ifndef _SYS_SYSPROTO_H_
645struct setgroups_args {
646	u_int	gidsetsize;
647	gid_t	*gidset;
648};
649#endif
650/* ARGSUSED */
651int
652setgroups(p, uap)
653	struct proc *p;
654	struct setgroups_args *uap;
655{
656	register struct pcred *pc = p->p_cred;
657	register u_int ngrp;
658	int error;
659
660	if ((error = suser_xxx(0, p, PRISON_ROOT)))
661		return (error);
662	ngrp = uap->gidsetsize;
663	if (ngrp > NGROUPS)
664		return (EINVAL);
665	/*
666	 * XXX A little bit lazy here.  We could test if anything has
667	 * changed before crcopy() and setting P_SUGID.
668	 */
669	pc->pc_ucred = crcopy(pc->pc_ucred);
670	if (ngrp < 1) {
671		/*
672		 * setgroups(0, NULL) is a legitimate way of clearing the
673		 * groups vector on non-BSD systems (which generally do not
674		 * have the egid in the groups[0]).  We risk security holes
675		 * when running non-BSD software if we do not do the same.
676		 */
677		pc->pc_ucred->cr_ngroups = 1;
678	} else {
679		if ((error = copyin((caddr_t)uap->gidset,
680		    (caddr_t)pc->pc_ucred->cr_groups, ngrp * sizeof(gid_t))))
681			return (error);
682		pc->pc_ucred->cr_ngroups = ngrp;
683	}
684	setsugid(p);
685	return (0);
686}
687
688#ifndef _SYS_SYSPROTO_H_
689struct setreuid_args {
690	uid_t	ruid;
691	uid_t	euid;
692};
693#endif
694/* ARGSUSED */
695int
696setreuid(p, uap)
697	register struct proc *p;
698	struct setreuid_args *uap;
699{
700	register struct pcred *pc = p->p_cred;
701	register uid_t ruid, euid;
702	int error;
703
704	ruid = uap->ruid;
705	euid = uap->euid;
706	if (((ruid != (uid_t)-1 && ruid != pc->p_ruid && ruid != pc->p_svuid) ||
707	     (euid != (uid_t)-1 && euid != pc->pc_ucred->cr_uid &&
708	     euid != pc->p_ruid && euid != pc->p_svuid)) &&
709	    (error = suser_xxx(0, p, PRISON_ROOT)) != 0)
710		return (error);
711
712	if (euid != (uid_t)-1 && pc->pc_ucred->cr_uid != euid) {
713		change_euid(p, euid);
714		setsugid(p);
715	}
716	if (ruid != (uid_t)-1 && pc->p_ruid != ruid) {
717		change_ruid(p, ruid);
718		setsugid(p);
719	}
720	if ((ruid != (uid_t)-1 || pc->pc_ucred->cr_uid != pc->p_ruid) &&
721	    pc->p_svuid != pc->pc_ucred->cr_uid) {
722		pc->p_svuid = pc->pc_ucred->cr_uid;
723		setsugid(p);
724	}
725	return (0);
726}
727
728#ifndef _SYS_SYSPROTO_H_
729struct setregid_args {
730	gid_t	rgid;
731	gid_t	egid;
732};
733#endif
734/* ARGSUSED */
735int
736setregid(p, uap)
737	register struct proc *p;
738	struct setregid_args *uap;
739{
740	register struct pcred *pc = p->p_cred;
741	register gid_t rgid, egid;
742	int error;
743
744	rgid = uap->rgid;
745	egid = uap->egid;
746	if (((rgid != (gid_t)-1 && rgid != pc->p_rgid && rgid != pc->p_svgid) ||
747	     (egid != (gid_t)-1 && egid != pc->pc_ucred->cr_groups[0] &&
748	     egid != pc->p_rgid && egid != pc->p_svgid)) &&
749	    (error = suser_xxx(0, p, PRISON_ROOT)) != 0)
750		return (error);
751
752	if (egid != (gid_t)-1 && pc->pc_ucred->cr_groups[0] != egid) {
753		pc->pc_ucred = crcopy(pc->pc_ucred);
754		pc->pc_ucred->cr_groups[0] = egid;
755		setsugid(p);
756	}
757	if (rgid != (gid_t)-1 && pc->p_rgid != rgid) {
758		pc->p_rgid = rgid;
759		setsugid(p);
760	}
761	if ((rgid != (gid_t)-1 || pc->pc_ucred->cr_groups[0] != pc->p_rgid) &&
762	    pc->p_svgid != pc->pc_ucred->cr_groups[0]) {
763		pc->p_svgid = pc->pc_ucred->cr_groups[0];
764		setsugid(p);
765	}
766	return (0);
767}
768
769/*
770 * setresuid(ruid, euid, suid) is like setreuid except control over the
771 * saved uid is explicit.
772 */
773
774#ifndef _SYS_SYSPROTO_H_
775struct setresuid_args {
776	uid_t	ruid;
777	uid_t	euid;
778	uid_t	suid;
779};
780#endif
781/* ARGSUSED */
782int
783setresuid(p, uap)
784	register struct proc *p;
785	struct setresuid_args *uap;
786{
787	register struct pcred *pc = p->p_cred;
788	register uid_t ruid, euid, suid;
789	int error;
790
791	ruid = uap->ruid;
792	euid = uap->euid;
793	suid = uap->suid;
794	if (((ruid != (uid_t)-1 && ruid != pc->p_ruid && ruid != pc->p_svuid &&
795	      ruid != pc->pc_ucred->cr_uid) ||
796	     (euid != (uid_t)-1 && euid != pc->p_ruid && euid != pc->p_svuid &&
797	      euid != pc->pc_ucred->cr_uid) ||
798	     (suid != (uid_t)-1 && suid != pc->p_ruid && suid != pc->p_svuid &&
799	      suid != pc->pc_ucred->cr_uid)) &&
800	    (error = suser_xxx(0, p, PRISON_ROOT)) != 0)
801		return (error);
802	if (euid != (uid_t)-1 && pc->pc_ucred->cr_uid != euid) {
803		change_euid(p, euid);
804		setsugid(p);
805	}
806	if (ruid != (uid_t)-1 && pc->p_ruid != ruid) {
807		change_ruid(p, ruid);
808		setsugid(p);
809	}
810	if (suid != (uid_t)-1 && pc->p_svuid != suid) {
811		pc->p_svuid = suid;
812		setsugid(p);
813	}
814	return (0);
815}
816
817/*
818 * setresgid(rgid, egid, sgid) is like setregid except control over the
819 * saved gid is explicit.
820 */
821
822#ifndef _SYS_SYSPROTO_H_
823struct setresgid_args {
824	gid_t	rgid;
825	gid_t	egid;
826	gid_t	sgid;
827};
828#endif
829/* ARGSUSED */
830int
831setresgid(p, uap)
832	register struct proc *p;
833	struct setresgid_args *uap;
834{
835	register struct pcred *pc = p->p_cred;
836	register gid_t rgid, egid, sgid;
837	int error;
838
839	rgid = uap->rgid;
840	egid = uap->egid;
841	sgid = uap->sgid;
842	if (((rgid != (gid_t)-1 && rgid != pc->p_rgid && rgid != pc->p_svgid &&
843	      rgid != pc->pc_ucred->cr_groups[0]) ||
844	     (egid != (gid_t)-1 && egid != pc->p_rgid && egid != pc->p_svgid &&
845	      egid != pc->pc_ucred->cr_groups[0]) ||
846	     (sgid != (gid_t)-1 && sgid != pc->p_rgid && sgid != pc->p_svgid &&
847	      sgid != pc->pc_ucred->cr_groups[0])) &&
848	    (error = suser_xxx(0, p, PRISON_ROOT)) != 0)
849		return (error);
850
851	if (egid != (gid_t)-1 && pc->pc_ucred->cr_groups[0] != egid) {
852		pc->pc_ucred = crcopy(pc->pc_ucred);
853		pc->pc_ucred->cr_groups[0] = egid;
854		setsugid(p);
855	}
856	if (rgid != (gid_t)-1 && pc->p_rgid != rgid) {
857		pc->p_rgid = rgid;
858		setsugid(p);
859	}
860	if (sgid != (gid_t)-1 && pc->p_svgid != sgid) {
861		pc->p_svgid = sgid;
862		setsugid(p);
863	}
864	return (0);
865}
866
867#ifndef _SYS_SYSPROTO_H_
868struct getresuid_args {
869	uid_t	*ruid;
870	uid_t	*euid;
871	uid_t	*suid;
872};
873#endif
874/* ARGSUSED */
875int
876getresuid(p, uap)
877	register struct proc *p;
878	struct getresuid_args *uap;
879{
880	struct pcred *pc = p->p_cred;
881	int error1 = 0, error2 = 0, error3 = 0;
882
883	if (uap->ruid)
884		error1 = copyout((caddr_t)&pc->p_ruid,
885		    (caddr_t)uap->ruid, sizeof(pc->p_ruid));
886	if (uap->euid)
887		error2 = copyout((caddr_t)&pc->pc_ucred->cr_uid,
888		    (caddr_t)uap->euid, sizeof(pc->pc_ucred->cr_uid));
889	if (uap->suid)
890		error3 = copyout((caddr_t)&pc->p_svuid,
891		    (caddr_t)uap->suid, sizeof(pc->p_svuid));
892	return error1 ? error1 : (error2 ? error2 : error3);
893}
894
895#ifndef _SYS_SYSPROTO_H_
896struct getresgid_args {
897	gid_t	*rgid;
898	gid_t	*egid;
899	gid_t	*sgid;
900};
901#endif
902/* ARGSUSED */
903int
904getresgid(p, uap)
905	register struct proc *p;
906	struct getresgid_args *uap;
907{
908	struct pcred *pc = p->p_cred;
909	int error1 = 0, error2 = 0, error3 = 0;
910
911	if (uap->rgid)
912		error1 = copyout((caddr_t)&pc->p_rgid,
913		    (caddr_t)uap->rgid, sizeof(pc->p_rgid));
914	if (uap->egid)
915		error2 = copyout((caddr_t)&pc->pc_ucred->cr_groups[0],
916		    (caddr_t)uap->egid, sizeof(pc->pc_ucred->cr_groups[0]));
917	if (uap->sgid)
918		error3 = copyout((caddr_t)&pc->p_svgid,
919		    (caddr_t)uap->sgid, sizeof(pc->p_svgid));
920	return error1 ? error1 : (error2 ? error2 : error3);
921}
922
923
924#ifndef _SYS_SYSPROTO_H_
925struct issetugid_args {
926	int dummy;
927};
928#endif
929/* ARGSUSED */
930int
931issetugid(p, uap)
932	register struct proc *p;
933	struct issetugid_args *uap;
934{
935	/*
936	 * Note: OpenBSD sets a P_SUGIDEXEC flag set at execve() time,
937	 * we use P_SUGID because we consider changing the owners as
938	 * "tainting" as well.
939	 * This is significant for procs that start as root and "become"
940	 * a user without an exec - programs cannot know *everything*
941	 * that libc *might* have put in their data segment.
942	 */
943	p->p_retval[0] = (p->p_flag & P_SUGID) ? 1 : 0;
944	return (0);
945}
946
947int
948__setugid(p, uap)
949	struct proc *p;
950	struct __setugid_args *uap;
951{
952
953#ifdef REGRESSION
954	switch (uap->flag) {
955	case 0:
956		p->p_flag &= ~P_SUGID;
957		return (0);
958	case 1:
959		p->p_flag |= P_SUGID;
960		return (0);
961	default:
962		return (EINVAL);
963	}
964#else /* !REGRESSION */
965	return (ENOSYS);
966#endif /* !REGRESSION */
967}
968
969/*
970 * Check if gid is a member of the group set.
971 */
972int
973groupmember(gid, cred)
974	gid_t gid;
975	register struct ucred *cred;
976{
977	register gid_t *gp;
978	gid_t *egp;
979
980	egp = &(cred->cr_groups[cred->cr_ngroups]);
981	for (gp = cred->cr_groups; gp < egp; gp++)
982		if (*gp == gid)
983			return (1);
984	return (0);
985}
986
987static int suser_permitted = 1;
988
989SYSCTL_INT(_kern, OID_AUTO, suser_permitted, CTLFLAG_RW, &suser_permitted, 0,
990    "processes with uid 0 have privilege");
991
992/*
993 * Test whether the specified credentials imply "super-user"
994 * privilege; if so, and we have accounting info, set the flag
995 * indicating use of super-powers.
996 * Returns 0 or error.
997 */
998int
999suser(p)
1000	struct proc *p;
1001{
1002	return suser_xxx(0, p, 0);
1003}
1004
1005int
1006suser_xxx(cred, proc, flag)
1007	struct ucred *cred;
1008	struct proc *proc;
1009	int flag;
1010{
1011	if (!suser_permitted)
1012		return (EPERM);
1013	if (!cred && !proc) {
1014		printf("suser_xxx(): THINK!\n");
1015		return (EPERM);
1016	}
1017	if (!cred)
1018		cred = proc->p_ucred;
1019	if (cred->cr_uid != 0)
1020		return (EPERM);
1021	if (jailed(cred) && !(flag & PRISON_ROOT))
1022		return (EPERM);
1023	return (0);
1024}
1025
1026/*
1027 * u_cansee(u1, u2): determine if u1 "can see" the subject specified by u2
1028 * Arguments: imutable credentials u1, u2
1029 * Returns: 0 for permitted, an errno value otherwise
1030 * Locks: none
1031 * References: u1 and u2 must be valid for the lifetime of the call
1032 *             u1 may equal u2, in which case only one reference is required
1033 */
1034int
1035u_cansee(struct ucred *u1, struct ucred *u2)
1036{
1037	int error;
1038
1039	if ((error = prison_check(u1, u2)))
1040		return (error);
1041	if (!ps_showallprocs && u1->cr_uid != u2->cr_uid) {
1042		if (suser_xxx(u1, NULL, PRISON_ROOT) != 0)
1043			return (ESRCH);
1044	}
1045	return (0);
1046}
1047
1048static int
1049p_cansee(struct proc *p1, struct proc *p2, int *privused)
1050{
1051
1052	/* XXX: privused is going away, so don't do that here. */
1053	if (privused != NULL)
1054		*privused = 0;
1055	/* Wrap u_cansee() for all functionality. */
1056	return (u_cansee(p1->p_ucred, p2->p_ucred));
1057}
1058
1059/*
1060 * Can process p1 send the signal signum to process p2?
1061 */
1062int
1063p_cansignal(struct proc *p1, struct proc *p2, int signum)
1064{
1065	int	error;
1066
1067	if (p1 == p2)
1068		return (0);
1069
1070	/*
1071	 * Jail semantics limit the scope of signalling to p2 in the same
1072	 * jail as p1, if p1 is in jail.
1073	 */
1074	if ((error = prison_check(p1->p_ucred, p2->p_ucred)))
1075		return (error);
1076
1077	/*
1078	 * UNIX signalling semantics require that processes in the same
1079	 * session always be able to deliver SIGCONT to one another,
1080	 * overriding the remaining protections.
1081	 */
1082	if (signum == SIGCONT && p1->p_session == p2->p_session)
1083		return (0);
1084
1085	/*
1086	 * UNIX uid semantics depend on the status of the P_SUGID
1087	 * bit on the target process.  If the bit is set, then more
1088	 * restricted signal sets are permitted.
1089	 */
1090	if (p2->p_flag & P_SUGID) {
1091		switch (signum) {
1092		case 0:
1093		case SIGKILL:
1094		case SIGINT:
1095		case SIGTERM:
1096		case SIGSTOP:
1097		case SIGTTIN:
1098		case SIGTTOU:
1099		case SIGTSTP:
1100		case SIGHUP:
1101		case SIGUSR1:
1102		case SIGUSR2:
1103			break;
1104		default:
1105			/* Not permitted, try privilege. */
1106			error = suser_xxx(NULL, p1, PRISON_ROOT);
1107			if (error)
1108				return (error);
1109		}
1110	}
1111
1112	/*
1113	 * Generally, the object credential's ruid or svuid must match the
1114	 * subject credential's ruid or euid.
1115	 */
1116	if (p1->p_cred->p_ruid != p2->p_cred->p_ruid &&
1117	    p1->p_cred->p_ruid != p2->p_cred->p_svuid &&
1118	    p1->p_ucred->cr_uid != p2->p_cred->p_ruid &&
1119	    p1->p_ucred->cr_uid != p2->p_cred->p_svuid) {
1120		/* Not permitted, try privilege. */
1121		error = suser_xxx(NULL, p1, PRISON_ROOT);
1122		if (error)
1123			return (error);
1124	}
1125
1126        return (0);
1127}
1128
1129static int
1130p_cansched(struct proc *p1, struct proc *p2, int *privused)
1131{
1132	int error;
1133
1134	if (privused != NULL)
1135		*privused = 0;
1136
1137	if (p1 == p2)
1138		return (0);
1139
1140	if ((error = prison_check(p1->p_ucred, p2->p_ucred)))
1141		return (error);
1142
1143	if (p1->p_cred->p_ruid == p2->p_cred->p_ruid)
1144		return (0);
1145	if (p1->p_ucred->cr_uid == p2->p_cred->p_ruid)
1146		return (0);
1147
1148	if (!suser_xxx(0, p1, PRISON_ROOT)) {
1149		if (privused != NULL)
1150			*privused = 1;
1151		return (0);
1152	}
1153
1154#ifdef CAPABILITIES
1155	if (!cap_check_xxx(0, p1, CAP_SYS_NICE, PRISON_ROOT)) {
1156		if (privused != NULL)
1157			*privused = 1;
1158		return (0);
1159	}
1160#endif
1161
1162	return (EPERM);
1163}
1164
1165static int
1166p_candebug(struct proc *p1, struct proc *p2, int *privused)
1167{
1168	int error;
1169
1170	if (privused != NULL)
1171		*privused = 0;
1172
1173	if (p1 == p2)
1174		return (0);
1175
1176	if ((error = prison_check(p1->p_ucred, p2->p_ucred)))
1177		return (error);
1178
1179	/* not owned by you, has done setuid (unless you're root) */
1180	/* add a CAP_SYS_PTRACE here? */
1181	if (p1->p_cred->pc_ucred->cr_uid != p2->p_cred->p_ruid ||
1182	    p1->p_cred->p_ruid != p2->p_cred->p_ruid ||
1183	    p1->p_cred->p_svuid != p2->p_cred->p_ruid ||
1184	    p2->p_flag & P_SUGID) {
1185		if ((error = suser_xxx(0, p1, PRISON_ROOT)))
1186			return (error);
1187		if (privused != NULL)
1188			*privused = 1;
1189	}
1190
1191	/* can't trace init when securelevel > 0 */
1192	if (securelevel > 0 && p2->p_pid == 1)
1193		return (EPERM);
1194
1195	return (0);
1196}
1197
1198int
1199p_can(struct proc *p1, struct proc *p2, int operation,
1200    int *privused)
1201{
1202
1203	switch(operation) {
1204	case P_CAN_SEE:
1205		return (p_cansee(p1, p2, privused));
1206
1207	case P_CAN_SCHED:
1208		return (p_cansched(p1, p2, privused));
1209
1210	case P_CAN_DEBUG:
1211		return (p_candebug(p1, p2, privused));
1212
1213	default:
1214		panic("p_can: invalid operation");
1215	}
1216}
1217
1218
1219/*
1220 * Allocate a zeroed cred structure.
1221 */
1222struct ucred *
1223crget()
1224{
1225	register struct ucred *cr;
1226
1227	MALLOC(cr, struct ucred *, sizeof(*cr), M_CRED, M_WAITOK|M_ZERO);
1228	cr->cr_ref = 1;
1229	mtx_init(&cr->cr_mtx, "ucred", MTX_DEF);
1230	return (cr);
1231}
1232
1233/*
1234 * Claim another reference to a ucred structure
1235 */
1236void
1237crhold(cr)
1238	struct ucred *cr;
1239{
1240
1241	mtx_lock(&cr->cr_mtx);
1242	cr->cr_ref++;
1243	mtx_unlock(&(cr)->cr_mtx);
1244}
1245
1246
1247/*
1248 * Free a cred structure.
1249 * Throws away space when ref count gets to 0.
1250 */
1251void
1252crfree(cr)
1253	struct ucred *cr;
1254{
1255
1256	mtx_lock(&cr->cr_mtx);
1257	KASSERT(cr->cr_ref > 0, ("bad ucred refcount: %d", cr->cr_ref));
1258	if (--cr->cr_ref == 0) {
1259		mtx_destroy(&cr->cr_mtx);
1260		/*
1261		 * Some callers of crget(), such as nfs_statfs(),
1262		 * allocate a temporary credential, but don't
1263		 * allocate a uidinfo structure.
1264		 */
1265		if (cr->cr_uidinfo != NULL)
1266			uifree(cr->cr_uidinfo);
1267		/*
1268		 * Free a prison, if any.
1269		 */
1270		if (jailed(cr))
1271			prison_free(cr->cr_prison);
1272		FREE((caddr_t)cr, M_CRED);
1273	} else {
1274		mtx_unlock(&cr->cr_mtx);
1275	}
1276}
1277
1278/*
1279 * Copy cred structure to a new one and free the old one.
1280 */
1281struct ucred *
1282crcopy(cr)
1283	struct ucred *cr;
1284{
1285	struct ucred *newcr;
1286
1287	mtx_lock(&cr->cr_mtx);
1288	if (cr->cr_ref == 1) {
1289		mtx_unlock(&cr->cr_mtx);
1290		return (cr);
1291	}
1292	mtx_unlock(&cr->cr_mtx);
1293	newcr = crdup(cr);
1294	crfree(cr);
1295	return (newcr);
1296}
1297
1298/*
1299 * Dup cred struct to a new held one.
1300 */
1301struct ucred *
1302crdup(cr)
1303	struct ucred *cr;
1304{
1305	struct ucred *newcr;
1306
1307	MALLOC(newcr, struct ucred *, sizeof(*cr), M_CRED, M_WAITOK);
1308	*newcr = *cr;
1309	mtx_init(&newcr->cr_mtx, "ucred", MTX_DEF);
1310	uihold(newcr->cr_uidinfo);
1311	if (jailed(newcr))
1312		prison_hold(newcr->cr_prison);
1313	newcr->cr_ref = 1;
1314	return (newcr);
1315}
1316
1317/*
1318 * Get login name, if available.
1319 */
1320#ifndef _SYS_SYSPROTO_H_
1321struct getlogin_args {
1322	char	*namebuf;
1323	u_int	namelen;
1324};
1325#endif
1326/* ARGSUSED */
1327int
1328getlogin(p, uap)
1329	struct proc *p;
1330	struct getlogin_args *uap;
1331{
1332
1333	if (uap->namelen > MAXLOGNAME)
1334		uap->namelen = MAXLOGNAME;
1335	return (copyout((caddr_t) p->p_pgrp->pg_session->s_login,
1336	    (caddr_t) uap->namebuf, uap->namelen));
1337}
1338
1339/*
1340 * Set login name.
1341 */
1342#ifndef _SYS_SYSPROTO_H_
1343struct setlogin_args {
1344	char	*namebuf;
1345};
1346#endif
1347/* ARGSUSED */
1348int
1349setlogin(p, uap)
1350	struct proc *p;
1351	struct setlogin_args *uap;
1352{
1353	int error;
1354	char logintmp[MAXLOGNAME];
1355
1356	if ((error = suser_xxx(0, p, PRISON_ROOT)))
1357		return (error);
1358	error = copyinstr((caddr_t) uap->namebuf, (caddr_t) logintmp,
1359	    sizeof(logintmp), (size_t *)0);
1360	if (error == ENAMETOOLONG)
1361		error = EINVAL;
1362	else if (!error)
1363		(void) memcpy(p->p_pgrp->pg_session->s_login, logintmp,
1364		    sizeof(logintmp));
1365	return (error);
1366}
1367
1368void
1369setsugid(p)
1370	struct proc *p;
1371{
1372	p->p_flag |= P_SUGID;
1373	if (!(p->p_pfsflags & PF_ISUGID))
1374		p->p_stops = 0;
1375}
1376
1377/*
1378 * Helper function to change the effective uid of a process
1379 */
1380void
1381change_euid(p, euid)
1382	struct	proc *p;
1383	uid_t	euid;
1384{
1385	struct	pcred *pc;
1386	struct	uidinfo *uip;
1387
1388	pc = p->p_cred;
1389	/*
1390	 * crcopy is essentially a NOP if ucred has a reference count
1391	 * of 1, which is true if it has already been copied.
1392	 */
1393	pc->pc_ucred = crcopy(pc->pc_ucred);
1394	uip = pc->pc_ucred->cr_uidinfo;
1395	pc->pc_ucred->cr_uid = euid;
1396	pc->pc_ucred->cr_uidinfo = uifind(euid);
1397	uifree(uip);
1398}
1399
1400/*
1401 * Helper function to change the real uid of a process
1402 *
1403 * The per-uid process count for this process is transfered from
1404 * the old uid to the new uid.
1405 */
1406void
1407change_ruid(p, ruid)
1408	struct	proc *p;
1409	uid_t	ruid;
1410{
1411	struct	pcred *pc;
1412	struct	uidinfo *uip;
1413
1414	pc = p->p_cred;
1415	(void)chgproccnt(pc->p_uidinfo, -1, 0);
1416	uip = pc->p_uidinfo;
1417	/* It is assumed that pcred is not shared between processes */
1418	pc->p_ruid = ruid;
1419	pc->p_uidinfo = uifind(ruid);
1420	(void)chgproccnt(pc->p_uidinfo, 1, 0);
1421	uifree(uip);
1422}
1423