xref: /freebsd/sys/kern/kern_prot.c (revision 23f282aa31e9b6fceacd449020e936e98d6f2298)
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$
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/proc.h>
54 #include <sys/malloc.h>
55 #include <sys/pioctl.h>
56 
57 static MALLOC_DEFINE(M_CRED, "cred", "credentials");
58 
59 #ifndef _SYS_SYSPROTO_H_
60 struct getpid_args {
61 	int	dummy;
62 };
63 #endif
64 
65 /*
66  * NOT MP SAFE due to p_pptr access
67  */
68 /* ARGSUSED */
69 int
70 getpid(p, uap)
71 	struct proc *p;
72 	struct getpid_args *uap;
73 {
74 
75 	p->p_retval[0] = p->p_pid;
76 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
77 	p->p_retval[1] = p->p_pptr->p_pid;
78 #endif
79 	return (0);
80 }
81 
82 #ifndef _SYS_SYSPROTO_H_
83 struct getppid_args {
84         int     dummy;
85 };
86 #endif
87 /* ARGSUSED */
88 int
89 getppid(p, uap)
90 	struct proc *p;
91 	struct getppid_args *uap;
92 {
93 
94 	p->p_retval[0] = p->p_pptr->p_pid;
95 	return (0);
96 }
97 
98 /*
99  * Get process group ID; note that POSIX getpgrp takes no parameter
100  *
101  * MP SAFE
102  */
103 #ifndef _SYS_SYSPROTO_H_
104 struct getpgrp_args {
105         int     dummy;
106 };
107 #endif
108 
109 int
110 getpgrp(p, uap)
111 	struct proc *p;
112 	struct getpgrp_args *uap;
113 {
114 
115 	p->p_retval[0] = p->p_pgrp->pg_id;
116 	return (0);
117 }
118 
119 /* Get an arbitary pid's process group id */
120 #ifndef _SYS_SYSPROTO_H_
121 struct getpgid_args {
122 	pid_t	pid;
123 };
124 #endif
125 
126 int
127 getpgid(p, uap)
128 	struct proc *p;
129 	struct getpgid_args *uap;
130 {
131 	struct proc *pt;
132 
133 	pt = p;
134 	if (uap->pid == 0)
135 		goto found;
136 
137 	if ((pt = pfind(uap->pid)) == 0)
138 		return ESRCH;
139 found:
140 	p->p_retval[0] = pt->p_pgrp->pg_id;
141 	return 0;
142 }
143 
144 /*
145  * Get an arbitary pid's session id.
146  */
147 #ifndef _SYS_SYSPROTO_H_
148 struct getsid_args {
149 	pid_t	pid;
150 };
151 #endif
152 
153 int
154 getsid(p, uap)
155 	struct proc *p;
156 	struct getsid_args *uap;
157 {
158 	struct proc *pt;
159 
160 	pt = p;
161 	if (uap->pid == 0)
162 		goto found;
163 
164 	if ((pt == pfind(uap->pid)) == 0)
165 		return ESRCH;
166 found:
167 	p->p_retval[0] = pt->p_session->s_sid;
168 	return 0;
169 }
170 
171 
172 /*
173  * getuid() - MP SAFE
174  */
175 #ifndef _SYS_SYSPROTO_H_
176 struct getuid_args {
177         int     dummy;
178 };
179 #endif
180 
181 /* ARGSUSED */
182 int
183 getuid(p, uap)
184 	struct proc *p;
185 	struct getuid_args *uap;
186 {
187 
188 	p->p_retval[0] = p->p_cred->p_ruid;
189 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
190 	p->p_retval[1] = p->p_ucred->cr_uid;
191 #endif
192 	return (0);
193 }
194 
195 /*
196  * geteuid() - MP SAFE
197  */
198 #ifndef _SYS_SYSPROTO_H_
199 struct geteuid_args {
200         int     dummy;
201 };
202 #endif
203 
204 /* ARGSUSED */
205 int
206 geteuid(p, uap)
207 	struct proc *p;
208 	struct geteuid_args *uap;
209 {
210 
211 	p->p_retval[0] = p->p_ucred->cr_uid;
212 	return (0);
213 }
214 
215 /*
216  * getgid() - MP SAFE
217  */
218 #ifndef _SYS_SYSPROTO_H_
219 struct getgid_args {
220         int     dummy;
221 };
222 #endif
223 
224 /* ARGSUSED */
225 int
226 getgid(p, uap)
227 	struct proc *p;
228 	struct getgid_args *uap;
229 {
230 
231 	p->p_retval[0] = p->p_cred->p_rgid;
232 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
233 	p->p_retval[1] = p->p_ucred->cr_groups[0];
234 #endif
235 	return (0);
236 }
237 
238 /*
239  * Get effective group ID.  The "egid" is groups[0], and could be obtained
240  * via getgroups.  This syscall exists because it is somewhat painful to do
241  * correctly in a library function.
242  */
243 #ifndef _SYS_SYSPROTO_H_
244 struct getegid_args {
245         int     dummy;
246 };
247 #endif
248 
249 /* ARGSUSED */
250 int
251 getegid(p, uap)
252 	struct proc *p;
253 	struct getegid_args *uap;
254 {
255 
256 	p->p_retval[0] = p->p_ucred->cr_groups[0];
257 	return (0);
258 }
259 
260 #ifndef _SYS_SYSPROTO_H_
261 struct getgroups_args {
262 	u_int	gidsetsize;
263 	gid_t	*gidset;
264 };
265 #endif
266 int
267 getgroups(p, uap)
268 	struct proc *p;
269 	register struct	getgroups_args *uap;
270 {
271 	register struct pcred *pc = p->p_cred;
272 	register u_int ngrp;
273 	int error;
274 
275 	if ((ngrp = uap->gidsetsize) == 0) {
276 		p->p_retval[0] = pc->pc_ucred->cr_ngroups;
277 		return (0);
278 	}
279 	if (ngrp < pc->pc_ucred->cr_ngroups)
280 		return (EINVAL);
281 	ngrp = pc->pc_ucred->cr_ngroups;
282 	if ((error = copyout((caddr_t)pc->pc_ucred->cr_groups,
283 	    (caddr_t)uap->gidset, ngrp * sizeof(gid_t))))
284 		return (error);
285 	p->p_retval[0] = ngrp;
286 	return (0);
287 }
288 
289 #ifndef _SYS_SYSPROTO_H_
290 struct setsid_args {
291         int     dummy;
292 };
293 #endif
294 
295 /* ARGSUSED */
296 int
297 setsid(p, uap)
298 	register struct proc *p;
299 	struct setsid_args *uap;
300 {
301 
302 	if (p->p_pgid == p->p_pid || pgfind(p->p_pid)) {
303 		return (EPERM);
304 	} else {
305 		(void)enterpgrp(p, p->p_pid, 1);
306 		p->p_retval[0] = p->p_pid;
307 		return (0);
308 	}
309 }
310 
311 /*
312  * set process group (setpgid/old setpgrp)
313  *
314  * caller does setpgid(targpid, targpgid)
315  *
316  * pid must be caller or child of caller (ESRCH)
317  * if a child
318  *	pid must be in same session (EPERM)
319  *	pid can't have done an exec (EACCES)
320  * if pgid != pid
321  * 	there must exist some pid in same session having pgid (EPERM)
322  * pid must not be session leader (EPERM)
323  */
324 #ifndef _SYS_SYSPROTO_H_
325 struct setpgid_args {
326 	int	pid;	/* target process id */
327 	int	pgid;	/* target pgrp id */
328 };
329 #endif
330 /* ARGSUSED */
331 int
332 setpgid(curp, uap)
333 	struct proc *curp;
334 	register struct setpgid_args *uap;
335 {
336 	register struct proc *targp;		/* target process */
337 	register struct pgrp *pgrp;		/* target pgrp */
338 
339 	if (uap->pgid < 0)
340 		return (EINVAL);
341 	if (uap->pid != 0 && uap->pid != curp->p_pid) {
342 		if ((targp = pfind(uap->pid)) == 0 || !inferior(targp))
343 			return (ESRCH);
344 		if (targp->p_pgrp == NULL ||  targp->p_session != curp->p_session)
345 			return (EPERM);
346 		if (targp->p_flag & P_EXEC)
347 			return (EACCES);
348 	} else
349 		targp = curp;
350 	if (SESS_LEADER(targp))
351 		return (EPERM);
352 	if (uap->pgid == 0)
353 		uap->pgid = targp->p_pid;
354 	else if (uap->pgid != targp->p_pid)
355 		if ((pgrp = pgfind(uap->pgid)) == 0 ||
356 	            pgrp->pg_session != curp->p_session)
357 			return (EPERM);
358 	return (enterpgrp(targp, uap->pgid, 0));
359 }
360 
361 /*
362  * Use the clause in B.4.2.2 that allows setuid/setgid to be 4.2/4.3BSD
363  * compatable.  It says that setting the uid/gid to euid/egid is a special
364  * case of "appropriate privilege".  Once the rules are expanded out, this
365  * basically means that setuid(nnn) sets all three id's, in all permitted
366  * cases unless _POSIX_SAVED_IDS is enabled.  In that case, setuid(getuid())
367  * does not set the saved id - this is dangerous for traditional BSD
368  * programs.  For this reason, we *really* do not want to set
369  * _POSIX_SAVED_IDS and do not want to clear POSIX_APPENDIX_B_4_2_2.
370  */
371 #define POSIX_APPENDIX_B_4_2_2
372 
373 #ifndef _SYS_SYSPROTO_H_
374 struct setuid_args {
375 	uid_t	uid;
376 };
377 #endif
378 /* ARGSUSED */
379 int
380 setuid(p, uap)
381 	struct proc *p;
382 	struct setuid_args *uap;
383 {
384 	register struct pcred *pc = p->p_cred;
385 	register uid_t uid;
386 	int error;
387 
388 	/*
389 	 * See if we have "permission" by POSIX 1003.1 rules.
390 	 *
391 	 * Note that setuid(geteuid()) is a special case of
392 	 * "appropriate privileges" in appendix B.4.2.2.  We need
393 	 * to use this clause to be compatable with traditional BSD
394 	 * semantics.  Basically, it means that "setuid(xx)" sets all
395 	 * three id's (assuming you have privs).
396 	 *
397 	 * Notes on the logic.  We do things in three steps.
398 	 * 1: We determine if the euid is going to change, and do EPERM
399 	 *    right away.  We unconditionally change the euid later if this
400 	 *    test is satisfied, simplifying that part of the logic.
401 	 * 2: We determine if the real and/or saved uid's are going to
402 	 *    change.  Determined by compile options.
403 	 * 3: Change euid last. (after tests in #2 for "appropriate privs")
404 	 */
405 	uid = uap->uid;
406 	if (uid != pc->p_ruid &&		/* allow setuid(getuid()) */
407 #ifdef _POSIX_SAVED_IDS
408 	    uid != pc->p_svuid &&		/* allow setuid(saved gid) */
409 #endif
410 #ifdef POSIX_APPENDIX_B_4_2_2	/* Use BSD-compat clause from B.4.2.2 */
411 	    uid != pc->pc_ucred->cr_uid &&	/* allow setuid(geteuid()) */
412 #endif
413 	    (error = suser_xxx(0, p, PRISON_ROOT)))
414 		return (error);
415 
416 #ifdef _POSIX_SAVED_IDS
417 	/*
418 	 * Do we have "appropriate privileges" (are we root or uid == euid)
419 	 * If so, we are changing the real uid and/or saved uid.
420 	 */
421 	if (
422 #ifdef POSIX_APPENDIX_B_4_2_2	/* Use the clause from B.4.2.2 */
423 	    uid == pc->pc_ucred->cr_uid ||
424 #endif
425 	    suser_xxx(0, p, PRISON_ROOT) == 0) /* we are using privs */
426 #endif
427 	{
428 		/*
429 		 * Transfer proc count to new user.
430 		 */
431 		if (uid != pc->p_ruid) {
432 			(void)chgproccnt(pc->p_ruid, -1);
433 			(void)chgproccnt(uid, 1);
434 		}
435 		/*
436 		 * Set real uid
437 		 */
438 		if (uid != pc->p_ruid) {
439 			pc->p_ruid = uid;
440 			setsugid(p);
441 		}
442 		/*
443 		 * Set saved uid
444 		 *
445 		 * XXX always set saved uid even if not _POSIX_SAVED_IDS, as
446 		 * the security of seteuid() depends on it.  B.4.2.2 says it
447 		 * is important that we should do this.
448 		 */
449 		if (pc->p_svuid != uid) {
450 			pc->p_svuid = uid;
451 			setsugid(p);
452 		}
453 	}
454 
455 	/*
456 	 * In all permitted cases, we are changing the euid.
457 	 * Copy credentials so other references do not see our changes.
458 	 */
459 	if (pc->pc_ucred->cr_uid != uid) {
460 		pc->pc_ucred = crcopy(pc->pc_ucred);
461 		pc->pc_ucred->cr_uid = uid;
462 		setsugid(p);
463 	}
464 	return (0);
465 }
466 
467 #ifndef _SYS_SYSPROTO_H_
468 struct seteuid_args {
469 	uid_t	euid;
470 };
471 #endif
472 /* ARGSUSED */
473 int
474 seteuid(p, uap)
475 	struct proc *p;
476 	struct seteuid_args *uap;
477 {
478 	register struct pcred *pc = p->p_cred;
479 	register uid_t euid;
480 	int error;
481 
482 	euid = uap->euid;
483 	if (euid != pc->p_ruid &&		/* allow seteuid(getuid()) */
484 	    euid != pc->p_svuid &&		/* allow seteuid(saved uid) */
485 	    (error = suser_xxx(0, p, PRISON_ROOT)))
486 		return (error);
487 	/*
488 	 * Everything's okay, do it.  Copy credentials so other references do
489 	 * not see our changes.
490 	 */
491 	if (pc->pc_ucred->cr_uid != euid) {
492 		pc->pc_ucred = crcopy(pc->pc_ucred);
493 		pc->pc_ucred->cr_uid = euid;
494 		setsugid(p);
495 	}
496 	return (0);
497 }
498 
499 #ifndef _SYS_SYSPROTO_H_
500 struct setgid_args {
501 	gid_t	gid;
502 };
503 #endif
504 /* ARGSUSED */
505 int
506 setgid(p, uap)
507 	struct proc *p;
508 	struct setgid_args *uap;
509 {
510 	register struct pcred *pc = p->p_cred;
511 	register gid_t gid;
512 	int error;
513 
514 	/*
515 	 * See if we have "permission" by POSIX 1003.1 rules.
516 	 *
517 	 * Note that setgid(getegid()) is a special case of
518 	 * "appropriate privileges" in appendix B.4.2.2.  We need
519 	 * to use this clause to be compatable with traditional BSD
520 	 * semantics.  Basically, it means that "setgid(xx)" sets all
521 	 * three id's (assuming you have privs).
522 	 *
523 	 * For notes on the logic here, see setuid() above.
524 	 */
525 	gid = uap->gid;
526 	if (gid != pc->p_rgid &&		/* allow setgid(getgid()) */
527 #ifdef _POSIX_SAVED_IDS
528 	    gid != pc->p_svgid &&		/* allow setgid(saved gid) */
529 #endif
530 #ifdef POSIX_APPENDIX_B_4_2_2	/* Use BSD-compat clause from B.4.2.2 */
531 	    gid != pc->pc_ucred->cr_groups[0] && /* allow setgid(getegid()) */
532 #endif
533 	    (error = suser_xxx(0, p, PRISON_ROOT)))
534 		return (error);
535 
536 #ifdef _POSIX_SAVED_IDS
537 	/*
538 	 * Do we have "appropriate privileges" (are we root or gid == egid)
539 	 * If so, we are changing the real uid and saved gid.
540 	 */
541 	if (
542 #ifdef POSIX_APPENDIX_B_4_2_2	/* use the clause from B.4.2.2 */
543 	    gid == pc->pc_ucred->cr_groups[0] ||
544 #endif
545 	    suser_xxx(0, p, PRISON_ROOT) == 0) /* we are using privs */
546 #endif
547 	{
548 		/*
549 		 * Set real gid
550 		 */
551 		if (pc->p_rgid != gid) {
552 			pc->p_rgid = gid;
553 			setsugid(p);
554 		}
555 		/*
556 		 * Set saved gid
557 		 *
558 		 * XXX always set saved gid even if not _POSIX_SAVED_IDS, as
559 		 * the security of setegid() depends on it.  B.4.2.2 says it
560 		 * is important that we should do this.
561 		 */
562 		if (pc->p_svgid != gid) {
563 			pc->p_svgid = gid;
564 			setsugid(p);
565 		}
566 	}
567 	/*
568 	 * In all cases permitted cases, we are changing the egid.
569 	 * Copy credentials so other references do not see our changes.
570 	 */
571 	if (pc->pc_ucred->cr_groups[0] != gid) {
572 		pc->pc_ucred = crcopy(pc->pc_ucred);
573 		pc->pc_ucred->cr_groups[0] = gid;
574 		setsugid(p);
575 	}
576 	return (0);
577 }
578 
579 #ifndef _SYS_SYSPROTO_H_
580 struct setegid_args {
581 	gid_t	egid;
582 };
583 #endif
584 /* ARGSUSED */
585 int
586 setegid(p, uap)
587 	struct proc *p;
588 	struct setegid_args *uap;
589 {
590 	register struct pcred *pc = p->p_cred;
591 	register gid_t egid;
592 	int error;
593 
594 	egid = uap->egid;
595 	if (egid != pc->p_rgid &&		/* allow setegid(getgid()) */
596 	    egid != pc->p_svgid &&		/* allow setegid(saved gid) */
597 	    (error = suser_xxx(0, p, PRISON_ROOT)))
598 		return (error);
599 	if (pc->pc_ucred->cr_groups[0] != egid) {
600 		pc->pc_ucred = crcopy(pc->pc_ucred);
601 		pc->pc_ucred->cr_groups[0] = egid;
602 		setsugid(p);
603 	}
604 	return (0);
605 }
606 
607 #ifndef _SYS_SYSPROTO_H_
608 struct setgroups_args {
609 	u_int	gidsetsize;
610 	gid_t	*gidset;
611 };
612 #endif
613 /* ARGSUSED */
614 int
615 setgroups(p, uap)
616 	struct proc *p;
617 	struct setgroups_args *uap;
618 {
619 	register struct pcred *pc = p->p_cred;
620 	register u_int ngrp;
621 	int error;
622 
623 	if ((error = suser_xxx(0, p, PRISON_ROOT)))
624 		return (error);
625 	ngrp = uap->gidsetsize;
626 	if (ngrp > NGROUPS)
627 		return (EINVAL);
628 	/*
629 	 * XXX A little bit lazy here.  We could test if anything has
630 	 * changed before crcopy() and setting P_SUGID.
631 	 */
632 	pc->pc_ucred = crcopy(pc->pc_ucred);
633 	if (ngrp < 1) {
634 		/*
635 		 * setgroups(0, NULL) is a legitimate way of clearing the
636 		 * groups vector on non-BSD systems (which generally do not
637 		 * have the egid in the groups[0]).  We risk security holes
638 		 * when running non-BSD software if we do not do the same.
639 		 */
640 		pc->pc_ucred->cr_ngroups = 1;
641 	} else {
642 		if ((error = copyin((caddr_t)uap->gidset,
643 		    (caddr_t)pc->pc_ucred->cr_groups, ngrp * sizeof(gid_t))))
644 			return (error);
645 		pc->pc_ucred->cr_ngroups = ngrp;
646 	}
647 	setsugid(p);
648 	return (0);
649 }
650 
651 #ifndef _SYS_SYSPROTO_H_
652 struct setreuid_args {
653 	uid_t	ruid;
654 	uid_t	euid;
655 };
656 #endif
657 /* ARGSUSED */
658 int
659 setreuid(p, uap)
660 	register struct proc *p;
661 	struct setreuid_args *uap;
662 {
663 	register struct pcred *pc = p->p_cred;
664 	register uid_t ruid, euid;
665 	int error;
666 
667 	ruid = uap->ruid;
668 	euid = uap->euid;
669 	if (((ruid != (uid_t)-1 && ruid != pc->p_ruid && ruid != pc->p_svuid) ||
670 	     (euid != (uid_t)-1 && euid != pc->pc_ucred->cr_uid &&
671 	     euid != pc->p_ruid && euid != pc->p_svuid)) &&
672 	    (error = suser_xxx(0, p, PRISON_ROOT)) != 0)
673 		return (error);
674 
675 	if (euid != (uid_t)-1 && pc->pc_ucred->cr_uid != euid) {
676 		pc->pc_ucred = crcopy(pc->pc_ucred);
677 		pc->pc_ucred->cr_uid = euid;
678 		setsugid(p);
679 	}
680 	if (ruid != (uid_t)-1 && pc->p_ruid != ruid) {
681 		(void)chgproccnt(pc->p_ruid, -1);
682 		(void)chgproccnt(ruid, 1);
683 		pc->p_ruid = 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_
695 struct setregid_args {
696 	gid_t	rgid;
697 	gid_t	egid;
698 };
699 #endif
700 /* ARGSUSED */
701 int
702 setregid(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_
741 struct setresuid_args {
742 	uid_t	ruid;
743 	uid_t	euid;
744 	uid_t	suid;
745 };
746 #endif
747 /* ARGSUSED */
748 int
749 setresuid(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 		pc->pc_ucred = crcopy(pc->pc_ucred);
770 		pc->pc_ucred->cr_uid = euid;
771 		setsugid(p);
772 	}
773 	if (ruid != (uid_t)-1 && pc->p_ruid != ruid) {
774 		(void)chgproccnt(pc->p_ruid, -1);
775 		(void)chgproccnt(ruid, 1);
776 		pc->p_ruid = ruid;
777 		setsugid(p);
778 	}
779 	if (suid != (uid_t)-1 && pc->p_svuid != suid) {
780 		pc->p_svuid = suid;
781 		setsugid(p);
782 	}
783 	return (0);
784 }
785 
786 /*
787  * setresgid(rgid, egid, sgid) is like setregid except control over the
788  * saved gid is explicit.
789  */
790 
791 #ifndef _SYS_SYSPROTO_H_
792 struct setresgid_args {
793 	gid_t	rgid;
794 	gid_t	egid;
795 	gid_t	sgid;
796 };
797 #endif
798 /* ARGSUSED */
799 int
800 setresgid(p, uap)
801 	register struct proc *p;
802 	struct setresgid_args *uap;
803 {
804 	register struct pcred *pc = p->p_cred;
805 	register gid_t rgid, egid, sgid;
806 	int error;
807 
808 	rgid = uap->rgid;
809 	egid = uap->egid;
810 	sgid = uap->sgid;
811 	if (((rgid != (gid_t)-1 && rgid != pc->p_rgid && rgid != pc->p_svgid &&
812 	      rgid != pc->pc_ucred->cr_groups[0]) ||
813 	     (egid != (gid_t)-1 && egid != pc->p_rgid && egid != pc->p_svgid &&
814 	      egid != pc->pc_ucred->cr_groups[0]) ||
815 	     (sgid != (gid_t)-1 && sgid != pc->p_rgid && sgid != pc->p_svgid &&
816 	      sgid != pc->pc_ucred->cr_groups[0])) &&
817 	    (error = suser_xxx(0, p, PRISON_ROOT)) != 0)
818 		return (error);
819 
820 	if (egid != (gid_t)-1 && pc->pc_ucred->cr_groups[0] != egid) {
821 		pc->pc_ucred = crcopy(pc->pc_ucred);
822 		pc->pc_ucred->cr_groups[0] = egid;
823 		setsugid(p);
824 	}
825 	if (rgid != (gid_t)-1 && pc->p_rgid != rgid) {
826 		pc->p_rgid = rgid;
827 		setsugid(p);
828 	}
829 	if (sgid != (gid_t)-1 && pc->p_svgid != sgid) {
830 		pc->p_svgid = sgid;
831 		setsugid(p);
832 	}
833 	return (0);
834 }
835 
836 #ifndef _SYS_SYSPROTO_H_
837 struct getresuid_args {
838 	uid_t	*ruid;
839 	uid_t	*euid;
840 	uid_t	*suid;
841 };
842 #endif
843 /* ARGSUSED */
844 int
845 getresuid(p, uap)
846 	register struct proc *p;
847 	struct getresuid_args *uap;
848 {
849 	struct pcred *pc = p->p_cred;
850 	int error1 = 0, error2 = 0, error3 = 0;
851 
852 	if (uap->ruid)
853 		error1 = copyout((caddr_t)&pc->p_ruid,
854 		    (caddr_t)uap->ruid, sizeof(pc->p_ruid));
855 	if (uap->euid)
856 		error2 = copyout((caddr_t)&pc->pc_ucred->cr_uid,
857 		    (caddr_t)uap->euid, sizeof(pc->pc_ucred->cr_uid));
858 	if (uap->suid)
859 		error3 = copyout((caddr_t)&pc->p_svuid,
860 		    (caddr_t)uap->suid, sizeof(pc->p_svuid));
861 	return error1 ? error1 : (error2 ? error2 : error3);
862 }
863 
864 #ifndef _SYS_SYSPROTO_H_
865 struct getresgid_args {
866 	gid_t	*rgid;
867 	gid_t	*egid;
868 	gid_t	*sgid;
869 };
870 #endif
871 /* ARGSUSED */
872 int
873 getresgid(p, uap)
874 	register struct proc *p;
875 	struct getresgid_args *uap;
876 {
877 	struct pcred *pc = p->p_cred;
878 	int error1 = 0, error2 = 0, error3 = 0;
879 
880 	if (uap->rgid)
881 		error1 = copyout((caddr_t)&pc->p_rgid,
882 		    (caddr_t)uap->rgid, sizeof(pc->p_rgid));
883 	if (uap->egid)
884 		error2 = copyout((caddr_t)&pc->pc_ucred->cr_groups[0],
885 		    (caddr_t)uap->egid, sizeof(pc->pc_ucred->cr_groups[0]));
886 	if (uap->sgid)
887 		error3 = copyout((caddr_t)&pc->p_svgid,
888 		    (caddr_t)uap->sgid, sizeof(pc->p_svgid));
889 	return error1 ? error1 : (error2 ? error2 : error3);
890 }
891 
892 
893 #ifndef _SYS_SYSPROTO_H_
894 struct issetugid_args {
895 	int dummy;
896 };
897 #endif
898 /* ARGSUSED */
899 int
900 issetugid(p, uap)
901 	register struct proc *p;
902 	struct issetugid_args *uap;
903 {
904 	/*
905 	 * Note: OpenBSD sets a P_SUGIDEXEC flag set at execve() time,
906 	 * we use P_SUGID because we consider changing the owners as
907 	 * "tainting" as well.
908 	 * This is significant for procs that start as root and "become"
909 	 * a user without an exec - programs cannot know *everything*
910 	 * that libc *might* have put in their data segment.
911 	 */
912 	if (p->p_flag & P_SUGID)
913 		return (1);
914 	return (0);
915 }
916 
917 /*
918  * Check if gid is a member of the group set.
919  */
920 int
921 groupmember(gid, cred)
922 	gid_t gid;
923 	register struct ucred *cred;
924 {
925 	register gid_t *gp;
926 	gid_t *egp;
927 
928 	egp = &(cred->cr_groups[cred->cr_ngroups]);
929 	for (gp = cred->cr_groups; gp < egp; gp++)
930 		if (*gp == gid)
931 			return (1);
932 	return (0);
933 }
934 
935 /*
936  * Test whether the specified credentials imply "super-user"
937  * privilege; if so, and we have accounting info, set the flag
938  * indicating use of super-powers.
939  * Returns 0 or error.
940  */
941 int
942 suser(p)
943 	struct proc *p;
944 {
945 	return suser_xxx(0, p, 0);
946 }
947 
948 int
949 suser_xxx(cred, proc, flag)
950 	struct ucred *cred;
951 	struct proc *proc;
952 	int flag;
953 {
954 	if (!cred && !proc) {
955 		printf("suser_xxx(): THINK!\n");
956 		return (EPERM);
957 	}
958 	if (!cred)
959 		cred = proc->p_ucred;
960 	if (cred->cr_uid != 0)
961 		return (EPERM);
962 	if (proc && proc->p_prison && !(flag & PRISON_ROOT))
963 		return (EPERM);
964 	if (proc)
965 		proc->p_acflag |= ASU;
966 	return (0);
967 }
968 
969 /*
970  * Return zero if p1 can fondle p2, return errno (EPERM/ESRCH) otherwise.
971  */
972 
973 int
974 p_trespass(struct proc *p1, struct proc *p2)
975 {
976 
977 	if (p1 == p2)
978 		return (0);
979 	if (!PRISON_CHECK(p1, p2))
980 		return (ESRCH);
981 	if (p1->p_cred->p_ruid == p2->p_cred->p_ruid)
982 		return (0);
983 	if (p1->p_ucred->cr_uid == p2->p_cred->p_ruid)
984 		return (0);
985 	if (p1->p_cred->p_ruid == p2->p_ucred->cr_uid)
986 		return (0);
987 	if (p1->p_ucred->cr_uid == p2->p_ucred->cr_uid)
988 		return (0);
989 	if (!suser_xxx(0, p1, PRISON_ROOT))
990 		return (0);
991 	return (EPERM);
992 }
993 
994 /*
995  * Allocate a zeroed cred structure.
996  */
997 struct ucred *
998 crget()
999 {
1000 	register struct ucred *cr;
1001 
1002 	MALLOC(cr, struct ucred *, sizeof(*cr), M_CRED, M_WAITOK);
1003 	bzero((caddr_t)cr, sizeof(*cr));
1004 	cr->cr_ref = 1;
1005 	return (cr);
1006 }
1007 
1008 /*
1009  * Free a cred structure.
1010  * Throws away space when ref count gets to 0.
1011  */
1012 void
1013 crfree(cr)
1014 	struct ucred *cr;
1015 {
1016 	if (--cr->cr_ref == 0)
1017 		FREE((caddr_t)cr, M_CRED);
1018 }
1019 
1020 /*
1021  * Copy cred structure to a new one and free the old one.
1022  */
1023 struct ucred *
1024 crcopy(cr)
1025 	struct ucred *cr;
1026 {
1027 	struct ucred *newcr;
1028 
1029 	if (cr->cr_ref == 1)
1030 		return (cr);
1031 	newcr = crget();
1032 	*newcr = *cr;
1033 	crfree(cr);
1034 	newcr->cr_ref = 1;
1035 	return (newcr);
1036 }
1037 
1038 /*
1039  * Dup cred struct to a new held one.
1040  */
1041 struct ucred *
1042 crdup(cr)
1043 	struct ucred *cr;
1044 {
1045 	struct ucred *newcr;
1046 
1047 	newcr = crget();
1048 	*newcr = *cr;
1049 	newcr->cr_ref = 1;
1050 	return (newcr);
1051 }
1052 
1053 /*
1054  * Get login name, if available.
1055  */
1056 #ifndef _SYS_SYSPROTO_H_
1057 struct getlogin_args {
1058 	char	*namebuf;
1059 	u_int	namelen;
1060 };
1061 #endif
1062 /* ARGSUSED */
1063 int
1064 getlogin(p, uap)
1065 	struct proc *p;
1066 	struct getlogin_args *uap;
1067 {
1068 
1069 	if (uap->namelen > MAXLOGNAME)
1070 		uap->namelen = MAXLOGNAME;
1071 	return (copyout((caddr_t) p->p_pgrp->pg_session->s_login,
1072 	    (caddr_t) uap->namebuf, uap->namelen));
1073 }
1074 
1075 /*
1076  * Set login name.
1077  */
1078 #ifndef _SYS_SYSPROTO_H_
1079 struct setlogin_args {
1080 	char	*namebuf;
1081 };
1082 #endif
1083 /* ARGSUSED */
1084 int
1085 setlogin(p, uap)
1086 	struct proc *p;
1087 	struct setlogin_args *uap;
1088 {
1089 	int error;
1090 	char logintmp[MAXLOGNAME];
1091 
1092 	if ((error = suser_xxx(0, p, PRISON_ROOT)))
1093 		return (error);
1094 	error = copyinstr((caddr_t) uap->namebuf, (caddr_t) logintmp,
1095 	    sizeof(logintmp), (size_t *)0);
1096 	if (error == ENAMETOOLONG)
1097 		error = EINVAL;
1098 	else if (!error)
1099 		(void) memcpy(p->p_pgrp->pg_session->s_login, logintmp,
1100 		    sizeof(logintmp));
1101 	return (error);
1102 }
1103 
1104 void
1105 setsugid(p)
1106 	struct proc *p;
1107 {
1108 	p->p_flag |= P_SUGID;
1109 	if (!(p->p_pfsflags & PF_ISUGID))
1110 		p->p_stops = 0;
1111 }
1112