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