kern_prot.c revision 75893
1127668Sbms/*
2127668Sbms * Copyright (c) 1982, 1986, 1989, 1990, 1991, 1993
3127668Sbms *	The Regents of the University of California.  All rights reserved.
4127668Sbms * (c) UNIX System Laboratories, Inc.
5127668Sbms * All or some portions of this file are derived from material licensed
6127668Sbms * to the University of California by American Telephone and Telegraph
7127668Sbms * Co. or Unix System Laboratories, Inc. and are reproduced herein with
8127668Sbms * the permission of UNIX System Laboratories, Inc.
9127668Sbms *
10127668Sbms * Redistribution and use in source and binary forms, with or without
11127668Sbms * modification, are permitted provided that the following conditions
12127668Sbms * are met:
13127668Sbms * 1. Redistributions of source code must retain the above copyright
14127668Sbms *    notice, this list of conditions and the following disclaimer.
15127668Sbms * 2. Redistributions in binary form must reproduce the above copyright
16127668Sbms *    notice, this list of conditions and the following disclaimer in the
17127668Sbms *    documentation and/or other materials provided with the distribution.
18127668Sbms * 3. All advertising materials mentioning features or use of this software
19127668Sbms *    must display the following acknowledgement:
20127668Sbms *	This product includes software developed by the University of
21127668Sbms *	California, Berkeley and its contributors.
22127668Sbms * 4. Neither the name of the University nor the names of its contributors
23127668Sbms *    may be used to endorse or promote products derived from this software
24127668Sbms *    without specific prior written permission.
25127668Sbms *
26127668Sbms * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27127668Sbms * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28127668Sbms * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29127668Sbms * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30127668Sbms * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31127668Sbms * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32214478Srpaulo * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33127668Sbms * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34127668Sbms * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35127668Sbms * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36127668Sbms * SUCH DAMAGE.
37127668Sbms *
38190207Srpaulo *	@(#)kern_prot.c	8.6 (Berkeley) 1/21/94
39190207Srpaulo * $FreeBSD: head/sys/kern/kern_prot.c 75893 2001-04-24 00:51:53Z jhb $
40190207Srpaulo */
41190207Srpaulo
42190207Srpaulo/*
43190207Srpaulo * System calls related to processes and protection
44127668Sbms */
45127668Sbms
46127668Sbms#include "opt_compat.h"
47127668Sbms#include "opt_global.h"
48127668Sbms
49127668Sbms#include <sys/param.h>
50127668Sbms#include <sys/acct.h>
51127668Sbms#include <sys/systm.h>
52127668Sbms#include <sys/sysproto.h>
53127668Sbms#include <sys/kernel.h>
54127668Sbms#include <sys/lock.h>
55127668Sbms#include <sys/proc.h>
56127668Sbms#include <sys/malloc.h>
57127668Sbms#include <sys/pioctl.h>
58127668Sbms#include <sys/resourcevar.h>
59127668Sbms#include <sys/sysctl.h>
60127668Sbms#include <sys/jail.h>
61127668Sbms
62127668Sbmsstatic MALLOC_DEFINE(M_CRED, "cred", "credentials");
63127668Sbms
64127668Sbms#ifndef _SYS_SYSPROTO_H_
65127668Sbmsstruct getpid_args {
66127668Sbms	int	dummy;
67127668Sbms};
68127668Sbms#endif
69127668Sbms
70127668Sbms/*
71127668Sbms * getpid - MP SAFE
72127668Sbms */
73127668Sbms
74127668Sbms/* ARGSUSED */
75127668Sbmsint
76127668Sbmsgetpid(p, uap)
77127668Sbms	struct proc *p;
78127668Sbms	struct getpid_args *uap;
79127668Sbms{
80127668Sbms
81127668Sbms	p->p_retval[0] = p->p_pid;
82127668Sbms#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
83127668Sbms	PROC_LOCK(p);
84127668Sbms	p->p_retval[1] = p->p_pptr->p_pid;
85127668Sbms	PROC_UNLOCK(p);
86127668Sbms#endif
87127668Sbms	return (0);
88}
89
90/*
91 * getppid - MP SAFE
92 */
93
94#ifndef _SYS_SYSPROTO_H_
95struct getppid_args {
96        int     dummy;
97};
98#endif
99/* ARGSUSED */
100int
101getppid(p, uap)
102	struct proc *p;
103	struct getppid_args *uap;
104{
105
106	PROC_LOCK(p);
107	p->p_retval[0] = p->p_pptr->p_pid;
108	PROC_UNLOCK(p);
109	return (0);
110}
111
112/*
113 * Get process group ID; note that POSIX getpgrp takes no parameter
114 *
115 * MP SAFE
116 */
117#ifndef _SYS_SYSPROTO_H_
118struct getpgrp_args {
119        int     dummy;
120};
121#endif
122
123int
124getpgrp(p, uap)
125	struct proc *p;
126	struct getpgrp_args *uap;
127{
128
129	p->p_retval[0] = p->p_pgrp->pg_id;
130	return (0);
131}
132
133/* Get an arbitary pid's process group id */
134#ifndef _SYS_SYSPROTO_H_
135struct getpgid_args {
136	pid_t	pid;
137};
138#endif
139
140int
141getpgid(p, uap)
142	struct proc *p;
143	struct getpgid_args *uap;
144{
145	struct proc *pt;
146	int error;
147
148	if (uap->pid == 0)
149		p->p_retval[0] = p->p_pgrp->pg_id;
150	else {
151		if ((pt = pfind(uap->pid)) == NULL)
152			return ESRCH;
153		if ((error = p_can(p, pt, P_CAN_SEE, NULL))) {
154			PROC_UNLOCK(pt);
155			return (error);
156		}
157		p->p_retval[0] = pt->p_pgrp->pg_id;
158		PROC_UNLOCK(pt);
159	}
160	return 0;
161}
162
163/*
164 * Get an arbitary pid's session id.
165 */
166#ifndef _SYS_SYSPROTO_H_
167struct getsid_args {
168	pid_t	pid;
169};
170#endif
171
172int
173getsid(p, uap)
174	struct proc *p;
175	struct getsid_args *uap;
176{
177	struct proc *pt;
178	int error;
179
180	if (uap->pid == 0)
181		p->p_retval[0] = p->p_session->s_sid;
182	else {
183		if ((pt = pfind(uap->pid)) == NULL)
184			return ESRCH;
185		if ((error = p_can(p, pt, P_CAN_SEE, NULL))) {
186			PROC_UNLOCK(pt);
187			return (error);
188		}
189		p->p_retval[0] = pt->p_session->s_sid;
190		PROC_UNLOCK(pt);
191	}
192	return 0;
193}
194
195
196/*
197 * getuid() - MP SAFE
198 */
199#ifndef _SYS_SYSPROTO_H_
200struct getuid_args {
201        int     dummy;
202};
203#endif
204
205/* ARGSUSED */
206int
207getuid(p, uap)
208	struct proc *p;
209	struct getuid_args *uap;
210{
211
212	p->p_retval[0] = p->p_cred->p_ruid;
213#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
214	p->p_retval[1] = p->p_ucred->cr_uid;
215#endif
216	return (0);
217}
218
219/*
220 * geteuid() - MP SAFE
221 */
222#ifndef _SYS_SYSPROTO_H_
223struct geteuid_args {
224        int     dummy;
225};
226#endif
227
228/* ARGSUSED */
229int
230geteuid(p, uap)
231	struct proc *p;
232	struct geteuid_args *uap;
233{
234
235	p->p_retval[0] = p->p_ucred->cr_uid;
236	return (0);
237}
238
239/*
240 * getgid() - MP SAFE
241 */
242#ifndef _SYS_SYSPROTO_H_
243struct getgid_args {
244        int     dummy;
245};
246#endif
247
248/* ARGSUSED */
249int
250getgid(p, uap)
251	struct proc *p;
252	struct getgid_args *uap;
253{
254
255	p->p_retval[0] = p->p_cred->p_rgid;
256#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
257	p->p_retval[1] = p->p_ucred->cr_groups[0];
258#endif
259	return (0);
260}
261
262/*
263 * Get effective group ID.  The "egid" is groups[0], and could be obtained
264 * via getgroups.  This syscall exists because it is somewhat painful to do
265 * correctly in a library function.
266 */
267#ifndef _SYS_SYSPROTO_H_
268struct getegid_args {
269        int     dummy;
270};
271#endif
272
273/* ARGSUSED */
274int
275getegid(p, uap)
276	struct proc *p;
277	struct getegid_args *uap;
278{
279
280	p->p_retval[0] = p->p_ucred->cr_groups[0];
281	return (0);
282}
283
284#ifndef _SYS_SYSPROTO_H_
285struct getgroups_args {
286	u_int	gidsetsize;
287	gid_t	*gidset;
288};
289#endif
290int
291getgroups(p, uap)
292	struct proc *p;
293	register struct	getgroups_args *uap;
294{
295	register struct pcred *pc = p->p_cred;
296	register u_int ngrp;
297	int error;
298
299	if ((ngrp = uap->gidsetsize) == 0) {
300		p->p_retval[0] = pc->pc_ucred->cr_ngroups;
301		return (0);
302	}
303	if (ngrp < pc->pc_ucred->cr_ngroups)
304		return (EINVAL);
305	ngrp = pc->pc_ucred->cr_ngroups;
306	if ((error = copyout((caddr_t)pc->pc_ucred->cr_groups,
307	    (caddr_t)uap->gidset, ngrp * sizeof(gid_t))))
308		return (error);
309	p->p_retval[0] = ngrp;
310	return (0);
311}
312
313#ifndef _SYS_SYSPROTO_H_
314struct setsid_args {
315        int     dummy;
316};
317#endif
318
319/* ARGSUSED */
320int
321setsid(p, uap)
322	register struct proc *p;
323	struct setsid_args *uap;
324{
325
326	if (p->p_pgid == p->p_pid || pgfind(p->p_pid)) {
327		return (EPERM);
328	} else {
329		(void)enterpgrp(p, p->p_pid, 1);
330		p->p_retval[0] = p->p_pid;
331		return (0);
332	}
333}
334
335/*
336 * set process group (setpgid/old setpgrp)
337 *
338 * caller does setpgid(targpid, targpgid)
339 *
340 * pid must be caller or child of caller (ESRCH)
341 * if a child
342 *	pid must be in same session (EPERM)
343 *	pid can't have done an exec (EACCES)
344 * if pgid != pid
345 * 	there must exist some pid in same session having pgid (EPERM)
346 * pid must not be session leader (EPERM)
347 */
348#ifndef _SYS_SYSPROTO_H_
349struct setpgid_args {
350	int	pid;	/* target process id */
351	int	pgid;	/* target pgrp id */
352};
353#endif
354/* ARGSUSED */
355int
356setpgid(curp, uap)
357	struct proc *curp;
358	register struct setpgid_args *uap;
359{
360	register struct proc *targp;		/* target process */
361	register struct pgrp *pgrp;		/* target pgrp */
362	int error;
363
364	if (uap->pgid < 0)
365		return (EINVAL);
366	if (uap->pid != 0 && uap->pid != curp->p_pid) {
367		if ((targp = pfind(uap->pid)) == NULL || !inferior(targp)) {
368			if (targp)
369				PROC_UNLOCK(targp);
370			return (ESRCH);
371		}
372		if ((error = p_can(curproc, targp, P_CAN_SEE, NULL))) {
373			PROC_UNLOCK(targp);
374			return (error);
375		}
376		if (targp->p_pgrp == NULL ||
377		    targp->p_session != curp->p_session) {
378			PROC_UNLOCK(targp);
379			return (EPERM);
380		}
381		if (targp->p_flag & P_EXEC) {
382			PROC_UNLOCK(targp);
383			return (EACCES);
384		}
385	} else {
386		targp = curp;
387		PROC_LOCK(curp);	/* XXX: not needed */
388	}
389	if (SESS_LEADER(targp)) {
390		PROC_UNLOCK(targp);
391		return (EPERM);
392	}
393	if (uap->pgid == 0)
394		uap->pgid = targp->p_pid;
395	else if (uap->pgid != targp->p_pid)
396		if ((pgrp = pgfind(uap->pgid)) == 0 ||
397	            pgrp->pg_session != curp->p_session) {
398			PROC_UNLOCK(targp);
399			return (EPERM);
400		}
401	/* XXX: We should probably hold the lock across enterpgrp. */
402	PROC_UNLOCK(targp);
403	return (enterpgrp(targp, uap->pgid, 0));
404}
405
406/*
407 * Use the clause in B.4.2.2 that allows setuid/setgid to be 4.2/4.3BSD
408 * compatible.  It says that setting the uid/gid to euid/egid is a special
409 * case of "appropriate privilege".  Once the rules are expanded out, this
410 * basically means that setuid(nnn) sets all three id's, in all permitted
411 * cases unless _POSIX_SAVED_IDS is enabled.  In that case, setuid(getuid())
412 * does not set the saved id - this is dangerous for traditional BSD
413 * programs.  For this reason, we *really* do not want to set
414 * _POSIX_SAVED_IDS and do not want to clear POSIX_APPENDIX_B_4_2_2.
415 */
416#define POSIX_APPENDIX_B_4_2_2
417
418#ifndef _SYS_SYSPROTO_H_
419struct setuid_args {
420	uid_t	uid;
421};
422#endif
423/* ARGSUSED */
424int
425setuid(p, uap)
426	struct proc *p;
427	struct setuid_args *uap;
428{
429	register struct pcred *pc = p->p_cred;
430	register uid_t uid;
431	int error;
432
433	/*
434	 * See if we have "permission" by POSIX 1003.1 rules.
435	 *
436	 * Note that setuid(geteuid()) is a special case of
437	 * "appropriate privileges" in appendix B.4.2.2.  We need
438	 * to use this clause to be compatible with traditional BSD
439	 * semantics.  Basically, it means that "setuid(xx)" sets all
440	 * three id's (assuming you have privs).
441	 *
442	 * Notes on the logic.  We do things in three steps.
443	 * 1: We determine if the euid is going to change, and do EPERM
444	 *    right away.  We unconditionally change the euid later if this
445	 *    test is satisfied, simplifying that part of the logic.
446	 * 2: We determine if the real and/or saved uid's are going to
447	 *    change.  Determined by compile options.
448	 * 3: Change euid last. (after tests in #2 for "appropriate privs")
449	 */
450	uid = uap->uid;
451	if (uid != pc->p_ruid &&		/* allow setuid(getuid()) */
452#ifdef _POSIX_SAVED_IDS
453	    uid != pc->p_svuid &&		/* allow setuid(saved gid) */
454#endif
455#ifdef POSIX_APPENDIX_B_4_2_2	/* Use BSD-compat clause from B.4.2.2 */
456	    uid != pc->pc_ucred->cr_uid &&	/* allow setuid(geteuid()) */
457#endif
458	    (error = suser_xxx(0, p, PRISON_ROOT)))
459		return (error);
460
461#ifdef _POSIX_SAVED_IDS
462	/*
463	 * Do we have "appropriate privileges" (are we root or uid == euid)
464	 * If so, we are changing the real uid and/or saved uid.
465	 */
466	if (
467#ifdef POSIX_APPENDIX_B_4_2_2	/* Use the clause from B.4.2.2 */
468	    uid == pc->pc_ucred->cr_uid ||
469#endif
470	    suser_xxx(0, p, PRISON_ROOT) == 0) /* we are using privs */
471#endif
472	{
473		/*
474		 * Set the real uid and transfer proc count to new user.
475		 */
476		if (uid != pc->p_ruid) {
477			change_ruid(p, uid);
478			setsugid(p);
479		}
480		/*
481		 * Set saved uid
482		 *
483		 * XXX always set saved uid even if not _POSIX_SAVED_IDS, as
484		 * the security of seteuid() depends on it.  B.4.2.2 says it
485		 * is important that we should do this.
486		 */
487		if (pc->p_svuid != uid) {
488			pc->p_svuid = uid;
489			setsugid(p);
490		}
491	}
492
493	/*
494	 * In all permitted cases, we are changing the euid.
495	 * Copy credentials so other references do not see our changes.
496	 */
497	if (pc->pc_ucred->cr_uid != uid) {
498		change_euid(p, uid);
499		setsugid(p);
500	}
501	return (0);
502}
503
504#ifndef _SYS_SYSPROTO_H_
505struct seteuid_args {
506	uid_t	euid;
507};
508#endif
509/* ARGSUSED */
510int
511seteuid(p, uap)
512	struct proc *p;
513	struct seteuid_args *uap;
514{
515	register struct pcred *pc = p->p_cred;
516	register uid_t euid;
517	int error;
518
519	euid = uap->euid;
520	if (euid != pc->p_ruid &&		/* allow seteuid(getuid()) */
521	    euid != pc->p_svuid &&		/* allow seteuid(saved uid) */
522	    (error = suser_xxx(0, p, PRISON_ROOT)))
523		return (error);
524	/*
525	 * Everything's okay, do it.  Copy credentials so other references do
526	 * not see our changes.
527	 */
528	if (pc->pc_ucred->cr_uid != euid) {
529		change_euid(p, euid);
530		setsugid(p);
531	}
532	return (0);
533}
534
535#ifndef _SYS_SYSPROTO_H_
536struct setgid_args {
537	gid_t	gid;
538};
539#endif
540/* ARGSUSED */
541int
542setgid(p, uap)
543	struct proc *p;
544	struct setgid_args *uap;
545{
546	register struct pcred *pc = p->p_cred;
547	register gid_t gid;
548	int error;
549
550	/*
551	 * See if we have "permission" by POSIX 1003.1 rules.
552	 *
553	 * Note that setgid(getegid()) is a special case of
554	 * "appropriate privileges" in appendix B.4.2.2.  We need
555	 * to use this clause to be compatible with traditional BSD
556	 * semantics.  Basically, it means that "setgid(xx)" sets all
557	 * three id's (assuming you have privs).
558	 *
559	 * For notes on the logic here, see setuid() above.
560	 */
561	gid = uap->gid;
562	if (gid != pc->p_rgid &&		/* allow setgid(getgid()) */
563#ifdef _POSIX_SAVED_IDS
564	    gid != pc->p_svgid &&		/* allow setgid(saved gid) */
565#endif
566#ifdef POSIX_APPENDIX_B_4_2_2	/* Use BSD-compat clause from B.4.2.2 */
567	    gid != pc->pc_ucred->cr_groups[0] && /* allow setgid(getegid()) */
568#endif
569	    (error = suser_xxx(0, p, PRISON_ROOT)))
570		return (error);
571
572#ifdef _POSIX_SAVED_IDS
573	/*
574	 * Do we have "appropriate privileges" (are we root or gid == egid)
575	 * If so, we are changing the real uid and saved gid.
576	 */
577	if (
578#ifdef POSIX_APPENDIX_B_4_2_2	/* use the clause from B.4.2.2 */
579	    gid == pc->pc_ucred->cr_groups[0] ||
580#endif
581	    suser_xxx(0, p, PRISON_ROOT) == 0) /* we are using privs */
582#endif
583	{
584		/*
585		 * Set real gid
586		 */
587		if (pc->p_rgid != gid) {
588			pc->p_rgid = gid;
589			setsugid(p);
590		}
591		/*
592		 * Set saved gid
593		 *
594		 * XXX always set saved gid even if not _POSIX_SAVED_IDS, as
595		 * the security of setegid() depends on it.  B.4.2.2 says it
596		 * is important that we should do this.
597		 */
598		if (pc->p_svgid != gid) {
599			pc->p_svgid = gid;
600			setsugid(p);
601		}
602	}
603	/*
604	 * In all cases permitted cases, we are changing the egid.
605	 * Copy credentials so other references do not see our changes.
606	 */
607	if (pc->pc_ucred->cr_groups[0] != gid) {
608		pc->pc_ucred = crcopy(pc->pc_ucred);
609		pc->pc_ucred->cr_groups[0] = gid;
610		setsugid(p);
611	}
612	return (0);
613}
614
615#ifndef _SYS_SYSPROTO_H_
616struct setegid_args {
617	gid_t	egid;
618};
619#endif
620/* ARGSUSED */
621int
622setegid(p, uap)
623	struct proc *p;
624	struct setegid_args *uap;
625{
626	register struct pcred *pc = p->p_cred;
627	register gid_t egid;
628	int error;
629
630	egid = uap->egid;
631	if (egid != pc->p_rgid &&		/* allow setegid(getgid()) */
632	    egid != pc->p_svgid &&		/* allow setegid(saved gid) */
633	    (error = suser_xxx(0, p, PRISON_ROOT)))
634		return (error);
635	if (pc->pc_ucred->cr_groups[0] != egid) {
636		pc->pc_ucred = crcopy(pc->pc_ucred);
637		pc->pc_ucred->cr_groups[0] = egid;
638		setsugid(p);
639	}
640	return (0);
641}
642
643#ifndef _SYS_SYSPROTO_H_
644struct setgroups_args {
645	u_int	gidsetsize;
646	gid_t	*gidset;
647};
648#endif
649/* ARGSUSED */
650int
651setgroups(p, uap)
652	struct proc *p;
653	struct setgroups_args *uap;
654{
655	register struct pcred *pc = p->p_cred;
656	register u_int ngrp;
657	int error;
658
659	if ((error = suser_xxx(0, p, PRISON_ROOT)))
660		return (error);
661	ngrp = uap->gidsetsize;
662	if (ngrp > NGROUPS)
663		return (EINVAL);
664	/*
665	 * XXX A little bit lazy here.  We could test if anything has
666	 * changed before crcopy() and setting P_SUGID.
667	 */
668	pc->pc_ucred = crcopy(pc->pc_ucred);
669	if (ngrp < 1) {
670		/*
671		 * setgroups(0, NULL) is a legitimate way of clearing the
672		 * groups vector on non-BSD systems (which generally do not
673		 * have the egid in the groups[0]).  We risk security holes
674		 * when running non-BSD software if we do not do the same.
675		 */
676		pc->pc_ucred->cr_ngroups = 1;
677	} else {
678		if ((error = copyin((caddr_t)uap->gidset,
679		    (caddr_t)pc->pc_ucred->cr_groups, ngrp * sizeof(gid_t))))
680			return (error);
681		pc->pc_ucred->cr_ngroups = ngrp;
682	}
683	setsugid(p);
684	return (0);
685}
686
687#ifndef _SYS_SYSPROTO_H_
688struct setreuid_args {
689	uid_t	ruid;
690	uid_t	euid;
691};
692#endif
693/* ARGSUSED */
694int
695setreuid(p, uap)
696	register struct proc *p;
697	struct setreuid_args *uap;
698{
699	register struct pcred *pc = p->p_cred;
700	register uid_t ruid, euid;
701	int error;
702
703	ruid = uap->ruid;
704	euid = uap->euid;
705	if (((ruid != (uid_t)-1 && ruid != pc->p_ruid && ruid != pc->p_svuid) ||
706	     (euid != (uid_t)-1 && euid != pc->pc_ucred->cr_uid &&
707	     euid != pc->p_ruid && euid != pc->p_svuid)) &&
708	    (error = suser_xxx(0, p, PRISON_ROOT)) != 0)
709		return (error);
710
711	if (euid != (uid_t)-1 && pc->pc_ucred->cr_uid != euid) {
712		change_euid(p, euid);
713		setsugid(p);
714	}
715	if (ruid != (uid_t)-1 && pc->p_ruid != ruid) {
716		change_ruid(p, ruid);
717		setsugid(p);
718	}
719	if ((ruid != (uid_t)-1 || pc->pc_ucred->cr_uid != pc->p_ruid) &&
720	    pc->p_svuid != pc->pc_ucred->cr_uid) {
721		pc->p_svuid = pc->pc_ucred->cr_uid;
722		setsugid(p);
723	}
724	return (0);
725}
726
727#ifndef _SYS_SYSPROTO_H_
728struct setregid_args {
729	gid_t	rgid;
730	gid_t	egid;
731};
732#endif
733/* ARGSUSED */
734int
735setregid(p, uap)
736	register struct proc *p;
737	struct setregid_args *uap;
738{
739	register struct pcred *pc = p->p_cred;
740	register gid_t rgid, egid;
741	int error;
742
743	rgid = uap->rgid;
744	egid = uap->egid;
745	if (((rgid != (gid_t)-1 && rgid != pc->p_rgid && rgid != pc->p_svgid) ||
746	     (egid != (gid_t)-1 && egid != pc->pc_ucred->cr_groups[0] &&
747	     egid != pc->p_rgid && egid != pc->p_svgid)) &&
748	    (error = suser_xxx(0, p, PRISON_ROOT)) != 0)
749		return (error);
750
751	if (egid != (gid_t)-1 && pc->pc_ucred->cr_groups[0] != egid) {
752		pc->pc_ucred = crcopy(pc->pc_ucred);
753		pc->pc_ucred->cr_groups[0] = egid;
754		setsugid(p);
755	}
756	if (rgid != (gid_t)-1 && pc->p_rgid != rgid) {
757		pc->p_rgid = rgid;
758		setsugid(p);
759	}
760	if ((rgid != (gid_t)-1 || pc->pc_ucred->cr_groups[0] != pc->p_rgid) &&
761	    pc->p_svgid != pc->pc_ucred->cr_groups[0]) {
762		pc->p_svgid = pc->pc_ucred->cr_groups[0];
763		setsugid(p);
764	}
765	return (0);
766}
767
768/*
769 * setresuid(ruid, euid, suid) is like setreuid except control over the
770 * saved uid is explicit.
771 */
772
773#ifndef _SYS_SYSPROTO_H_
774struct setresuid_args {
775	uid_t	ruid;
776	uid_t	euid;
777	uid_t	suid;
778};
779#endif
780/* ARGSUSED */
781int
782setresuid(p, uap)
783	register struct proc *p;
784	struct setresuid_args *uap;
785{
786	register struct pcred *pc = p->p_cred;
787	register uid_t ruid, euid, suid;
788	int error;
789
790	ruid = uap->ruid;
791	euid = uap->euid;
792	suid = uap->suid;
793	if (((ruid != (uid_t)-1 && ruid != pc->p_ruid && ruid != pc->p_svuid &&
794	      ruid != pc->pc_ucred->cr_uid) ||
795	     (euid != (uid_t)-1 && euid != pc->p_ruid && euid != pc->p_svuid &&
796	      euid != pc->pc_ucred->cr_uid) ||
797	     (suid != (uid_t)-1 && suid != pc->p_ruid && suid != pc->p_svuid &&
798	      suid != pc->pc_ucred->cr_uid)) &&
799	    (error = suser_xxx(0, p, PRISON_ROOT)) != 0)
800		return (error);
801	if (euid != (uid_t)-1 && pc->pc_ucred->cr_uid != euid) {
802		change_euid(p, euid);
803		setsugid(p);
804	}
805	if (ruid != (uid_t)-1 && pc->p_ruid != ruid) {
806		change_ruid(p, ruid);
807		setsugid(p);
808	}
809	if (suid != (uid_t)-1 && pc->p_svuid != suid) {
810		pc->p_svuid = suid;
811		setsugid(p);
812	}
813	return (0);
814}
815
816/*
817 * setresgid(rgid, egid, sgid) is like setregid except control over the
818 * saved gid is explicit.
819 */
820
821#ifndef _SYS_SYSPROTO_H_
822struct setresgid_args {
823	gid_t	rgid;
824	gid_t	egid;
825	gid_t	sgid;
826};
827#endif
828/* ARGSUSED */
829int
830setresgid(p, uap)
831	register struct proc *p;
832	struct setresgid_args *uap;
833{
834	register struct pcred *pc = p->p_cred;
835	register gid_t rgid, egid, sgid;
836	int error;
837
838	rgid = uap->rgid;
839	egid = uap->egid;
840	sgid = uap->sgid;
841	if (((rgid != (gid_t)-1 && rgid != pc->p_rgid && rgid != pc->p_svgid &&
842	      rgid != pc->pc_ucred->cr_groups[0]) ||
843	     (egid != (gid_t)-1 && egid != pc->p_rgid && egid != pc->p_svgid &&
844	      egid != pc->pc_ucred->cr_groups[0]) ||
845	     (sgid != (gid_t)-1 && sgid != pc->p_rgid && sgid != pc->p_svgid &&
846	      sgid != pc->pc_ucred->cr_groups[0])) &&
847	    (error = suser_xxx(0, p, PRISON_ROOT)) != 0)
848		return (error);
849
850	if (egid != (gid_t)-1 && pc->pc_ucred->cr_groups[0] != egid) {
851		pc->pc_ucred = crcopy(pc->pc_ucred);
852		pc->pc_ucred->cr_groups[0] = egid;
853		setsugid(p);
854	}
855	if (rgid != (gid_t)-1 && pc->p_rgid != rgid) {
856		pc->p_rgid = rgid;
857		setsugid(p);
858	}
859	if (sgid != (gid_t)-1 && pc->p_svgid != sgid) {
860		pc->p_svgid = sgid;
861		setsugid(p);
862	}
863	return (0);
864}
865
866#ifndef _SYS_SYSPROTO_H_
867struct getresuid_args {
868	uid_t	*ruid;
869	uid_t	*euid;
870	uid_t	*suid;
871};
872#endif
873/* ARGSUSED */
874int
875getresuid(p, uap)
876	register struct proc *p;
877	struct getresuid_args *uap;
878{
879	struct pcred *pc = p->p_cred;
880	int error1 = 0, error2 = 0, error3 = 0;
881
882	if (uap->ruid)
883		error1 = copyout((caddr_t)&pc->p_ruid,
884		    (caddr_t)uap->ruid, sizeof(pc->p_ruid));
885	if (uap->euid)
886		error2 = copyout((caddr_t)&pc->pc_ucred->cr_uid,
887		    (caddr_t)uap->euid, sizeof(pc->pc_ucred->cr_uid));
888	if (uap->suid)
889		error3 = copyout((caddr_t)&pc->p_svuid,
890		    (caddr_t)uap->suid, sizeof(pc->p_svuid));
891	return error1 ? error1 : (error2 ? error2 : error3);
892}
893
894#ifndef _SYS_SYSPROTO_H_
895struct getresgid_args {
896	gid_t	*rgid;
897	gid_t	*egid;
898	gid_t	*sgid;
899};
900#endif
901/* ARGSUSED */
902int
903getresgid(p, uap)
904	register struct proc *p;
905	struct getresgid_args *uap;
906{
907	struct pcred *pc = p->p_cred;
908	int error1 = 0, error2 = 0, error3 = 0;
909
910	if (uap->rgid)
911		error1 = copyout((caddr_t)&pc->p_rgid,
912		    (caddr_t)uap->rgid, sizeof(pc->p_rgid));
913	if (uap->egid)
914		error2 = copyout((caddr_t)&pc->pc_ucred->cr_groups[0],
915		    (caddr_t)uap->egid, sizeof(pc->pc_ucred->cr_groups[0]));
916	if (uap->sgid)
917		error3 = copyout((caddr_t)&pc->p_svgid,
918		    (caddr_t)uap->sgid, sizeof(pc->p_svgid));
919	return error1 ? error1 : (error2 ? error2 : error3);
920}
921
922
923#ifndef _SYS_SYSPROTO_H_
924struct issetugid_args {
925	int dummy;
926};
927#endif
928/* ARGSUSED */
929int
930issetugid(p, uap)
931	register struct proc *p;
932	struct issetugid_args *uap;
933{
934	/*
935	 * Note: OpenBSD sets a P_SUGIDEXEC flag set at execve() time,
936	 * we use P_SUGID because we consider changing the owners as
937	 * "tainting" as well.
938	 * This is significant for procs that start as root and "become"
939	 * a user without an exec - programs cannot know *everything*
940	 * that libc *might* have put in their data segment.
941	 */
942	p->p_retval[0] = (p->p_flag & P_SUGID) ? 1 : 0;
943	return (0);
944}
945
946int
947__setugid(p, uap)
948	struct proc *p;
949	struct __setugid_args *uap;
950{
951
952#ifdef REGRESSION
953	switch (uap->flag) {
954	case 0:
955		p->p_flag &= ~P_SUGID;
956		return (0);
957	case 1:
958		p->p_flag |= P_SUGID;
959		return (0);
960	default:
961		return (EINVAL);
962	}
963#else /* !REGRESSION */
964	return (ENOSYS);
965#endif /* !REGRESSION */
966}
967
968/*
969 * Check if gid is a member of the group set.
970 */
971int
972groupmember(gid, cred)
973	gid_t gid;
974	register struct ucred *cred;
975{
976	register gid_t *gp;
977	gid_t *egp;
978
979	egp = &(cred->cr_groups[cred->cr_ngroups]);
980	for (gp = cred->cr_groups; gp < egp; gp++)
981		if (*gp == gid)
982			return (1);
983	return (0);
984}
985
986static int suser_permitted = 1;
987
988SYSCTL_INT(_kern, OID_AUTO, suser_permitted, CTLFLAG_RW, &suser_permitted, 0,
989    "processes with uid 0 have privilege");
990
991/*
992 * Test whether the specified credentials imply "super-user"
993 * privilege; if so, and we have accounting info, set the flag
994 * indicating use of super-powers.
995 * Returns 0 or error.
996 */
997int
998suser(p)
999	struct proc *p;
1000{
1001	return suser_xxx(0, p, 0);
1002}
1003
1004int
1005suser_xxx(cred, proc, flag)
1006	struct ucred *cred;
1007	struct proc *proc;
1008	int flag;
1009{
1010	if (!suser_permitted)
1011		return (EPERM);
1012	if (!cred && !proc) {
1013		printf("suser_xxx(): THINK!\n");
1014		return (EPERM);
1015	}
1016	if (!cred)
1017		cred = proc->p_ucred;
1018	if (cred->cr_uid != 0)
1019		return (EPERM);
1020	if (jailed(cred) && !(flag & PRISON_ROOT))
1021		return (EPERM);
1022	return (0);
1023}
1024
1025/*
1026 * u_cansee(u1, u2): determine if u1 "can see" the subject specified by u2
1027 * Arguments: imutable credentials u1, u2
1028 * Returns: 0 for permitted, an errno value otherwise
1029 * Locks: none
1030 * References: u1 and u2 must be valid for the lifetime of the call
1031 *             u1 may equal u2, in which case only one reference is required
1032 */
1033int
1034u_cansee(struct ucred *u1, struct ucred *u2)
1035{
1036	int error;
1037
1038	if ((error = prison_check(u1, u2)))
1039		return (error);
1040	if (!ps_showallprocs && u1->cr_uid != u2->cr_uid) {
1041		if (suser_xxx(u1, NULL, PRISON_ROOT) != 0)
1042			return (ESRCH);
1043	}
1044	return (0);
1045}
1046
1047static int
1048p_cansee(struct proc *p1, struct proc *p2, int *privused)
1049{
1050
1051	/* XXX: privused is going away, so don't do that here. */
1052	if (privused != NULL)
1053		*privused = 0;
1054	/* Wrap u_cansee() for all functionality. */
1055	return (u_cansee(p1->p_ucred, p2->p_ucred));
1056}
1057
1058/*
1059 * Can process p1 send the signal signum to process p2?
1060 */
1061int
1062p_cansignal(struct proc *p1, struct proc *p2, int signum)
1063{
1064	int	error;
1065
1066	if (p1 == p2)
1067		return (0);
1068
1069	/*
1070	 * Jail semantics limit the scope of signalling to p2 in the same
1071	 * jail as p1, if p1 is in jail.
1072	 */
1073	if ((error = prison_check(p1->p_ucred, p2->p_ucred)))
1074		return (error);
1075
1076	/*
1077	 * UNIX signalling semantics require that processes in the same
1078	 * session always be able to deliver SIGCONT to one another,
1079	 * overriding the remaining protections.
1080	 */
1081	if (signum == SIGCONT && p1->p_session == p2->p_session)
1082		return (0);
1083
1084	/*
1085	 * UNIX uid semantics depend on the status of the P_SUGID
1086	 * bit on the target process.  If the bit is set, then more
1087	 * restricted signal sets are permitted.
1088	 */
1089	if (p2->p_flag & P_SUGID) {
1090		switch (signum) {
1091		case 0:
1092		case SIGKILL:
1093		case SIGINT:
1094		case SIGTERM:
1095		case SIGSTOP:
1096		case SIGTTIN:
1097		case SIGTTOU:
1098		case SIGTSTP:
1099		case SIGHUP:
1100		case SIGUSR1:
1101		case SIGUSR2:
1102			break;
1103		default:
1104			/* Not permitted, try privilege. */
1105			error = suser_xxx(NULL, p1, PRISON_ROOT);
1106			if (error)
1107				return (error);
1108		}
1109	}
1110
1111	/*
1112	 * Generally, the object credential's ruid or svuid must match the
1113	 * subject credential's ruid or euid.
1114	 */
1115	if (p1->p_cred->p_ruid != p2->p_cred->p_ruid &&
1116	    p1->p_cred->p_ruid != p2->p_cred->p_svuid &&
1117	    p1->p_ucred->cr_uid != p2->p_cred->p_ruid &&
1118	    p1->p_ucred->cr_uid != p2->p_cred->p_svuid) {
1119		/* Not permitted, try privilege. */
1120		error = suser_xxx(NULL, p1, PRISON_ROOT);
1121		if (error)
1122			return (error);
1123	}
1124
1125        return (0);
1126}
1127
1128static int
1129p_cansched(struct proc *p1, struct proc *p2, int *privused)
1130{
1131	int error;
1132
1133	if (privused != NULL)
1134		*privused = 0;
1135
1136	if (p1 == p2)
1137		return (0);
1138
1139	if ((error = prison_check(p1->p_ucred, p2->p_ucred)))
1140		return (error);
1141
1142	if (p1->p_cred->p_ruid == p2->p_cred->p_ruid)
1143		return (0);
1144	if (p1->p_ucred->cr_uid == p2->p_cred->p_ruid)
1145		return (0);
1146#if 0
1147	/*
1148	 * XXX should a process be able to affect another process
1149	 * acting as the same uid (i.e., sendmail delivery, lpd,
1150	 * et al?)
1151	 */
1152	if (p1->p_cred->p_ruid == p2->p_ucred->cr_uid)
1153		return (0);
1154	if (p1->p_ucred->cr_uid == p2->p_ucred->cr_uid)
1155		return (0);
1156#endif /* 0 */
1157
1158	if (!suser_xxx(0, p1, PRISON_ROOT)) {
1159		if (privused != NULL)
1160			*privused = 1;
1161		return (0);
1162	}
1163
1164#ifdef CAPABILITIES
1165	if (!cap_check_xxx(0, p1, CAP_SYS_NICE, PRISON_ROOT)) {
1166		if (privused != NULL)
1167			*privused = 1;
1168		return (0);
1169	}
1170#endif
1171
1172	return (EPERM);
1173}
1174
1175static int
1176p_candebug(struct proc *p1, struct proc *p2, int *privused)
1177{
1178	int error;
1179
1180	if (privused != NULL)
1181		*privused = 0;
1182
1183	if (p1 == p2)
1184		return (0);
1185
1186	if ((error = prison_check(p1->p_ucred, p2->p_ucred)))
1187		return (error);
1188
1189	/* not owned by you, has done setuid (unless you're root) */
1190	/* add a CAP_SYS_PTRACE here? */
1191	if (p1->p_cred->pc_ucred->cr_uid != p2->p_cred->p_ruid ||
1192	    p1->p_cred->p_ruid != p2->p_cred->p_ruid ||
1193	    p1->p_cred->p_svuid != p2->p_cred->p_ruid ||
1194	    p2->p_flag & P_SUGID) {
1195		if ((error = suser_xxx(0, p1, PRISON_ROOT)))
1196			return (error);
1197		if (privused != NULL)
1198			*privused = 1;
1199	}
1200
1201	/* can't trace init when securelevel > 0 */
1202	if (securelevel > 0 && p2->p_pid == 1)
1203		return (EPERM);
1204
1205	return (0);
1206}
1207
1208int
1209p_can(struct proc *p1, struct proc *p2, int operation,
1210    int *privused)
1211{
1212
1213	switch(operation) {
1214	case P_CAN_SEE:
1215		return (p_cansee(p1, p2, privused));
1216
1217	case P_CAN_SCHED:
1218		return (p_cansched(p1, p2, privused));
1219
1220	case P_CAN_DEBUG:
1221		return (p_candebug(p1, p2, privused));
1222
1223	default:
1224		panic("p_can: invalid operation");
1225	}
1226}
1227
1228
1229/*
1230 * Allocate a zeroed cred structure.
1231 */
1232struct ucred *
1233crget()
1234{
1235	register struct ucred *cr;
1236
1237	MALLOC(cr, struct ucred *, sizeof(*cr), M_CRED, M_WAITOK|M_ZERO);
1238	cr->cr_ref = 1;
1239	mtx_init(&cr->cr_mtx, "ucred", MTX_DEF);
1240	return (cr);
1241}
1242
1243/*
1244 * Claim another reference to a ucred structure
1245 */
1246void
1247crhold(cr)
1248	struct ucred *cr;
1249{
1250
1251	mtx_lock(&cr->cr_mtx);
1252	cr->cr_ref++;
1253	mtx_unlock(&(cr)->cr_mtx);
1254}
1255
1256
1257/*
1258 * Free a cred structure.
1259 * Throws away space when ref count gets to 0.
1260 */
1261void
1262crfree(cr)
1263	struct ucred *cr;
1264{
1265
1266	mtx_lock(&cr->cr_mtx);
1267	KASSERT(cr->cr_ref > 0, ("bad ucred refcount: %d", cr->cr_ref));
1268	if (--cr->cr_ref == 0) {
1269		mtx_destroy(&cr->cr_mtx);
1270		/*
1271		 * Some callers of crget(), such as nfs_statfs(),
1272		 * allocate a temporary credential, but don't
1273		 * allocate a uidinfo structure.
1274		 */
1275		if (cr->cr_uidinfo != NULL)
1276			uifree(cr->cr_uidinfo);
1277		/*
1278		 * Free a prison, if any.
1279		 */
1280		if (jailed(cr))
1281			prison_free(cr->cr_prison);
1282		FREE((caddr_t)cr, M_CRED);
1283	} else {
1284		mtx_unlock(&cr->cr_mtx);
1285	}
1286}
1287
1288/*
1289 * Copy cred structure to a new one and free the old one.
1290 */
1291struct ucred *
1292crcopy(cr)
1293	struct ucred *cr;
1294{
1295	struct ucred *newcr;
1296
1297	mtx_lock(&cr->cr_mtx);
1298	if (cr->cr_ref == 1) {
1299		mtx_unlock(&cr->cr_mtx);
1300		return (cr);
1301	}
1302	mtx_unlock(&cr->cr_mtx);
1303	newcr = crdup(cr);
1304	crfree(cr);
1305	return (newcr);
1306}
1307
1308/*
1309 * Dup cred struct to a new held one.
1310 */
1311struct ucred *
1312crdup(cr)
1313	struct ucred *cr;
1314{
1315	struct ucred *newcr;
1316
1317	MALLOC(newcr, struct ucred *, sizeof(*cr), M_CRED, M_WAITOK);
1318	*newcr = *cr;
1319	mtx_init(&newcr->cr_mtx, "ucred", MTX_DEF);
1320	uihold(newcr->cr_uidinfo);
1321	if (jailed(newcr))
1322		prison_hold(newcr->cr_prison);
1323	newcr->cr_ref = 1;
1324	return (newcr);
1325}
1326
1327/*
1328 * Get login name, if available.
1329 */
1330#ifndef _SYS_SYSPROTO_H_
1331struct getlogin_args {
1332	char	*namebuf;
1333	u_int	namelen;
1334};
1335#endif
1336/* ARGSUSED */
1337int
1338getlogin(p, uap)
1339	struct proc *p;
1340	struct getlogin_args *uap;
1341{
1342
1343	if (uap->namelen > MAXLOGNAME)
1344		uap->namelen = MAXLOGNAME;
1345	return (copyout((caddr_t) p->p_pgrp->pg_session->s_login,
1346	    (caddr_t) uap->namebuf, uap->namelen));
1347}
1348
1349/*
1350 * Set login name.
1351 */
1352#ifndef _SYS_SYSPROTO_H_
1353struct setlogin_args {
1354	char	*namebuf;
1355};
1356#endif
1357/* ARGSUSED */
1358int
1359setlogin(p, uap)
1360	struct proc *p;
1361	struct setlogin_args *uap;
1362{
1363	int error;
1364	char logintmp[MAXLOGNAME];
1365
1366	if ((error = suser_xxx(0, p, PRISON_ROOT)))
1367		return (error);
1368	error = copyinstr((caddr_t) uap->namebuf, (caddr_t) logintmp,
1369	    sizeof(logintmp), (size_t *)0);
1370	if (error == ENAMETOOLONG)
1371		error = EINVAL;
1372	else if (!error)
1373		(void) memcpy(p->p_pgrp->pg_session->s_login, logintmp,
1374		    sizeof(logintmp));
1375	return (error);
1376}
1377
1378void
1379setsugid(p)
1380	struct proc *p;
1381{
1382	p->p_flag |= P_SUGID;
1383	if (!(p->p_pfsflags & PF_ISUGID))
1384		p->p_stops = 0;
1385}
1386
1387/*
1388 * Helper function to change the effective uid of a process
1389 */
1390void
1391change_euid(p, euid)
1392	struct	proc *p;
1393	uid_t	euid;
1394{
1395	struct	pcred *pc;
1396	struct	uidinfo *uip;
1397
1398	pc = p->p_cred;
1399	/*
1400	 * crcopy is essentially a NOP if ucred has a reference count
1401	 * of 1, which is true if it has already been copied.
1402	 */
1403	pc->pc_ucred = crcopy(pc->pc_ucred);
1404	uip = pc->pc_ucred->cr_uidinfo;
1405	pc->pc_ucred->cr_uid = euid;
1406	pc->pc_ucred->cr_uidinfo = uifind(euid);
1407	uifree(uip);
1408}
1409
1410/*
1411 * Helper function to change the real uid of a process
1412 *
1413 * The per-uid process count for this process is transfered from
1414 * the old uid to the new uid.
1415 */
1416void
1417change_ruid(p, ruid)
1418	struct	proc *p;
1419	uid_t	ruid;
1420{
1421	struct	pcred *pc;
1422	struct	uidinfo *uip;
1423
1424	pc = p->p_cred;
1425	(void)chgproccnt(pc->p_uidinfo, -1, 0);
1426	uip = pc->p_uidinfo;
1427	/* It is assumed that pcred is not shared between processes */
1428	pc->p_ruid = ruid;
1429	pc->p_uidinfo = uifind(ruid);
1430	(void)chgproccnt(pc->p_uidinfo, 1, 0);
1431	uifree(uip);
1432}
1433