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