kern_prot.c revision 92987
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.
987218Srwatson * Copyright (c) 2000-2001 Robert N. M. Watson.  All rights reserved.
101541Srgrimes *
111541Srgrimes * Redistribution and use in source and binary forms, with or without
121541Srgrimes * modification, are permitted provided that the following conditions
131541Srgrimes * are met:
141541Srgrimes * 1. Redistributions of source code must retain the above copyright
151541Srgrimes *    notice, this list of conditions and the following disclaimer.
161541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
171541Srgrimes *    notice, this list of conditions and the following disclaimer in the
181541Srgrimes *    documentation and/or other materials provided with the distribution.
191541Srgrimes * 3. All advertising materials mentioning features or use of this software
201541Srgrimes *    must display the following acknowledgement:
211541Srgrimes *	This product includes software developed by the University of
221541Srgrimes *	California, Berkeley and its contributors.
231541Srgrimes * 4. Neither the name of the University nor the names of its contributors
241541Srgrimes *    may be used to endorse or promote products derived from this software
251541Srgrimes *    without specific prior written permission.
261541Srgrimes *
271541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
281541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
291541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
301541Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
311541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
321541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
331541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
341541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
351541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
361541Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
371541Srgrimes * SUCH DAMAGE.
381541Srgrimes *
391541Srgrimes *	@(#)kern_prot.c	8.6 (Berkeley) 1/21/94
4050477Speter * $FreeBSD: head/sys/kern/kern_prot.c 92987 2002-03-22 22:32:04Z jhb $
411541Srgrimes */
421541Srgrimes
431541Srgrimes/*
441541Srgrimes * System calls related to processes and protection
451541Srgrimes */
461541Srgrimes
4731778Seivind#include "opt_compat.h"
4831778Seivind
491541Srgrimes#include <sys/param.h>
5076166Smarkm#include <sys/systm.h>
511541Srgrimes#include <sys/acct.h>
5241059Speter#include <sys/kernel.h>
5370317Sjake#include <sys/lock.h>
5491140Stanimura#include <sys/malloc.h>
5576166Smarkm#include <sys/mutex.h>
5691140Stanimura#include <sys/sx.h>
571541Srgrimes#include <sys/proc.h>
5876166Smarkm#include <sys/sysproto.h>
5987218Srwatson#include <sys/jail.h>
6031891Ssef#include <sys/pioctl.h>
6165495Struckman#include <sys/resourcevar.h>
6292976Srwatson#include <sys/socket.h>
6392976Srwatson#include <sys/socketvar.h>
6461287Srwatson#include <sys/sysctl.h>
651541Srgrimes
6630354Sphkstatic MALLOC_DEFINE(M_CRED, "cred", "credentials");
6730354Sphk
6889414SarrSYSCTL_DECL(_security);
6989414SarrSYSCTL_NODE(_security, OID_AUTO, bsd, CTLFLAG_RW, 0,
7087138Srwatson    "BSD security policy");
7187138Srwatson
7212221Sbde#ifndef _SYS_SYSPROTO_H_
7311332Sswallacestruct getpid_args {
741541Srgrimes	int	dummy;
751541Srgrimes};
7612221Sbde#endif
7758717Sdillon/*
7882749Sdillon * MPSAFE
7982749Sdillon */
801541Srgrimes/* ARGSUSED */
811549Srgrimesint
8283366Sjuliangetpid(td, uap)
8383366Sjulian	struct thread *td;
8411332Sswallace	struct getpid_args *uap;
851541Srgrimes{
8683366Sjulian	struct proc *p = td->td_proc;
8785564Sdillon	int s;
881541Srgrimes
8985564Sdillon	s = mtx_lock_giant(kern_giant_proc);
9083366Sjulian	td->td_retval[0] = p->p_pid;
911541Srgrimes#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
9274728Sjhb	PROC_LOCK(p);
9383366Sjulian	td->td_retval[1] = p->p_pptr->p_pid;
9474728Sjhb	PROC_UNLOCK(p);
951541Srgrimes#endif
9685564Sdillon	mtx_unlock_giant(s);
971541Srgrimes	return (0);
981541Srgrimes}
991541Srgrimes
10012221Sbde#ifndef _SYS_SYSPROTO_H_
10111332Sswallacestruct getppid_args {
10211332Sswallace        int     dummy;
10311332Sswallace};
10412221Sbde#endif
10582749Sdillon/*
10682749Sdillon * MPSAFE
10782749Sdillon */
1081541Srgrimes/* ARGSUSED */
1091549Srgrimesint
11083366Sjuliangetppid(td, uap)
11183366Sjulian	struct thread *td;
11211332Sswallace	struct getppid_args *uap;
1131541Srgrimes{
11483366Sjulian	struct proc *p = td->td_proc;
11585564Sdillon	int s;
1161541Srgrimes
11785564Sdillon	s = mtx_lock_giant(kern_giant_proc);
11874728Sjhb	PROC_LOCK(p);
11983366Sjulian	td->td_retval[0] = p->p_pptr->p_pid;
12074728Sjhb	PROC_UNLOCK(p);
12185564Sdillon	mtx_unlock_giant(s);
1221541Srgrimes	return (0);
1231541Srgrimes}
1241541Srgrimes
12587466Srwatson/*
12687218Srwatson * Get process group ID; note that POSIX getpgrp takes no parameter.
12758717Sdillon */
12812221Sbde#ifndef _SYS_SYSPROTO_H_
12911332Sswallacestruct getpgrp_args {
13011332Sswallace        int     dummy;
13111332Sswallace};
13212221Sbde#endif
13382749Sdillon/*
13482749Sdillon * MPSAFE
13582749Sdillon */
1361549Srgrimesint
13783366Sjuliangetpgrp(td, uap)
13883366Sjulian	struct thread *td;
13911332Sswallace	struct getpgrp_args *uap;
1401541Srgrimes{
14183366Sjulian	struct proc *p = td->td_proc;
14291140Stanimura	int s;
1431541Srgrimes
14491140Stanimura	s = mtx_lock_giant(kern_giant_proc);
14591140Stanimura	PROC_LOCK(p);
14683366Sjulian	td->td_retval[0] = p->p_pgrp->pg_id;
14791140Stanimura	PROC_UNLOCK(p);
14891140Stanimura	mtx_unlock_giant(s);
1491541Srgrimes	return (0);
1501541Srgrimes}
1511541Srgrimes
15228401Speter/* Get an arbitary pid's process group id */
15312221Sbde#ifndef _SYS_SYSPROTO_H_
15428401Speterstruct getpgid_args {
15528401Speter	pid_t	pid;
15628401Speter};
15728401Speter#endif
15882749Sdillon/*
15982749Sdillon * MPSAFE
16082749Sdillon */
16128401Speterint
16283366Sjuliangetpgid(td, uap)
16383366Sjulian	struct thread *td;
16428401Speter	struct getpgid_args *uap;
16528401Speter{
16683366Sjulian	struct proc *p = td->td_proc;
16741726Struckman	struct proc *pt;
16892985Sjhb	int error;
16941726Struckman
17092985Sjhb	mtx_lock(&Giant);
17187218Srwatson	error = 0;
17291140Stanimura	if (uap->pid == 0) {
17391140Stanimura		PROC_LOCK(p);
17483366Sjulian		td->td_retval[0] = p->p_pgrp->pg_id;
17591140Stanimura		PROC_UNLOCK(p);
17691140Stanimura	} else if ((pt = pfind(uap->pid)) == NULL)
17784825Sjhb		error = ESRCH;
17875893Sjhb	else {
17984825Sjhb		error = p_cansee(p, pt);
18084825Sjhb		if (error == 0)
18184825Sjhb			td->td_retval[0] = pt->p_pgrp->pg_id;
18275893Sjhb		PROC_UNLOCK(pt);
18375893Sjhb	}
18492985Sjhb	mtx_unlock(&Giant);
18582749Sdillon	return (error);
18628401Speter}
18728401Speter
18828401Speter/*
18928401Speter * Get an arbitary pid's session id.
19028401Speter */
19128401Speter#ifndef _SYS_SYSPROTO_H_
19228401Speterstruct getsid_args {
19328401Speter	pid_t	pid;
19428401Speter};
19528401Speter#endif
19682749Sdillon/*
19782749Sdillon * MPSAFE
19882749Sdillon */
19928401Speterint
20083366Sjuliangetsid(td, uap)
20183366Sjulian	struct thread *td;
20228401Speter	struct getsid_args *uap;
20328401Speter{
20483366Sjulian	struct proc *p = td->td_proc;
20541726Struckman	struct proc *pt;
20687218Srwatson	int error;
20741726Struckman
20892985Sjhb	mtx_lock(&Giant);
20987218Srwatson	error = 0;
21091140Stanimura	if (uap->pid == 0) {
21191140Stanimura		PROC_LOCK(p);
21283366Sjulian		td->td_retval[0] = p->p_session->s_sid;
21391140Stanimura		PROC_UNLOCK(p);
21491140Stanimura	} else if ((pt = pfind(uap->pid)) == NULL)
21584825Sjhb		error = ESRCH;
21684825Sjhb	else {
21784825Sjhb		error = p_cansee(p, pt);
21884825Sjhb		if (error == 0)
21984825Sjhb			td->td_retval[0] = pt->p_session->s_sid;
22075893Sjhb		PROC_UNLOCK(pt);
22175893Sjhb	}
22292985Sjhb	mtx_unlock(&Giant);
22382749Sdillon	return (error);
22428401Speter}
22528401Speter
22628401Speter#ifndef _SYS_SYSPROTO_H_
22711332Sswallacestruct getuid_args {
22811332Sswallace        int     dummy;
22911332Sswallace};
23012221Sbde#endif
23182749Sdillon/*
23282749Sdillon * MPSAFE
23382749Sdillon */
2341541Srgrimes/* ARGSUSED */
2351549Srgrimesint
23683366Sjuliangetuid(td, uap)
23783366Sjulian	struct thread *td;
23811332Sswallace	struct getuid_args *uap;
2391541Srgrimes{
2401541Srgrimes
24192987Sjhb	td->td_retval[0] = td->td_ucred->cr_ruid;
2421541Srgrimes#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
24392987Sjhb	td->td_retval[1] = td->td_ucred->cr_uid;
2441541Srgrimes#endif
2451541Srgrimes	return (0);
2461541Srgrimes}
2471541Srgrimes
24812221Sbde#ifndef _SYS_SYSPROTO_H_
24911332Sswallacestruct geteuid_args {
25011332Sswallace        int     dummy;
25111332Sswallace};
25212221Sbde#endif
25387218Srwatson/*
25487218Srwatson * MPSAFE
25587218Srwatson */
2561541Srgrimes/* ARGSUSED */
2571549Srgrimesint
25883366Sjuliangeteuid(td, uap)
25983366Sjulian	struct thread *td;
26011332Sswallace	struct geteuid_args *uap;
2611541Srgrimes{
26292987Sjhb
26392987Sjhb	td->td_retval[0] = td->td_ucred->cr_uid;
2641541Srgrimes	return (0);
2651541Srgrimes}
2661541Srgrimes
26712221Sbde#ifndef _SYS_SYSPROTO_H_
26811332Sswallacestruct getgid_args {
26911332Sswallace        int     dummy;
27011332Sswallace};
27112221Sbde#endif
27282749Sdillon/*
27382749Sdillon * MPSAFE
27482749Sdillon */
2751541Srgrimes/* ARGSUSED */
2761549Srgrimesint
27783366Sjuliangetgid(td, uap)
27883366Sjulian	struct thread *td;
27911332Sswallace	struct getgid_args *uap;
2801541Srgrimes{
2811541Srgrimes
28292987Sjhb	td->td_retval[0] = td->td_ucred->cr_rgid;
2831541Srgrimes#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
28492987Sjhb	td->td_retval[1] = td->td_ucred->cr_groups[0];
2851541Srgrimes#endif
2861541Srgrimes	return (0);
2871541Srgrimes}
2881541Srgrimes
2891541Srgrimes/*
2901541Srgrimes * Get effective group ID.  The "egid" is groups[0], and could be obtained
2911541Srgrimes * via getgroups.  This syscall exists because it is somewhat painful to do
2921541Srgrimes * correctly in a library function.
2931541Srgrimes */
29412221Sbde#ifndef _SYS_SYSPROTO_H_
29511332Sswallacestruct getegid_args {
29611332Sswallace        int     dummy;
29711332Sswallace};
29812221Sbde#endif
29982749Sdillon/*
30082749Sdillon * MPSAFE
30182749Sdillon */
3021541Srgrimes/* ARGSUSED */
3031549Srgrimesint
30483366Sjuliangetegid(td, uap)
30583366Sjulian	struct thread *td;
30611332Sswallace	struct getegid_args *uap;
3071541Srgrimes{
3081541Srgrimes
30992987Sjhb	td->td_retval[0] = td->td_ucred->cr_groups[0];
3101541Srgrimes	return (0);
3111541Srgrimes}
3121541Srgrimes
31312221Sbde#ifndef _SYS_SYSPROTO_H_
3141541Srgrimesstruct getgroups_args {
3151541Srgrimes	u_int	gidsetsize;
3161541Srgrimes	gid_t	*gidset;
3171541Srgrimes};
31812221Sbde#endif
31982749Sdillon/*
32082749Sdillon * MPSAFE
32182749Sdillon */
3221549Srgrimesint
32383366Sjuliangetgroups(td, uap)
32483366Sjulian	struct thread *td;
32587218Srwatson	register struct getgroups_args *uap;
3261541Srgrimes{
32782749Sdillon	struct ucred *cred;
32877183Srwatson	u_int ngrp;
32987218Srwatson	int error;
3301541Srgrimes
33192987Sjhb	cred = td->td_ucred;
3321541Srgrimes	if ((ngrp = uap->gidsetsize) == 0) {
33383366Sjulian		td->td_retval[0] = cred->cr_ngroups;
33492987Sjhb		return (0);
3351541Srgrimes	}
33692987Sjhb	if (ngrp < cred->cr_ngroups)
33792987Sjhb		return (EINVAL);
33877183Srwatson	ngrp = cred->cr_ngroups;
33992987Sjhb	error = copyout((caddr_t)cred->cr_groups, (caddr_t)uap->gidset,
34092987Sjhb	    ngrp * sizeof(gid_t));
34192987Sjhb	if (error)
34292987Sjhb		return (error);
34383366Sjulian	td->td_retval[0] = ngrp;
34492987Sjhb	return (0);
3451541Srgrimes}
3461541Srgrimes
34712221Sbde#ifndef _SYS_SYSPROTO_H_
34812207Sbdestruct setsid_args {
34911332Sswallace        int     dummy;
35011332Sswallace};
35112221Sbde#endif
35282749Sdillon/*
35382749Sdillon * MPSAFE
35482749Sdillon */
3551541Srgrimes/* ARGSUSED */
3561549Srgrimesint
35783366Sjuliansetsid(td, uap)
35883366Sjulian	register struct thread *td;
35912207Sbde	struct setsid_args *uap;
3601541Srgrimes{
36191140Stanimura	struct pgrp *pgrp;
36282749Sdillon	int error;
36383366Sjulian	struct proc *p = td->td_proc;
36491140Stanimura	struct pgrp *newpgrp;
36591140Stanimura	struct session *newsess;
3661541Srgrimes
36791140Stanimura	error = 0;
36891140Stanimura	pgrp = NULL;
36991140Stanimura
37082749Sdillon	mtx_lock(&Giant);
37191140Stanimura
37291140Stanimura	MALLOC(newpgrp, struct pgrp *, sizeof(struct pgrp), M_PGRP, M_WAITOK | M_ZERO);
37391140Stanimura	MALLOC(newsess, struct session *, sizeof(struct session), M_SESSION, M_WAITOK | M_ZERO);
37491140Stanimura
37591140Stanimura	PGRPSESS_XLOCK();
37691140Stanimura
37791140Stanimura	if (p->p_pgid == p->p_pid || (pgrp = pgfind(p->p_pid)) != NULL) {
37891140Stanimura		if (pgrp != NULL)
37991140Stanimura			PGRP_UNLOCK(pgrp);
38082749Sdillon		error = EPERM;
38191140Stanimura		goto fail;
38291140Stanimura	} else {
38391140Stanimura		(void)enterpgrp(p, p->p_pid, newpgrp, newsess);
38483366Sjulian		td->td_retval[0] = p->p_pid;
38582749Sdillon		error = 0;
3861541Srgrimes	}
38791140Stanimura	PGRPSESS_XUNLOCK();
38882749Sdillon	mtx_unlock(&Giant);
38991140Stanimura	return (0);
39091140Stanimura
39191140Stanimurafail:
39291140Stanimura	PGRPSESS_XUNLOCK();
39391140Stanimura
39491140Stanimura	FREE(newpgrp, M_PGRP);
39591140Stanimura	FREE(newsess, M_SESSION);
39691140Stanimura
39791140Stanimura	mtx_unlock(&Giant);
39891140Stanimura	return (0);
3991541Srgrimes}
4001541Srgrimes
4011541Srgrimes/*
4021541Srgrimes * set process group (setpgid/old setpgrp)
4031541Srgrimes *
4041541Srgrimes * caller does setpgid(targpid, targpgid)
4051541Srgrimes *
4061541Srgrimes * pid must be caller or child of caller (ESRCH)
4071541Srgrimes * if a child
4081541Srgrimes *	pid must be in same session (EPERM)
4091541Srgrimes *	pid can't have done an exec (EACCES)
4101541Srgrimes * if pgid != pid
4111541Srgrimes * 	there must exist some pid in same session having pgid (EPERM)
4121541Srgrimes * pid must not be session leader (EPERM)
4131541Srgrimes */
41412221Sbde#ifndef _SYS_SYSPROTO_H_
4151541Srgrimesstruct setpgid_args {
41687218Srwatson	int	pid;		/* target process id */
41787218Srwatson	int	pgid;		/* target pgrp id */
4181541Srgrimes};
41912221Sbde#endif
42082749Sdillon/*
42182749Sdillon * MPSAFE
42282749Sdillon */
4231541Srgrimes/* ARGSUSED */
4241549Srgrimesint
42583366Sjuliansetpgid(td, uap)
42683366Sjulian	struct thread *td;
4271541Srgrimes	register struct setpgid_args *uap;
4281541Srgrimes{
42983366Sjulian	struct proc *curp = td->td_proc;
43087218Srwatson	register struct proc *targp;	/* target process */
43187218Srwatson	register struct pgrp *pgrp;	/* target pgrp */
43275448Srwatson	int error;
43391140Stanimura	struct pgrp *newpgrp;
4341541Srgrimes
43520677Sbde	if (uap->pgid < 0)
43620677Sbde		return (EINVAL);
43791140Stanimura
43891140Stanimura	error = 0;
43991140Stanimura
44082749Sdillon	mtx_lock(&Giant);
44191140Stanimura
44291140Stanimura	MALLOC(newpgrp, struct pgrp *, sizeof(struct pgrp), M_PGRP, M_WAITOK | M_ZERO);
44391140Stanimura
44491140Stanimura	PGRPSESS_XLOCK();
44591140Stanimura
4461541Srgrimes	if (uap->pid != 0 && uap->pid != curp->p_pid) {
44791140Stanimura		sx_slock(&proctree_lock);
44891140Stanimura		if ((targp = pfind(uap->pid)) == NULL) {
44975893Sjhb			if (targp)
45075893Sjhb				PROC_UNLOCK(targp);
45191140Stanimura			sx_sunlock(&proctree_lock);
45282749Sdillon			error = ESRCH;
45391140Stanimura			goto fail;
45475893Sjhb		}
45591140Stanimura		if (!inferior(targp)) {
45691140Stanimura			PROC_UNLOCK(targp);
45791140Stanimura			sx_sunlock(&proctree_lock);
45891371Stanimura			error = ESRCH;
45991140Stanimura			goto fail;
46091140Stanimura		}
46191140Stanimura		sx_sunlock(&proctree_lock);
46279335Srwatson		if ((error = p_cansee(curproc, targp))) {
46375893Sjhb			PROC_UNLOCK(targp);
46491140Stanimura			goto fail;
46575893Sjhb		}
46675893Sjhb		if (targp->p_pgrp == NULL ||
46775893Sjhb		    targp->p_session != curp->p_session) {
46875893Sjhb			PROC_UNLOCK(targp);
46982749Sdillon			error = EPERM;
47091140Stanimura			goto fail;
47175893Sjhb		}
47275893Sjhb		if (targp->p_flag & P_EXEC) {
47375893Sjhb			PROC_UNLOCK(targp);
47482749Sdillon			error = EACCES;
47591140Stanimura			goto fail;
47675893Sjhb		}
47791140Stanimura		PROC_UNLOCK(targp);
47891140Stanimura	} else
4791541Srgrimes		targp = curp;
48075893Sjhb	if (SESS_LEADER(targp)) {
48182749Sdillon		error = EPERM;
48291140Stanimura		goto fail;
48375893Sjhb	}
48487218Srwatson	if (uap->pgid == 0)
4851541Srgrimes		uap->pgid = targp->p_pid;
48691140Stanimura	if (uap->pgid == targp->p_pid) {
48791140Stanimura		if (targp->p_pgid == uap->pgid)
48891140Stanimura			goto done;
48991140Stanimura		error = enterpgrp(targp, uap->pgid, newpgrp, NULL);
49091140Stanimura		if (error == 0)
49191140Stanimura			newpgrp = NULL;
49291140Stanimura	} else {
49391140Stanimura		if ((pgrp = pgfind(uap->pgid)) == NULL ||
49487218Srwatson		    pgrp->pg_session != curp->p_session) {
49591140Stanimura			if (pgrp != NULL)
49691140Stanimura				PGRP_UNLOCK(pgrp);
49782749Sdillon			error = EPERM;
49891140Stanimura			goto fail;
49975893Sjhb		}
50091140Stanimura		if (pgrp == targp->p_pgrp) {
50191140Stanimura			PGRP_UNLOCK(pgrp);
50291140Stanimura			goto done;
50391140Stanimura		}
50491140Stanimura		PGRP_UNLOCK(pgrp);
50591140Stanimura		error = enterthispgrp(targp, pgrp);
50682749Sdillon	}
50791140Stanimuradone:
50891140Stanimura	PGRPSESS_XUNLOCK();
50991140Stanimura	if (newpgrp != NULL)
51091140Stanimura		FREE(newpgrp, M_PGRP);
51182749Sdillon	mtx_unlock(&Giant);
51291140Stanimura	return (0);
51391140Stanimura
51491140Stanimurafail:
51591140Stanimura	PGRPSESS_XUNLOCK();
51691140Stanimura
51791140Stanimura	KASSERT(newpgrp != NULL, ("setpgid failed and newpgrp is null."));
51891371Stanimura	KASSERT(error != 0, ("setpgid successfully failed?"));
51991140Stanimura	FREE(newpgrp, M_PGRP);
52091140Stanimura
52191140Stanimura	mtx_unlock(&Giant);
52282749Sdillon	return (error);
5231541Srgrimes}
5241541Srgrimes
52524448Speter/*
52624448Speter * Use the clause in B.4.2.2 that allows setuid/setgid to be 4.2/4.3BSD
52772093Sasmodai * compatible.  It says that setting the uid/gid to euid/egid is a special
52824448Speter * case of "appropriate privilege".  Once the rules are expanded out, this
52924448Speter * basically means that setuid(nnn) sets all three id's, in all permitted
53024448Speter * cases unless _POSIX_SAVED_IDS is enabled.  In that case, setuid(getuid())
53124448Speter * does not set the saved id - this is dangerous for traditional BSD
53224448Speter * programs.  For this reason, we *really* do not want to set
53324448Speter * _POSIX_SAVED_IDS and do not want to clear POSIX_APPENDIX_B_4_2_2.
53424448Speter */
53524448Speter#define POSIX_APPENDIX_B_4_2_2
53624448Speter
53712221Sbde#ifndef _SYS_SYSPROTO_H_
5381541Srgrimesstruct setuid_args {
5391541Srgrimes	uid_t	uid;
5401541Srgrimes};
54112221Sbde#endif
54282749Sdillon/*
54382749Sdillon * MPSAFE
54482749Sdillon */
5451541Srgrimes/* ARGSUSED */
5461549Srgrimesint
54783366Sjuliansetuid(td, uap)
54883366Sjulian	struct thread *td;
5491541Srgrimes	struct setuid_args *uap;
5501541Srgrimes{
55183366Sjulian	struct proc *p = td->td_proc;
55277183Srwatson	struct ucred *newcred, *oldcred;
55377183Srwatson	uid_t uid;
55487218Srwatson	int error;
5551541Srgrimes
55677183Srwatson	uid = uap->uid;
55782749Sdillon	mtx_lock(&Giant);
55887218Srwatson	error = 0;
55987219Srwatson	oldcred = p->p_ucred;
56087466Srwatson
56124448Speter	/*
56224448Speter	 * See if we have "permission" by POSIX 1003.1 rules.
56324448Speter	 *
56487218Srwatson	 * Note that setuid(geteuid()) is a special case of
56524448Speter	 * "appropriate privileges" in appendix B.4.2.2.  We need
56672093Sasmodai	 * to use this clause to be compatible with traditional BSD
56724448Speter	 * semantics.  Basically, it means that "setuid(xx)" sets all
56824448Speter	 * three id's (assuming you have privs).
56924448Speter	 *
57024448Speter	 * Notes on the logic.  We do things in three steps.
57124448Speter	 * 1: We determine if the euid is going to change, and do EPERM
57224448Speter	 *    right away.  We unconditionally change the euid later if this
57324448Speter	 *    test is satisfied, simplifying that part of the logic.
57487218Srwatson	 * 2: We determine if the real and/or saved uids are going to
57524448Speter	 *    change.  Determined by compile options.
57624448Speter	 * 3: Change euid last. (after tests in #2 for "appropriate privs")
57724448Speter	 */
57877183Srwatson	if (uid != oldcred->cr_ruid &&		/* allow setuid(getuid()) */
57917994Sache#ifdef _POSIX_SAVED_IDS
58077183Srwatson	    uid != oldcred->cr_svuid &&		/* allow setuid(saved gid) */
58117994Sache#endif
58224448Speter#ifdef POSIX_APPENDIX_B_4_2_2	/* Use BSD-compat clause from B.4.2.2 */
58377183Srwatson	    uid != oldcred->cr_uid &&		/* allow setuid(geteuid()) */
58424448Speter#endif
58587218Srwatson	    (error = suser_xxx(oldcred, NULL, PRISON_ROOT)) != 0)
58682749Sdillon		goto done2;
58724448Speter
58877183Srwatson	newcred = crdup(oldcred);
58924448Speter#ifdef _POSIX_SAVED_IDS
5901541Srgrimes	/*
59124448Speter	 * Do we have "appropriate privileges" (are we root or uid == euid)
59224448Speter	 * If so, we are changing the real uid and/or saved uid.
5931541Srgrimes	 */
59417994Sache	if (
59524448Speter#ifdef POSIX_APPENDIX_B_4_2_2	/* Use the clause from B.4.2.2 */
59677183Srwatson	    uid == oldcred->cr_uid ||
59717994Sache#endif
59877183Srwatson	    suser_xxx(oldcred, NULL, PRISON_ROOT) == 0) /* we are using privs */
59917994Sache#endif
60024448Speter	{
60124448Speter		/*
60265495Struckman		 * Set the real uid and transfer proc count to new user.
60324448Speter		 */
60477183Srwatson		if (uid != oldcred->cr_ruid) {
60577183Srwatson			change_ruid(newcred, uid);
60665495Struckman			setsugid(p);
60724448Speter		}
60824448Speter		/*
60924448Speter		 * Set saved uid
61024448Speter		 *
61124448Speter		 * XXX always set saved uid even if not _POSIX_SAVED_IDS, as
61224448Speter		 * the security of seteuid() depends on it.  B.4.2.2 says it
61324448Speter		 * is important that we should do this.
61424448Speter		 */
61577183Srwatson		if (uid != oldcred->cr_svuid) {
61677183Srwatson			change_svuid(newcred, uid);
61731891Ssef			setsugid(p);
61824448Speter		}
6198141Sache	}
62024448Speter
62124448Speter	/*
62224448Speter	 * In all permitted cases, we are changing the euid.
62324448Speter	 * Copy credentials so other references do not see our changes.
62424448Speter	 */
62577183Srwatson	if (uid != oldcred->cr_uid) {
62677183Srwatson		change_euid(newcred, uid);
62731891Ssef		setsugid(p);
62824448Speter	}
62977183Srwatson	p->p_ucred = newcred;
63077183Srwatson	crfree(oldcred);
63182749Sdillondone2:
63282749Sdillon	mtx_unlock(&Giant);
63382749Sdillon	return (error);
6341541Srgrimes}
6351541Srgrimes
63612221Sbde#ifndef _SYS_SYSPROTO_H_
6371541Srgrimesstruct seteuid_args {
6381541Srgrimes	uid_t	euid;
6391541Srgrimes};
64012221Sbde#endif
64182749Sdillon/*
64282749Sdillon * MPSAFE
64382749Sdillon */
6441541Srgrimes/* ARGSUSED */
6451549Srgrimesint
64683366Sjulianseteuid(td, uap)
64783366Sjulian	struct thread *td;
6481541Srgrimes	struct seteuid_args *uap;
6491541Srgrimes{
65083366Sjulian	struct proc *p = td->td_proc;
65177183Srwatson	struct ucred *newcred, *oldcred;
65277183Srwatson	uid_t euid;
65387218Srwatson	int error;
6541541Srgrimes
6551541Srgrimes	euid = uap->euid;
65682749Sdillon	mtx_lock(&Giant);
65787218Srwatson	error = 0;
65877183Srwatson	oldcred = p->p_ucred;
65977183Srwatson	if (euid != oldcred->cr_ruid &&		/* allow seteuid(getuid()) */
66077183Srwatson	    euid != oldcred->cr_svuid &&	/* allow seteuid(saved uid) */
66187218Srwatson	    (error = suser_xxx(oldcred, NULL, PRISON_ROOT)) != 0)
66282749Sdillon		goto done2;
6631541Srgrimes	/*
6641541Srgrimes	 * Everything's okay, do it.  Copy credentials so other references do
6651541Srgrimes	 * not see our changes.
6661541Srgrimes	 */
66777183Srwatson	newcred = crdup(oldcred);
66877183Srwatson	if (oldcred->cr_uid != euid) {
66977183Srwatson		change_euid(newcred, euid);
67031891Ssef		setsugid(p);
67124449Speter	}
67277183Srwatson	p->p_ucred = newcred;
67377183Srwatson	crfree(oldcred);
67482749Sdillondone2:
67582749Sdillon	mtx_unlock(&Giant);
67682749Sdillon	return (error);
6771541Srgrimes}
6781541Srgrimes
67912221Sbde#ifndef _SYS_SYSPROTO_H_
6801541Srgrimesstruct setgid_args {
6811541Srgrimes	gid_t	gid;
6821541Srgrimes};
68312221Sbde#endif
68482749Sdillon/*
68582749Sdillon * MPSAFE
68682749Sdillon */
6871541Srgrimes/* ARGSUSED */
6881549Srgrimesint
68983366Sjuliansetgid(td, uap)
69083366Sjulian	struct thread *td;
6911541Srgrimes	struct setgid_args *uap;
6921541Srgrimes{
69383366Sjulian	struct proc *p = td->td_proc;
69477183Srwatson	struct ucred *newcred, *oldcred;
69577183Srwatson	gid_t gid;
69687218Srwatson	int error;
6971541Srgrimes
69877183Srwatson	gid = uap->gid;
69982749Sdillon	mtx_lock(&Giant);
70087218Srwatson	error = 0;
70177183Srwatson	oldcred = p->p_ucred;
70287466Srwatson
70324448Speter	/*
70424448Speter	 * See if we have "permission" by POSIX 1003.1 rules.
70524448Speter	 *
70624448Speter	 * Note that setgid(getegid()) is a special case of
70724448Speter	 * "appropriate privileges" in appendix B.4.2.2.  We need
70872093Sasmodai	 * to use this clause to be compatible with traditional BSD
70924448Speter	 * semantics.  Basically, it means that "setgid(xx)" sets all
71024448Speter	 * three id's (assuming you have privs).
71124448Speter	 *
71224448Speter	 * For notes on the logic here, see setuid() above.
71324448Speter	 */
71477183Srwatson	if (gid != oldcred->cr_rgid &&		/* allow setgid(getgid()) */
71517994Sache#ifdef _POSIX_SAVED_IDS
71677183Srwatson	    gid != oldcred->cr_svgid &&		/* allow setgid(saved gid) */
71717994Sache#endif
71824448Speter#ifdef POSIX_APPENDIX_B_4_2_2	/* Use BSD-compat clause from B.4.2.2 */
71977183Srwatson	    gid != oldcred->cr_groups[0] && /* allow setgid(getegid()) */
72024448Speter#endif
72187218Srwatson	    (error = suser_xxx(oldcred, NULL, PRISON_ROOT)) != 0)
72282749Sdillon		goto done2;
72324448Speter
72477183Srwatson	newcred = crdup(oldcred);
72517994Sache#ifdef _POSIX_SAVED_IDS
72624448Speter	/*
72724448Speter	 * Do we have "appropriate privileges" (are we root or gid == egid)
72824448Speter	 * If so, we are changing the real uid and saved gid.
72924448Speter	 */
73024448Speter	if (
73124448Speter#ifdef POSIX_APPENDIX_B_4_2_2	/* use the clause from B.4.2.2 */
73277183Srwatson	    gid == oldcred->cr_groups[0] ||
73317994Sache#endif
73477183Srwatson	    suser_xxx(oldcred, NULL, PRISON_ROOT) == 0) /* we are using privs */
73524448Speter#endif
73624448Speter	{
73724448Speter		/*
73824448Speter		 * Set real gid
73924448Speter		 */
74077183Srwatson		if (oldcred->cr_rgid != gid) {
74177183Srwatson			change_rgid(newcred, gid);
74231891Ssef			setsugid(p);
74324448Speter		}
74424448Speter		/*
74524448Speter		 * Set saved gid
74624448Speter		 *
74724448Speter		 * XXX always set saved gid even if not _POSIX_SAVED_IDS, as
74824448Speter		 * the security of setegid() depends on it.  B.4.2.2 says it
74924448Speter		 * is important that we should do this.
75024448Speter		 */
75177183Srwatson		if (oldcred->cr_svgid != gid) {
75277183Srwatson			change_svgid(newcred, gid);
75331891Ssef			setsugid(p);
75424448Speter		}
7558141Sache	}
75624448Speter	/*
75724448Speter	 * In all cases permitted cases, we are changing the egid.
75824448Speter	 * Copy credentials so other references do not see our changes.
75924448Speter	 */
76077183Srwatson	if (oldcred->cr_groups[0] != gid) {
76177183Srwatson		change_egid(newcred, gid);
76231891Ssef		setsugid(p);
76324448Speter	}
76477183Srwatson	p->p_ucred = newcred;
76577183Srwatson	crfree(oldcred);
76682749Sdillondone2:
76782749Sdillon	mtx_unlock(&Giant);
76882749Sdillon	return (error);
7691541Srgrimes}
7701541Srgrimes
77112221Sbde#ifndef _SYS_SYSPROTO_H_
7721541Srgrimesstruct setegid_args {
7731541Srgrimes	gid_t	egid;
7741541Srgrimes};
77512221Sbde#endif
77682749Sdillon/*
77782749Sdillon * MPSAFE
77882749Sdillon */
7791541Srgrimes/* ARGSUSED */
7801549Srgrimesint
78183366Sjuliansetegid(td, uap)
78283366Sjulian	struct thread *td;
7831541Srgrimes	struct setegid_args *uap;
7841541Srgrimes{
78583366Sjulian	struct proc *p = td->td_proc;
78677183Srwatson	struct ucred *newcred, *oldcred;
78777183Srwatson	gid_t egid;
78887218Srwatson	int error;
7891541Srgrimes
7901541Srgrimes	egid = uap->egid;
79182749Sdillon	mtx_lock(&Giant);
79287218Srwatson	error = 0;
79377183Srwatson	oldcred = p->p_ucred;
79477183Srwatson	if (egid != oldcred->cr_rgid &&		/* allow setegid(getgid()) */
79577183Srwatson	    egid != oldcred->cr_svgid &&	/* allow setegid(saved gid) */
79687218Srwatson	    (error = suser_xxx(oldcred, NULL, PRISON_ROOT)) != 0)
79782749Sdillon		goto done2;
79877183Srwatson	newcred = crdup(oldcred);
79977183Srwatson	if (oldcred->cr_groups[0] != egid) {
80077183Srwatson		change_egid(newcred, egid);
80131891Ssef		setsugid(p);
80224449Speter	}
80377183Srwatson	p->p_ucred = newcred;
80477183Srwatson	crfree(oldcred);
80582749Sdillondone2:
80682749Sdillon	mtx_unlock(&Giant);
80782749Sdillon	return (error);
8081541Srgrimes}
8091541Srgrimes
81012221Sbde#ifndef _SYS_SYSPROTO_H_
8111541Srgrimesstruct setgroups_args {
8121541Srgrimes	u_int	gidsetsize;
8131541Srgrimes	gid_t	*gidset;
8141541Srgrimes};
81512221Sbde#endif
81682749Sdillon/*
81782749Sdillon * MPSAFE
81882749Sdillon */
8191541Srgrimes/* ARGSUSED */
8201549Srgrimesint
82183366Sjuliansetgroups(td, uap)
82283366Sjulian	struct thread *td;
8231541Srgrimes	struct setgroups_args *uap;
8241541Srgrimes{
82583366Sjulian	struct proc *p = td->td_proc;
82677183Srwatson	struct ucred *newcred, *oldcred;
82777183Srwatson	u_int ngrp;
8281541Srgrimes	int error;
8291541Srgrimes
83087220Srwatson	ngrp = uap->gidsetsize;
83182749Sdillon	mtx_lock(&Giant);
83277183Srwatson	oldcred = p->p_ucred;
83387218Srwatson	if ((error = suser_xxx(oldcred, NULL, PRISON_ROOT)) != 0)
83482749Sdillon		goto done2;
83582749Sdillon	if (ngrp > NGROUPS) {
83682749Sdillon		error = EINVAL;
83782749Sdillon		goto done2;
83882749Sdillon	}
83924447Speter	/*
84024447Speter	 * XXX A little bit lazy here.  We could test if anything has
84124447Speter	 * changed before crcopy() and setting P_SUGID.
84224447Speter	 */
84377183Srwatson	newcred = crdup(oldcred);
84424447Speter	if (ngrp < 1) {
84524447Speter		/*
84624447Speter		 * setgroups(0, NULL) is a legitimate way of clearing the
84724447Speter		 * groups vector on non-BSD systems (which generally do not
84824447Speter		 * have the egid in the groups[0]).  We risk security holes
84924447Speter		 * when running non-BSD software if we do not do the same.
85024447Speter		 */
85177183Srwatson		newcred->cr_ngroups = 1;
85224447Speter	} else {
85324447Speter		if ((error = copyin((caddr_t)uap->gidset,
85477183Srwatson		    (caddr_t)newcred->cr_groups, ngrp * sizeof(gid_t)))) {
85577183Srwatson			crfree(newcred);
85682749Sdillon			goto done2;
85777183Srwatson		}
85877183Srwatson		newcred->cr_ngroups = ngrp;
85924447Speter	}
86031891Ssef	setsugid(p);
86177183Srwatson	p->p_ucred = newcred;
86277183Srwatson	crfree(oldcred);
86382749Sdillondone2:
86482749Sdillon	mtx_unlock(&Giant);
86582749Sdillon	return (error);
8661541Srgrimes}
8671541Srgrimes
86812221Sbde#ifndef _SYS_SYSPROTO_H_
8691541Srgrimesstruct setreuid_args {
8709238Sache	uid_t	ruid;
8719238Sache	uid_t	euid;
8721541Srgrimes};
87312221Sbde#endif
87482749Sdillon/*
87582749Sdillon * MPSAFE
87682749Sdillon */
8771541Srgrimes/* ARGSUSED */
8781549Srgrimesint
87983366Sjuliansetreuid(td, uap)
88083366Sjulian	register struct thread *td;
8811541Srgrimes	struct setreuid_args *uap;
8821541Srgrimes{
88383366Sjulian	struct proc *p = td->td_proc;
88477183Srwatson	struct ucred *newcred, *oldcred;
88587218Srwatson	uid_t euid, ruid;
88687218Srwatson	int error;
8871541Srgrimes
88887218Srwatson	euid = uap->euid;
8899238Sache	ruid = uap->ruid;
89082749Sdillon	mtx_lock(&Giant);
89187218Srwatson	error = 0;
89277183Srwatson	oldcred = p->p_ucred;
89377183Srwatson	if (((ruid != (uid_t)-1 && ruid != oldcred->cr_ruid &&
89477183Srwatson	      ruid != oldcred->cr_svuid) ||
89577183Srwatson	     (euid != (uid_t)-1 && euid != oldcred->cr_uid &&
89677183Srwatson	      euid != oldcred->cr_ruid && euid != oldcred->cr_svuid)) &&
89787218Srwatson	    (error = suser_xxx(oldcred, NULL, PRISON_ROOT)) != 0)
89882749Sdillon		goto done2;
89977183Srwatson	newcred = crdup(oldcred);
90077183Srwatson	if (euid != (uid_t)-1 && oldcred->cr_uid != euid) {
90177183Srwatson		change_euid(newcred, euid);
90231891Ssef		setsugid(p);
90324450Speter	}
90477183Srwatson	if (ruid != (uid_t)-1 && oldcred->cr_ruid != ruid) {
90577183Srwatson		change_ruid(newcred, ruid);
90631891Ssef		setsugid(p);
9078135Sache	}
90877183Srwatson	if ((ruid != (uid_t)-1 || newcred->cr_uid != newcred->cr_ruid) &&
90977183Srwatson	    newcred->cr_svuid != newcred->cr_uid) {
91077183Srwatson		change_svuid(newcred, newcred->cr_uid);
91131891Ssef		setsugid(p);
91224450Speter	}
91377183Srwatson	p->p_ucred = newcred;
91477183Srwatson	crfree(oldcred);
91582749Sdillondone2:
91682749Sdillon	mtx_unlock(&Giant);
91782749Sdillon	return (error);
9181541Srgrimes}
9191541Srgrimes
92012221Sbde#ifndef _SYS_SYSPROTO_H_
9211541Srgrimesstruct setregid_args {
9229238Sache	gid_t	rgid;
9239238Sache	gid_t	egid;
9241541Srgrimes};
92512221Sbde#endif
92682749Sdillon/*
92782749Sdillon * MPSAFE
92882749Sdillon */
9291541Srgrimes/* ARGSUSED */
9301549Srgrimesint
93183366Sjuliansetregid(td, uap)
93283366Sjulian	register struct thread *td;
9331541Srgrimes	struct setregid_args *uap;
9341541Srgrimes{
93583366Sjulian	struct proc *p = td->td_proc;
93677183Srwatson	struct ucred *newcred, *oldcred;
93787218Srwatson	gid_t egid, rgid;
93887218Srwatson	int error;
9391541Srgrimes
94087218Srwatson	egid = uap->egid;
9419238Sache	rgid = uap->rgid;
94282749Sdillon	mtx_lock(&Giant);
94387218Srwatson	error = 0;
94477183Srwatson	oldcred = p->p_ucred;
94577183Srwatson	if (((rgid != (gid_t)-1 && rgid != oldcred->cr_rgid &&
94677183Srwatson	    rgid != oldcred->cr_svgid) ||
94777183Srwatson	     (egid != (gid_t)-1 && egid != oldcred->cr_groups[0] &&
94877183Srwatson	     egid != oldcred->cr_rgid && egid != oldcred->cr_svgid)) &&
94987218Srwatson	    (error = suser_xxx(oldcred, NULL, PRISON_ROOT)) != 0)
95082749Sdillon		goto done2;
95177183Srwatson	newcred = crdup(oldcred);
95277183Srwatson	if (egid != (gid_t)-1 && oldcred->cr_groups[0] != egid) {
95377183Srwatson		change_egid(newcred, egid);
95431891Ssef		setsugid(p);
95524450Speter	}
95677183Srwatson	if (rgid != (gid_t)-1 && oldcred->cr_rgid != rgid) {
95777183Srwatson		change_rgid(newcred, rgid);
95831891Ssef		setsugid(p);
95924450Speter	}
96077183Srwatson	if ((rgid != (gid_t)-1 || newcred->cr_groups[0] != newcred->cr_rgid) &&
96177183Srwatson	    newcred->cr_svgid != newcred->cr_groups[0]) {
96277183Srwatson		change_svgid(newcred, newcred->cr_groups[0]);
96331891Ssef		setsugid(p);
96424450Speter	}
96577812Sru	p->p_ucred = newcred;
96677812Sru	crfree(oldcred);
96782749Sdillondone2:
96882749Sdillon	mtx_unlock(&Giant);
96982749Sdillon	return (error);
9701541Srgrimes}
9711541Srgrimes
97256115Speter/*
97356115Speter * setresuid(ruid, euid, suid) is like setreuid except control over the
97456115Speter * saved uid is explicit.
97556115Speter */
97656115Speter
97724453Speter#ifndef _SYS_SYSPROTO_H_
97856115Speterstruct setresuid_args {
97956115Speter	uid_t	ruid;
98056115Speter	uid_t	euid;
98156115Speter	uid_t	suid;
98256115Speter};
98356115Speter#endif
98482749Sdillon/*
98582749Sdillon * MPSAFE
98682749Sdillon */
98756115Speter/* ARGSUSED */
98856115Speterint
98983366Sjuliansetresuid(td, uap)
99083366Sjulian	register struct thread *td;
99156115Speter	struct setresuid_args *uap;
99256115Speter{
99383366Sjulian	struct proc *p = td->td_proc;
99477183Srwatson	struct ucred *newcred, *oldcred;
99587218Srwatson	uid_t euid, ruid, suid;
99656115Speter	int error;
99756115Speter
99887218Srwatson	euid = uap->euid;
99956115Speter	ruid = uap->ruid;
100056115Speter	suid = uap->suid;
100182749Sdillon	mtx_lock(&Giant);
100277183Srwatson	oldcred = p->p_ucred;
100377183Srwatson	if (((ruid != (uid_t)-1 && ruid != oldcred->cr_ruid &&
100477183Srwatson	     ruid != oldcred->cr_svuid &&
100577183Srwatson	      ruid != oldcred->cr_uid) ||
100677183Srwatson	     (euid != (uid_t)-1 && euid != oldcred->cr_ruid &&
100777183Srwatson	    euid != oldcred->cr_svuid &&
100877183Srwatson	      euid != oldcred->cr_uid) ||
100977183Srwatson	     (suid != (uid_t)-1 && suid != oldcred->cr_ruid &&
101077183Srwatson	    suid != oldcred->cr_svuid &&
101177183Srwatson	      suid != oldcred->cr_uid)) &&
101287218Srwatson	    (error = suser_xxx(oldcred, NULL, PRISON_ROOT)) != 0)
101382749Sdillon		goto done2;
101477183Srwatson	newcred = crdup(oldcred);
101577183Srwatson	if (euid != (uid_t)-1 && oldcred->cr_uid != euid) {
101677183Srwatson		change_euid(newcred, euid);
101756115Speter		setsugid(p);
101856115Speter	}
101977183Srwatson	if (ruid != (uid_t)-1 && oldcred->cr_ruid != ruid) {
102077183Srwatson		change_ruid(newcred, ruid);
102156115Speter		setsugid(p);
102256115Speter	}
102377183Srwatson	if (suid != (uid_t)-1 && oldcred->cr_svuid != suid) {
102477183Srwatson		change_svuid(newcred, suid);
102556115Speter		setsugid(p);
102656115Speter	}
102777183Srwatson	p->p_ucred = newcred;
102877183Srwatson	crfree(oldcred);
102982749Sdillon	error = 0;
103082749Sdillondone2:
103182749Sdillon	mtx_unlock(&Giant);
103282749Sdillon	return (error);
103356115Speter}
103456115Speter
103556115Speter/*
103656115Speter * setresgid(rgid, egid, sgid) is like setregid except control over the
103756115Speter * saved gid is explicit.
103856115Speter */
103956115Speter
104056115Speter#ifndef _SYS_SYSPROTO_H_
104156115Speterstruct setresgid_args {
104256115Speter	gid_t	rgid;
104356115Speter	gid_t	egid;
104456115Speter	gid_t	sgid;
104556115Speter};
104656115Speter#endif
104787466Srwatson/*
104882749Sdillon * MPSAFE
104982749Sdillon */
105056115Speter/* ARGSUSED */
105156115Speterint
105283366Sjuliansetresgid(td, uap)
105383366Sjulian	register struct thread *td;
105456115Speter	struct setresgid_args *uap;
105556115Speter{
105683366Sjulian	struct proc *p = td->td_proc;
105777183Srwatson	struct ucred *newcred, *oldcred;
105887218Srwatson	gid_t egid, rgid, sgid;
105956115Speter	int error;
106056115Speter
106187218Srwatson	egid = uap->egid;
106256115Speter	rgid = uap->rgid;
106356115Speter	sgid = uap->sgid;
106482749Sdillon	mtx_lock(&Giant);
106577183Srwatson	oldcred = p->p_ucred;
106677183Srwatson	if (((rgid != (gid_t)-1 && rgid != oldcred->cr_rgid &&
106777183Srwatson	      rgid != oldcred->cr_svgid &&
106877183Srwatson	      rgid != oldcred->cr_groups[0]) ||
106977183Srwatson	     (egid != (gid_t)-1 && egid != oldcred->cr_rgid &&
107077183Srwatson	      egid != oldcred->cr_svgid &&
107177183Srwatson	      egid != oldcred->cr_groups[0]) ||
107277183Srwatson	     (sgid != (gid_t)-1 && sgid != oldcred->cr_rgid &&
107377183Srwatson	      sgid != oldcred->cr_svgid &&
107477183Srwatson	      sgid != oldcred->cr_groups[0])) &&
107587466Srwatson	    (error = suser_xxx(oldcred, NULL, PRISON_ROOT)) != 0)
107682749Sdillon		goto done2;
107777183Srwatson	newcred = crdup(oldcred);
107877183Srwatson	if (egid != (gid_t)-1 && oldcred->cr_groups[0] != egid) {
107977183Srwatson		change_egid(newcred, egid);
108056115Speter		setsugid(p);
108156115Speter	}
108277183Srwatson	if (rgid != (gid_t)-1 && oldcred->cr_rgid != rgid) {
108377183Srwatson		change_rgid(newcred, rgid);
108456115Speter		setsugid(p);
108556115Speter	}
108677183Srwatson	if (sgid != (gid_t)-1 && oldcred->cr_svgid != sgid) {
108777183Srwatson		change_svgid(newcred, sgid);
108856115Speter		setsugid(p);
108956115Speter	}
109077183Srwatson	p->p_ucred = newcred;
109177183Srwatson	crfree(oldcred);
109282749Sdillon	error = 0;
109382749Sdillondone2:
109482749Sdillon	mtx_unlock(&Giant);
109582749Sdillon	return (error);
109656115Speter}
109756115Speter
109856115Speter#ifndef _SYS_SYSPROTO_H_
109956115Speterstruct getresuid_args {
110056115Speter	uid_t	*ruid;
110156115Speter	uid_t	*euid;
110256115Speter	uid_t	*suid;
110356115Speter};
110456115Speter#endif
110582749Sdillon/*
110682749Sdillon * MPSAFE
110782749Sdillon */
110856115Speter/* ARGSUSED */
110956115Speterint
111083366Sjuliangetresuid(td, uap)
111183366Sjulian	register struct thread *td;
111256115Speter	struct getresuid_args *uap;
111356115Speter{
111482749Sdillon	struct ucred *cred;
111583366Sjulian	struct proc *p = td->td_proc;
111656115Speter	int error1 = 0, error2 = 0, error3 = 0;
111756115Speter
111882749Sdillon	mtx_lock(&Giant);
111982749Sdillon	cred = p->p_ucred;
112056115Speter	if (uap->ruid)
112177183Srwatson		error1 = copyout((caddr_t)&cred->cr_ruid,
112277183Srwatson		    (caddr_t)uap->ruid, sizeof(cred->cr_ruid));
112356115Speter	if (uap->euid)
112477183Srwatson		error2 = copyout((caddr_t)&cred->cr_uid,
112577183Srwatson		    (caddr_t)uap->euid, sizeof(cred->cr_uid));
112656115Speter	if (uap->suid)
112777183Srwatson		error3 = copyout((caddr_t)&cred->cr_svuid,
112877183Srwatson		    (caddr_t)uap->suid, sizeof(cred->cr_svuid));
112982749Sdillon	mtx_unlock(&Giant);
113087218Srwatson	return (error1 ? error1 : error2 ? error2 : error3);
113156115Speter}
113256115Speter
113356115Speter#ifndef _SYS_SYSPROTO_H_
113456115Speterstruct getresgid_args {
113556115Speter	gid_t	*rgid;
113656115Speter	gid_t	*egid;
113756115Speter	gid_t	*sgid;
113856115Speter};
113956115Speter#endif
114082749Sdillon/*
114182749Sdillon * MPSAFE
114282749Sdillon */
114356115Speter/* ARGSUSED */
114456115Speterint
114583366Sjuliangetresgid(td, uap)
114683366Sjulian	register struct thread *td;
114756115Speter	struct getresgid_args *uap;
114856115Speter{
114982749Sdillon	struct ucred *cred;
115083366Sjulian	struct proc *p = td->td_proc;
115156115Speter	int error1 = 0, error2 = 0, error3 = 0;
115256115Speter
115382749Sdillon	mtx_lock(&Giant);
115482749Sdillon	cred = p->p_ucred;
115556115Speter	if (uap->rgid)
115677183Srwatson		error1 = copyout((caddr_t)&cred->cr_rgid,
115777183Srwatson		    (caddr_t)uap->rgid, sizeof(cred->cr_rgid));
115856115Speter	if (uap->egid)
115977183Srwatson		error2 = copyout((caddr_t)&cred->cr_groups[0],
116077183Srwatson		    (caddr_t)uap->egid, sizeof(cred->cr_groups[0]));
116156115Speter	if (uap->sgid)
116277183Srwatson		error3 = copyout((caddr_t)&cred->cr_svgid,
116377183Srwatson		    (caddr_t)uap->sgid, sizeof(cred->cr_svgid));
116482749Sdillon	mtx_unlock(&Giant);
116587218Srwatson	return (error1 ? error1 : error2 ? error2 : error3);
116656115Speter}
116756115Speter
116856115Speter#ifndef _SYS_SYSPROTO_H_
116924453Speterstruct issetugid_args {
117024453Speter	int dummy;
117124453Speter};
117224453Speter#endif
117387218Srwatson/*
117487218Srwatson * NOT MPSAFE?
117587218Srwatson */
117624453Speter/* ARGSUSED */
117724453Speterint
117883366Sjulianissetugid(td, uap)
117983366Sjulian	register struct thread *td;
118024453Speter	struct issetugid_args *uap;
118124453Speter{
118283366Sjulian	struct proc *p = td->td_proc;
118383366Sjulian
118424453Speter	/*
118524453Speter	 * Note: OpenBSD sets a P_SUGIDEXEC flag set at execve() time,
118624453Speter	 * we use P_SUGID because we consider changing the owners as
118724453Speter	 * "tainting" as well.
118824453Speter	 * This is significant for procs that start as root and "become"
118924453Speter	 * a user without an exec - programs cannot know *everything*
119024453Speter	 * that libc *might* have put in their data segment.
119124453Speter	 */
119291140Stanimura	PROC_LOCK(p);
119383366Sjulian	td->td_retval[0] = (p->p_flag & P_SUGID) ? 1 : 0;
119491140Stanimura	PROC_UNLOCK(p);
119524453Speter	return (0);
119624453Speter}
119724453Speter
119882749Sdillon/*
119982749Sdillon * MPSAFE
120082749Sdillon */
120175426Srwatsonint
120283366Sjulian__setugid(td, uap)
120383366Sjulian	struct thread *td;
120475426Srwatson	struct __setugid_args *uap;
120575426Srwatson{
120682749Sdillon#ifdef REGRESSION
120787218Srwatson	int error;
120875426Srwatson
120982749Sdillon	mtx_lock(&Giant);
121087218Srwatson	error = 0;
121175426Srwatson	switch (uap->flag) {
121275426Srwatson	case 0:
121391140Stanimura		PROC_LOCK(td->td_proc);
121483366Sjulian		td->td_proc->p_flag &= ~P_SUGID;
121591140Stanimura		PROC_UNLOCK(td->td_proc);
121682749Sdillon		break;
121775426Srwatson	case 1:
121891140Stanimura		PROC_LOCK(td->td_proc);
121983366Sjulian		td->td_proc->p_flag |= P_SUGID;
122091140Stanimura		PROC_UNLOCK(td->td_proc);
122182749Sdillon		break;
122275426Srwatson	default:
122382749Sdillon		error = EINVAL;
122482749Sdillon		break;
122575426Srwatson	}
122682749Sdillon	mtx_unlock(&Giant);
122782749Sdillon	return (error);
122875426Srwatson#else /* !REGRESSION */
122987218Srwatson
123075426Srwatson	return (ENOSYS);
123187218Srwatson#endif /* REGRESSION */
123275426Srwatson}
123375426Srwatson
12341541Srgrimes/*
12351541Srgrimes * Check if gid is a member of the group set.
12361541Srgrimes */
12371549Srgrimesint
12381541Srgrimesgroupmember(gid, cred)
12391541Srgrimes	gid_t gid;
124077183Srwatson	struct ucred *cred;
12411541Srgrimes{
12421541Srgrimes	register gid_t *gp;
12431541Srgrimes	gid_t *egp;
12441541Srgrimes
12451541Srgrimes	egp = &(cred->cr_groups[cred->cr_ngroups]);
12461541Srgrimes	for (gp = cred->cr_groups; gp < egp; gp++)
12471541Srgrimes		if (*gp == gid)
12481541Srgrimes			return (1);
12491541Srgrimes	return (0);
12501541Srgrimes}
12511541Srgrimes
125282424Srwatson/*
125389414Sarr * `suser_enabled' (which can be set by the security.suser_enabled
125482466Srwatson * sysctl) determines whether the system 'super-user' policy is in effect.
125582466Srwatson * If it is nonzero, an effective uid of 0 connotes special privilege,
125682466Srwatson * overriding many mandatory and discretionary protections.  If it is zero,
125782466Srwatson * uid 0 is offered no special privilege in the kernel security policy.
125882466Srwatson * Setting it to zero may seriously impact the functionality of many
125982466Srwatson * existing userland programs, and should not be done without careful
126082466Srwatson * consideration of the consequences.
126182424Srwatson */
126282693Srwatsonint	suser_enabled = 1;
126389414SarrSYSCTL_INT(_security_bsd, OID_AUTO, suser_enabled, CTLFLAG_RW,
126482693Srwatson    &suser_enabled, 0, "processes with uid 0 have privilege");
126589414SarrTUNABLE_INT("security.bsd.suser_enabled", &suser_enabled);
126661287Srwatson
12671541Srgrimes/*
126882466Srwatson * Test whether the specified credentials imply "super-user" privilege.
126982466Srwatson * Return 0 or EPERM.
12701541Srgrimes */
12711549Srgrimesint
127246112Sphksuser(p)
127372786Srwatson	struct proc *p;
127446112Sphk{
127587218Srwatson
127687218Srwatson	return (suser_xxx(0, p, 0));
127746112Sphk}
127846112Sphk
127983366Sjulian/*
128083366Sjulian * version for when the thread pointer is available and not the proc.
128183366Sjulian * (saves having to include proc.h into every file that needs to do the change.)
128283366Sjulian */
128346112Sphkint
128483366Sjuliansuser_td(td)
128583366Sjulian	struct thread *td;
128683366Sjulian{
128787466Srwatson	return (suser_xxx(0, td->td_proc, 0));
128883366Sjulian}
128983366Sjulian
129083366Sjulian/*
129183366Sjulian * wrapper to use if you have the thread on hand but not the proc.
129283366Sjulian */
129383366Sjulianint
129483366Sjuliansuser_xxx_td(cred, td, flag)
129583366Sjulian	struct ucred *cred;
129683366Sjulian	struct thread *td;
129783366Sjulian	int flag;
129883366Sjulian{
129983366Sjulian	return(suser_xxx(cred, td->td_proc, flag));
130083366Sjulian}
130183366Sjulian
130283366Sjulianint
130346155Sphksuser_xxx(cred, proc, flag)
130472786Srwatson	struct ucred *cred;
130572786Srwatson	struct proc *proc;
130646155Sphk	int flag;
13071541Srgrimes{
130882693Srwatson	if (!suser_enabled)
130961282Srwatson		return (EPERM);
131046155Sphk	if (!cred && !proc) {
131146155Sphk		printf("suser_xxx(): THINK!\n");
131246155Sphk		return (EPERM);
13131541Srgrimes	}
131487218Srwatson	if (cred == NULL)
131546155Sphk		cred = proc->p_ucred;
131687218Srwatson	if (cred->cr_uid != 0)
131746155Sphk		return (EPERM);
131872786Srwatson	if (jailed(cred) && !(flag & PRISON_ROOT))
131946155Sphk		return (EPERM);
132046155Sphk	return (0);
13211541Srgrimes}
13221541Srgrimes
132383639Srwatson/*
132487218Srwatson * Test the active securelevel against a given level.  securelevel_gt()
132587218Srwatson * implements (securelevel > level).  securelevel_ge() implements
132687218Srwatson * (securelevel >= level).  Note that the logic is inverted -- these
132787218Srwatson * functions return EPERM on "success" and 0 on "failure".
132883639Srwatson *
132983639Srwatson * cr is permitted to be NULL for the time being, as there were some
133083639Srwatson * existing securelevel checks that occurred without a process/credential
133187218Srwatson * context.  In the future this will be disallowed, so a kernel message
133287218Srwatson * is displayed.
133383639Srwatson */
133483639Srwatsonint
133583639Srwatsonsecurelevel_gt(struct ucred *cr, int level)
133683639Srwatson{
133787218Srwatson	int active_securelevel;
133883639Srwatson
133987218Srwatson	active_securelevel = securelevel;
134087218Srwatson	if (cr == NULL)
134192951Srwatson		panic("securelevel_gt: cr is NULL\n");
134287275Srwatson	if (cr->cr_prison != NULL) {
134387275Srwatson		mtx_lock(&cr->cr_prison->pr_mtx);
134487218Srwatson		active_securelevel = imax(cr->cr_prison->pr_securelevel,
134587218Srwatson		    active_securelevel);
134687275Srwatson		mtx_unlock(&cr->cr_prison->pr_mtx);
134787275Srwatson	}
134887218Srwatson	return (active_securelevel > level ? EPERM : 0);
134983639Srwatson}
135083639Srwatson
135183639Srwatsonint
135283639Srwatsonsecurelevel_ge(struct ucred *cr, int level)
135383639Srwatson{
135487218Srwatson	int active_securelevel;
135583639Srwatson
135687218Srwatson	active_securelevel = securelevel;
135787218Srwatson	if (cr == NULL)
135892951Srwatson		panic("securelevel_gt: cr is NULL\n");
135987275Srwatson	if (cr->cr_prison != NULL) {
136087275Srwatson		mtx_lock(&cr->cr_prison->pr_mtx);
136187218Srwatson		active_securelevel = imax(cr->cr_prison->pr_securelevel,
136287218Srwatson		    active_securelevel);
136387275Srwatson		mtx_unlock(&cr->cr_prison->pr_mtx);
136487275Srwatson	}
136587218Srwatson	return (active_securelevel >= level ? EPERM : 0);
136683639Srwatson}
136783639Srwatson
136884736Srwatson/*
136987144Srwatson * 'see_other_uids' determines whether or not visibility of processes
137087218Srwatson * and sockets with credentials holding different real uids is possible
137187138Srwatson * using a variety of system MIBs.
137287218Srwatson * XXX: data declarations should be together near the beginning of the file.
137384736Srwatson */
137487144Srwatsonstatic int	see_other_uids = 1;
137589414SarrSYSCTL_INT(_security_bsd, OID_AUTO, see_other_uids, CTLFLAG_RW,
137687218Srwatson    &see_other_uids, 0,
137784736Srwatson    "Unprivileged processes may see subjects/objects with different real uid");
137884736Srwatson
137982466Srwatson/*-
138092923Srwatson * Determine if u1 "can see" the subject specified by u2, according to the
138192923Srwatson * 'see_other_uids' policy.
138292923Srwatson * Returns: 0 for permitted, ESRCH otherwise
138392923Srwatson * Locks: none
138492923Srwatson * References: *u1 and *u2 must not change during the call
138592923Srwatson *             u1 may equal u2, in which case only one reference is required
138692923Srwatson */
138792923Srwatsonstatic int
138892923Srwatsoncr_seeotheruids(struct ucred *u1, struct ucred *u2)
138992923Srwatson{
139092923Srwatson
139192923Srwatson	if (!see_other_uids && u1->cr_ruid != u2->cr_ruid) {
139292923Srwatson		if (suser_xxx(u1, NULL, PRISON_ROOT) != 0)
139392923Srwatson			return (ESRCH);
139492923Srwatson	}
139592923Srwatson	return (0);
139692923Srwatson}
139792923Srwatson
139892923Srwatson/*-
139982466Srwatson * Determine if u1 "can see" the subject specified by u2.
140074956Srwatson * Returns: 0 for permitted, an errno value otherwise
140174956Srwatson * Locks: none
140287218Srwatson * References: *u1 and *u2 must not change during the call
140374956Srwatson *             u1 may equal u2, in which case only one reference is required
140474956Srwatson */
140574956Srwatsonint
140683742Srwatsoncr_cansee(struct ucred *u1, struct ucred *u2)
140765237Srwatson{
140872786Srwatson	int error;
140953518Sphk
141074956Srwatson	if ((error = prison_check(u1, u2)))
141172786Srwatson		return (error);
141292923Srwatson	if ((error = cr_seeotheruids(u1, u2)))
141392923Srwatson		return (error);
141465237Srwatson	return (0);
141565237Srwatson}
141665237Srwatson
141782466Srwatson/*-
141882466Srwatson * Determine if p1 "can see" the subject specified by p2.
141982424Srwatson * Returns: 0 for permitted, an errno value otherwise
142082466Srwatson * Locks: Sufficient locks to protect p1->p_ucred and p2->p_ucred must
142182424Srwatson *        be held.  Normally, p1 will be curproc, and a lock must be held
142282424Srwatson *        for p2.
142382424Srwatson * References: p1 and p2 must be valid for the lifetime of the call
142482424Srwatson */
142579335Srwatsonint
142679335Srwatsonp_cansee(struct proc *p1, struct proc *p2)
142774956Srwatson{
142874956Srwatson
142983742Srwatson	/* Wrap cr_cansee() for all functionality. */
143083742Srwatson	return (cr_cansee(p1->p_ucred, p2->p_ucred));
143174956Srwatson}
143274956Srwatson
143382466Srwatson/*-
143488943Srwatson * Determine whether cred may deliver the specified signal to proc.
143588943Srwatson * Returns: 0 for permitted, an errno value otherwise.
143688943Srwatson * Locks: A lock must be held for proc.
143788943Srwatson * References: cred and proc must be valid for the lifetime of the call.
143875437Srwatson */
143975437Srwatsonint
144088943Srwatsoncr_cansignal(struct ucred *cred, struct proc *proc, int signum)
144153518Sphk{
144282466Srwatson	int error;
144384826Sjhb
144475437Srwatson	/*
144588943Srwatson	 * Jail semantics limit the scope of signalling to proc in the
144688943Srwatson	 * same jail as cred, if cred is in jail.
144775437Srwatson	 */
144888943Srwatson	error = prison_check(cred, proc->p_ucred);
144988943Srwatson	if (error)
145072786Srwatson		return (error);
145192923Srwatson	error = cr_seeotheruids(cred, proc->p_ucred);
145292923Srwatson	if (error)
145392923Srwatson		return (error);
145465237Srwatson
145565237Srwatson	/*
145682424Srwatson	 * UNIX signal semantics depend on the status of the P_SUGID
145782424Srwatson	 * bit on the target process.  If the bit is set, then additional
145882424Srwatson	 * restrictions are placed on the set of available signals.
145975437Srwatson	 */
146088943Srwatson	if (proc->p_flag & P_SUGID) {
146175437Srwatson		switch (signum) {
146275437Srwatson		case 0:
146375437Srwatson		case SIGKILL:
146475437Srwatson		case SIGINT:
146575437Srwatson		case SIGTERM:
146675437Srwatson		case SIGSTOP:
146775437Srwatson		case SIGTTIN:
146875437Srwatson		case SIGTTOU:
146975437Srwatson		case SIGTSTP:
147075437Srwatson		case SIGHUP:
147175437Srwatson		case SIGUSR1:
147275437Srwatson		case SIGUSR2:
147382466Srwatson			/*
147482466Srwatson			 * Generally, permit job and terminal control
147582466Srwatson			 * signals.
147682466Srwatson			 */
147775437Srwatson			break;
147875437Srwatson		default:
147988943Srwatson			/* Not permitted without privilege. */
148088943Srwatson			error = suser_xxx(cred, NULL, PRISON_ROOT);
148175437Srwatson			if (error)
148275437Srwatson				return (error);
148375437Srwatson		}
148465237Srwatson	}
148565237Srwatson
148675480Srwatson	/*
148782424Srwatson	 * Generally, the target credential's ruid or svuid must match the
148875480Srwatson	 * subject credential's ruid or euid.
148975480Srwatson	 */
149088943Srwatson	if (cred->cr_ruid != proc->p_ucred->cr_ruid &&
149188943Srwatson	    cred->cr_ruid != proc->p_ucred->cr_svuid &&
149288943Srwatson	    cred->cr_uid != proc->p_ucred->cr_ruid &&
149388943Srwatson	    cred->cr_uid != proc->p_ucred->cr_svuid) {
149488943Srwatson		/* Not permitted without privilege. */
149588943Srwatson		error = suser_xxx(cred, NULL, PRISON_ROOT);
149675480Srwatson		if (error)
149775480Srwatson			return (error);
149875480Srwatson	}
149975480Srwatson
150087218Srwatson	return (0);
150153518Sphk}
150253518Sphk
150388943Srwatson
150482466Srwatson/*-
150588943Srwatson * Determine whether p1 may deliver the specified signal to p2.
150688943Srwatson * Returns: 0 for permitted, an errno value otherwise
150788943Srwatson * Locks: Sufficient locks to protect various components of p1 and p2
150888943Srwatson *        must be held.  Normally, p1 will be curproc, and a lock must
150988943Srwatson *        be held for p2.
151088943Srwatson * References: p1 and p2 must be valid for the lifetime of the call
151188943Srwatson */
151288943Srwatsonint
151388943Srwatsonp_cansignal(struct proc *p1, struct proc *p2, int signum)
151488943Srwatson{
151588943Srwatson
151688943Srwatson	if (p1 == p2)
151788943Srwatson		return (0);
151888943Srwatson
151988943Srwatson	/*
152088943Srwatson	 * UNIX signalling semantics require that processes in the same
152188943Srwatson	 * session always be able to deliver SIGCONT to one another,
152288943Srwatson	 * overriding the remaining protections.
152388943Srwatson	 */
152488943Srwatson	if (signum == SIGCONT && p1->p_session == p2->p_session)
152588943Srwatson		return (0);
152688943Srwatson
152788943Srwatson	return (cr_cansignal(p1->p_ucred, p2, signum));
152888943Srwatson}
152988943Srwatson
153088943Srwatson/*-
153187218Srwatson * Determine whether p1 may reschedule p2.
153282466Srwatson * Returns: 0 for permitted, an errno value otherwise
153382424Srwatson * Locks: Sufficient locks to protect various components of p1 and p2
153482424Srwatson *        must be held.  Normally, p1 will be curproc, and a lock must
153582466Srwatson *        be held for p2.
153682424Srwatson * References: p1 and p2 must be valid for the lifetime of the call
153782424Srwatson */
153879335Srwatsonint
153979335Srwatsonp_cansched(struct proc *p1, struct proc *p2)
154065237Srwatson{
154172786Srwatson	int error;
154265237Srwatson
154365237Srwatson	if (p1 == p2)
154465237Srwatson		return (0);
154572786Srwatson	if ((error = prison_check(p1->p_ucred, p2->p_ucred)))
154672786Srwatson		return (error);
154792923Srwatson	if ((error = cr_seeotheruids(p1->p_ucred, p2->p_ucred)))
154892923Srwatson		return (error);
154977183Srwatson	if (p1->p_ucred->cr_ruid == p2->p_ucred->cr_ruid)
155065237Srwatson		return (0);
155177183Srwatson	if (p1->p_ucred->cr_uid == p2->p_ucred->cr_ruid)
155265237Srwatson		return (0);
155382466Srwatson	if (suser_xxx(0, p1, PRISON_ROOT) == 0)
155465237Srwatson		return (0);
155565237Srwatson
155665237Srwatson#ifdef CAPABILITIES
155785874Srwatson	if (!cap_check(NULL, p1, CAP_SYS_NICE, PRISON_ROOT))
155865237Srwatson		return (0);
155965237Srwatson#endif
156065237Srwatson
156165237Srwatson	return (EPERM);
156265237Srwatson}
156365237Srwatson
156482424Srwatson/*
156587280Srwatson * The 'unprivileged_proc_debug' flag may be used to disable a variety of
156687280Srwatson * unprivileged inter-process debugging services, including some procfs
156787280Srwatson * functionality, ptrace(), and ktrace().  In the past, inter-process
156887280Srwatson * debugging has been involved in a variety of security problems, and sites
156987280Srwatson * not requiring the service might choose to disable it when hardening
157087280Srwatson * systems.
157182424Srwatson *
157282424Srwatson * XXX: Should modifying and reading this variable require locking?
157387218Srwatson * XXX: data declarations should be together near the beginning of the file.
157482424Srwatson */
157587144Srwatsonstatic int	unprivileged_proc_debug = 1;
157689414SarrSYSCTL_INT(_security_bsd, OID_AUTO, unprivileged_proc_debug, CTLFLAG_RW,
157787218Srwatson    &unprivileged_proc_debug, 0,
157880735Srwatson    "Unprivileged processes may use process debugging facilities");
157980735Srwatson
158082466Srwatson/*-
158182466Srwatson * Determine whether p1 may debug p2.
158282466Srwatson * Returns: 0 for permitted, an errno value otherwise
158382466Srwatson * Locks: Sufficient locks to protect various components of p1 and p2
158482466Srwatson *        must be held.  Normally, p1 will be curproc, and a lock must
158582466Srwatson *        be held for p2.
158682424Srwatson * References: p1 and p2 must be valid for the lifetime of the call
158782424Srwatson */
158879335Srwatsonint
158979335Srwatsonp_candebug(struct proc *p1, struct proc *p2)
159065237Srwatson{
159187218Srwatson	int credentialchanged, error, grpsubset, i, uidsubset;
159265237Srwatson
159387144Srwatson	if (!unprivileged_proc_debug) {
159484727Srwatson		error = suser_xxx(NULL, p1, PRISON_ROOT);
159584727Srwatson		if (error)
159684727Srwatson			return (error);
159784727Srwatson	}
159884636Sdes	if (p1 == p2)
159984636Sdes		return (0);
160072786Srwatson	if ((error = prison_check(p1->p_ucred, p2->p_ucred)))
160172786Srwatson		return (error);
160292923Srwatson	if ((error = cr_seeotheruids(p1->p_ucred, p2->p_ucred)))
160392923Srwatson		return (error);
160465237Srwatson
160582466Srwatson	/*
160685895Srwatson	 * Is p2's group set a subset of p1's effective group set?  This
160785895Srwatson	 * includes p2's egid, group access list, rgid, and svgid.
160882466Srwatson	 */
160985895Srwatson	grpsubset = 1;
161085895Srwatson	for (i = 0; i < p2->p_ucred->cr_ngroups; i++) {
161185895Srwatson		if (!groupmember(p2->p_ucred->cr_groups[i], p1->p_ucred)) {
161285895Srwatson			grpsubset = 0;
161385895Srwatson			break;
161485895Srwatson		}
161585895Srwatson	}
161685895Srwatson	grpsubset = grpsubset &&
161785895Srwatson	    groupmember(p2->p_ucred->cr_rgid, p1->p_ucred) &&
161885895Srwatson	    groupmember(p2->p_ucred->cr_svgid, p1->p_ucred);
161985895Srwatson
162085895Srwatson	/*
162185895Srwatson	 * Are the uids present in p2's credential equal to p1's
162285895Srwatson	 * effective uid?  This includes p2's euid, svuid, and ruid.
162385895Srwatson	 */
162485895Srwatson	uidsubset = (p1->p_ucred->cr_uid == p2->p_ucred->cr_uid &&
162585895Srwatson	    p1->p_ucred->cr_uid == p2->p_ucred->cr_svuid &&
162685895Srwatson	    p1->p_ucred->cr_uid == p2->p_ucred->cr_ruid);
162785895Srwatson
162885895Srwatson	/*
162985895Srwatson	 * Has the credential of the process changed since the last exec()?
163085895Srwatson	 */
163185895Srwatson	credentialchanged = (p2->p_flag & P_SUGID);
163285895Srwatson
163385895Srwatson	/*
163485895Srwatson	 * If p2's gids aren't a subset, or the uids aren't a subset,
163585895Srwatson	 * or the credential has changed, require appropriate privilege
163685895Srwatson	 * for p1 to debug p2.  For POSIX.1e capabilities, this will
163785895Srwatson	 * require CAP_SYS_PTRACE.
163885895Srwatson	 */
163985895Srwatson	if (!grpsubset || !uidsubset || credentialchanged) {
164084727Srwatson		error = suser_xxx(NULL, p1, PRISON_ROOT);
164184727Srwatson		if (error)
164265237Srwatson			return (error);
164382466Srwatson	}
164465237Srwatson
164587218Srwatson	/* Can't trace init when securelevel > 0. */
164687218Srwatson	if (p2 == initproc) {
164783639Srwatson		error = securelevel_gt(p1->p_ucred, 0);
164883639Srwatson		if (error)
164983639Srwatson			return (error);
165083639Srwatson	}
165165237Srwatson
165285880Srwatson	/*
165385880Srwatson	 * Can't trace a process that's currently exec'ing.
165485880Srwatson	 * XXX: Note, this is not a security policy decision, it's a
165585880Srwatson	 * basic correctness/functionality decision.  Therefore, this check
165685880Srwatson	 * should be moved to the caller's of p_candebug().
165785880Srwatson	 */
165885598Sdes	if ((p2->p_flag & P_INEXEC) != 0)
165985598Sdes		return (EAGAIN);
166087466Srwatson
166165237Srwatson	return (0);
166265237Srwatson}
166365237Srwatson
166492976Srwatson/*-
166592976Srwatson * Determine whether the subject represented by cred can "see" a socket.
166692976Srwatson * Returns: 0 for permitted, ENOENT otherwise.
166792976Srwatson */
166892976Srwatsonint
166992976Srwatsoncr_canseesocket(struct ucred *cred, struct socket *so)
167092976Srwatson{
167192976Srwatson	int error;
167292976Srwatson
167392976Srwatson	error = prison_check(cred, so->so_cred);
167492976Srwatson	if (error)
167592976Srwatson		return (ENOENT);
167692976Srwatson	if (cr_seeotheruids(cred, so->so_cred))
167792976Srwatson		return (ENOENT);
167892976Srwatson#ifdef MAC
167992976Srwatson	/* XXX: error = mac_cred_check_seesocket() here. */
168092976Srwatson#endif
168192976Srwatson
168292976Srwatson	return (0);
168392976Srwatson}
168492976Srwatson
168553518Sphk/*
16861541Srgrimes * Allocate a zeroed cred structure.
16871541Srgrimes */
16881541Srgrimesstruct ucred *
16891541Srgrimescrget()
16901541Srgrimes{
16911541Srgrimes	register struct ucred *cr;
16921541Srgrimes
169384826Sjhb	MALLOC(cr, struct ucred *, sizeof(*cr), M_CRED, M_WAITOK | M_ZERO);
16941541Srgrimes	cr->cr_ref = 1;
169590756Sdillon	cr->cr_mtxp = mtx_pool_find(cr);
16961541Srgrimes	return (cr);
16971541Srgrimes}
16981541Srgrimes
16991541Srgrimes/*
170082466Srwatson * Claim another reference to a ucred structure.
170169401Salfred */
170284827Sjhbstruct ucred *
170369401Salfredcrhold(cr)
170469401Salfred	struct ucred *cr;
170569401Salfred{
170669401Salfred
170790756Sdillon	mtx_lock(cr->cr_mtxp);
170869401Salfred	cr->cr_ref++;
170990756Sdillon	mtx_unlock(cr->cr_mtxp);
171084827Sjhb	return (cr);
171169401Salfred}
171269401Salfred
171369401Salfred/*
17141541Srgrimes * Free a cred structure.
17151541Srgrimes * Throws away space when ref count gets to 0.
17161541Srgrimes */
17171549Srgrimesvoid
17181541Srgrimescrfree(cr)
17191541Srgrimes	struct ucred *cr;
17201541Srgrimes{
172190756Sdillon	struct mtx *mtxp = cr->cr_mtxp;
172269239Salfred
172390756Sdillon	mtx_lock(mtxp);
172475632Salfred	KASSERT(cr->cr_ref > 0, ("bad ucred refcount: %d", cr->cr_ref));
172565495Struckman	if (--cr->cr_ref == 0) {
172665495Struckman		/*
172765495Struckman		 * Some callers of crget(), such as nfs_statfs(),
172865495Struckman		 * allocate a temporary credential, but don't
172965495Struckman		 * allocate a uidinfo structure.
173065495Struckman		 */
173190756Sdillon		mtx_unlock(mtxp);
173292823Sjhb		mtx_lock(&Giant);
173365495Struckman		if (cr->cr_uidinfo != NULL)
173465495Struckman			uifree(cr->cr_uidinfo);
173577277Srwatson		if (cr->cr_ruidinfo != NULL)
173677277Srwatson			uifree(cr->cr_ruidinfo);
173772786Srwatson		/*
173872786Srwatson		 * Free a prison, if any.
173972786Srwatson		 */
174072786Srwatson		if (jailed(cr))
174172786Srwatson			prison_free(cr->cr_prison);
17421541Srgrimes		FREE((caddr_t)cr, M_CRED);
174392823Sjhb		mtx_unlock(&Giant);
174490756Sdillon	} else {
174590756Sdillon		mtx_unlock(mtxp);
174690756Sdillon	}
17471541Srgrimes}
17481541Srgrimes
17491541Srgrimes/*
175084827Sjhb * Check to see if this ucred is shared.
17511541Srgrimes */
175284827Sjhbint
175384827Sjhbcrshared(cr)
17541541Srgrimes	struct ucred *cr;
17551541Srgrimes{
175684827Sjhb	int shared;
17571541Srgrimes
175890756Sdillon	mtx_lock(cr->cr_mtxp);
175984827Sjhb	shared = (cr->cr_ref > 1);
176090756Sdillon	mtx_unlock(cr->cr_mtxp);
176184827Sjhb	return (shared);
17621541Srgrimes}
17631541Srgrimes
17641541Srgrimes/*
176584827Sjhb * Copy a ucred's contents from a template.  Does not block.
176684827Sjhb */
176784827Sjhbvoid
176884827Sjhbcrcopy(dest, src)
176984827Sjhb	struct ucred *dest, *src;
177084827Sjhb{
177184827Sjhb
177284827Sjhb	KASSERT(crshared(dest) == 0, ("crcopy of shared ucred"));
177384827Sjhb	bcopy(&src->cr_startcopy, &dest->cr_startcopy,
177487218Srwatson	    (unsigned)((caddr_t)&src->cr_endcopy -
177584827Sjhb		(caddr_t)&src->cr_startcopy));
177684827Sjhb	uihold(dest->cr_uidinfo);
177784827Sjhb	uihold(dest->cr_ruidinfo);
177884827Sjhb	if (jailed(dest))
177984827Sjhb		prison_hold(dest->cr_prison);
178084827Sjhb}
178184827Sjhb
178284827Sjhb/*
17831541Srgrimes * Dup cred struct to a new held one.
17841541Srgrimes */
17851541Srgrimesstruct ucred *
17861541Srgrimescrdup(cr)
17871541Srgrimes	struct ucred *cr;
17881541Srgrimes{
17891541Srgrimes	struct ucred *newcr;
17901541Srgrimes
179184827Sjhb	newcr = crget();
179284827Sjhb	crcopy(newcr, cr);
17931541Srgrimes	return (newcr);
17941541Srgrimes}
17951541Srgrimes
179692823Sjhb#ifdef DIAGNOSTIC
179792823Sjhbvoid
179892823Sjhbcred_free_thread(struct thread *td)
179992823Sjhb{
180092823Sjhb	struct ucred *cred;
180192823Sjhb
180292823Sjhb	cred = td->td_ucred;
180392823Sjhb	td->td_ucred = NULL;
180492823Sjhb	if (cred != NULL)
180592823Sjhb		crfree(cred);
180692823Sjhb}
180792823Sjhb#endif
180892823Sjhb
18091541Srgrimes/*
181091354Sdd * Fill in a struct xucred based on a struct ucred.
181191354Sdd */
181291354Sddvoid
181391354Sddcru2x(cr, xcr)
181491354Sdd	struct ucred *cr;
181591354Sdd	struct xucred *xcr;
181691354Sdd{
181791354Sdd
181891354Sdd	bzero(xcr, sizeof(*xcr));
181991354Sdd	xcr->cr_version = XUCRED_VERSION;
182091354Sdd	xcr->cr_uid = cr->cr_uid;
182191354Sdd	xcr->cr_ngroups = cr->cr_ngroups;
182291354Sdd	bcopy(cr->cr_groups, xcr->cr_groups, sizeof(cr->cr_groups));
182391354Sdd}
182491354Sdd
182591354Sdd/*
182690748Sjulian * small routine to swap a thread's current ucred for the correct one
182790748Sjulian * taken from the process.
182890748Sjulian */
182990748Sjulianvoid
183090748Sjuliancred_update_thread(struct thread *td)
183190748Sjulian{
183290748Sjulian	struct proc *p;
183391405Sjhb	struct ucred *cred;
183490748Sjulian
183590748Sjulian	p = td->td_proc;
183691405Sjhb	cred = td->td_ucred;
183791405Sjhb	mtx_lock(&Giant);
183890748Sjulian	PROC_LOCK(p);
183990748Sjulian	td->td_ucred = crhold(p->p_ucred);
184090748Sjulian	PROC_UNLOCK(p);
184191405Sjhb	if (cred != NULL)
184291405Sjhb		crfree(cred);
184391405Sjhb	mtx_unlock(&Giant);
184490748Sjulian}
184590748Sjulian
184690748Sjulian/*
18471541Srgrimes * Get login name, if available.
18481541Srgrimes */
184912221Sbde#ifndef _SYS_SYSPROTO_H_
18501541Srgrimesstruct getlogin_args {
18511541Srgrimes	char	*namebuf;
18521541Srgrimes	u_int	namelen;
18531541Srgrimes};
185412221Sbde#endif
185582749Sdillon/*
185682749Sdillon * MPSAFE
185782749Sdillon */
18581541Srgrimes/* ARGSUSED */
18591549Srgrimesint
186083366Sjuliangetlogin(td, uap)
186183366Sjulian	struct thread *td;
18621541Srgrimes	struct getlogin_args *uap;
18631541Srgrimes{
186482749Sdillon	int error;
186591140Stanimura	char login[MAXLOGNAME];
186683366Sjulian	struct proc *p = td->td_proc;
18671541Srgrimes
186882749Sdillon	mtx_lock(&Giant);
186923358Sache	if (uap->namelen > MAXLOGNAME)
187023359Sache		uap->namelen = MAXLOGNAME;
187191140Stanimura	PROC_LOCK(p);
187291140Stanimura	SESS_LOCK(p->p_session);
187391140Stanimura	bcopy(p->p_session->s_login, login, uap->namelen);
187491140Stanimura	SESS_UNLOCK(p->p_session);
187591140Stanimura	PROC_UNLOCK(p);
187691140Stanimura	error = copyout((caddr_t) login, (caddr_t) uap->namebuf, uap->namelen);
187782749Sdillon	mtx_unlock(&Giant);
187882749Sdillon	return(error);
18791541Srgrimes}
18801541Srgrimes
18811541Srgrimes/*
18821541Srgrimes * Set login name.
18831541Srgrimes */
188412221Sbde#ifndef _SYS_SYSPROTO_H_
18851541Srgrimesstruct setlogin_args {
18861541Srgrimes	char	*namebuf;
18871541Srgrimes};
188812221Sbde#endif
188982749Sdillon/*
189082749Sdillon * MPSAFE
189182749Sdillon */
18921541Srgrimes/* ARGSUSED */
18931549Srgrimesint
189483366Sjuliansetlogin(td, uap)
189583366Sjulian	struct thread *td;
18961541Srgrimes	struct setlogin_args *uap;
18971541Srgrimes{
189883366Sjulian	struct proc *p = td->td_proc;
18991541Srgrimes	int error;
190023330Sache	char logintmp[MAXLOGNAME];
19011541Srgrimes
190282749Sdillon	mtx_lock(&Giant);
190387218Srwatson	if ((error = suser_xxx(0, p, PRISON_ROOT)) != 0)
190482749Sdillon		goto done2;
190522522Sdavidn	error = copyinstr((caddr_t) uap->namebuf, (caddr_t) logintmp,
190636845Sdfr	    sizeof(logintmp), (size_t *)0);
190787218Srwatson	if (error == ENAMETOOLONG)
19081541Srgrimes		error = EINVAL;
190991140Stanimura	else if (!error) {
191091140Stanimura		PROC_LOCK(p);
191191140Stanimura		SESS_LOCK(p->p_session);
191291140Stanimura		(void) memcpy(p->p_session->s_login, logintmp,
191323330Sache		    sizeof(logintmp));
191491140Stanimura		SESS_UNLOCK(p->p_session);
191591140Stanimura		PROC_UNLOCK(p);
191691140Stanimura	}
191782749Sdillondone2:
191882749Sdillon	mtx_unlock(&Giant);
19191541Srgrimes	return (error);
19201541Srgrimes}
192131891Ssef
192231891Ssefvoid
192331891Ssefsetsugid(p)
192455338Sphk	struct proc *p;
192531891Ssef{
192631891Ssef	p->p_flag |= P_SUGID;
192755707Ssef	if (!(p->p_pfsflags & PF_ISUGID))
192831891Ssef		p->p_stops = 0;
192931891Ssef}
193065495Struckman
193182466Srwatson/*-
193282466Srwatson * Change a process's effective uid.
193377183Srwatson * Side effects: newcred->cr_uid and newcred->cr_uidinfo will be modified.
193477183Srwatson * References: newcred must be an exclusive credential reference for the
193577183Srwatson *             duration of the call.
193665495Struckman */
193765495Struckmanvoid
193877183Srwatsonchange_euid(newcred, euid)
193977183Srwatson	struct ucred *newcred;
194077183Srwatson	uid_t euid;
194165495Struckman{
194265495Struckman
194377183Srwatson	newcred->cr_uid = euid;
194477183Srwatson	uifree(newcred->cr_uidinfo);
194577183Srwatson	newcred->cr_uidinfo = uifind(euid);
194665495Struckman}
194765495Struckman
194882466Srwatson/*-
194982466Srwatson * Change a process's effective gid.
195077183Srwatson * Side effects: newcred->cr_gid will be modified.
195177183Srwatson * References: newcred must be an exclusive credential reference for the
195277183Srwatson *             duration of the call.
195365495Struckman */
195467629Sgallatinvoid
195577183Srwatsonchange_egid(newcred, egid)
195677183Srwatson	struct ucred *newcred;
195777183Srwatson	gid_t egid;
195865495Struckman{
195965495Struckman
196077183Srwatson	newcred->cr_groups[0] = egid;
196165495Struckman}
196277183Srwatson
196382466Srwatson/*-
196482466Srwatson * Change a process's real uid.
196577183Srwatson * Side effects: newcred->cr_ruid will be updated, newcred->cr_ruidinfo
196677183Srwatson *               will be updated, and the old and new cr_ruidinfo proc
196777183Srwatson *               counts will be updated.
196877183Srwatson * References: newcred must be an exclusive credential reference for the
196977183Srwatson *             duration of the call.
197077183Srwatson */
197177183Srwatsonvoid
197277183Srwatsonchange_ruid(newcred, ruid)
197377183Srwatson	struct ucred *newcred;
197477183Srwatson	uid_t ruid;
197577183Srwatson{
197677183Srwatson
197777183Srwatson	(void)chgproccnt(newcred->cr_ruidinfo, -1, 0);
197877183Srwatson	newcred->cr_ruid = ruid;
197977183Srwatson	uifree(newcred->cr_ruidinfo);
198077183Srwatson	newcred->cr_ruidinfo = uifind(ruid);
198177183Srwatson	(void)chgproccnt(newcred->cr_ruidinfo, 1, 0);
198277183Srwatson}
198377183Srwatson
198482466Srwatson/*-
198582466Srwatson * Change a process's real gid.
198677183Srwatson * Side effects: newcred->cr_rgid will be updated.
198777183Srwatson * References: newcred must be an exclusive credential reference for the
198877183Srwatson *             duration of the call.
198977183Srwatson */
199077183Srwatsonvoid
199177183Srwatsonchange_rgid(newcred, rgid)
199277183Srwatson	struct ucred *newcred;
199377183Srwatson	gid_t rgid;
199477183Srwatson{
199577183Srwatson
199677183Srwatson	newcred->cr_rgid = rgid;
199777183Srwatson}
199877183Srwatson
199982466Srwatson/*-
200082466Srwatson * Change a process's saved uid.
200177183Srwatson * Side effects: newcred->cr_svuid will be updated.
200277183Srwatson * References: newcred must be an exclusive credential reference for the
200377183Srwatson *             duration of the call.
200477183Srwatson */
200577183Srwatsonvoid
200677183Srwatsonchange_svuid(newcred, svuid)
200777183Srwatson	struct ucred *newcred;
200877183Srwatson	uid_t svuid;
200977183Srwatson{
201077183Srwatson
201177183Srwatson	newcred->cr_svuid = svuid;
201277183Srwatson}
201377183Srwatson
201482466Srwatson/*-
201582466Srwatson * Change a process's saved gid.
201677183Srwatson * Side effects: newcred->cr_svgid will be updated.
201777183Srwatson * References: newcred must be an exclusive credential reference for the
201877183Srwatson *             duration of the call.
201977183Srwatson */
202077183Srwatsonvoid
202177183Srwatsonchange_svgid(newcred, svgid)
202277183Srwatson	struct ucred *newcred;
202377183Srwatson	gid_t svgid;
202477183Srwatson{
202577183Srwatson
202677183Srwatson	newcred->cr_svgid = svgid;
202777183Srwatson}
2028