xref: /openbsd-src/sys/kern/kern_prot.c (revision bb5dd46a8458ce3e04e7bbee8bfe3ad51905912d)
1 /*	$OpenBSD: kern_prot.c,v 1.66 2016/09/02 18:11:28 tedu Exp $	*/
2 /*	$NetBSD: kern_prot.c,v 1.33 1996/02/09 18:59:42 christos Exp $	*/
3 
4 /*
5  * Copyright (c) 1982, 1986, 1989, 1990, 1991, 1993
6  *	The Regents of the University of California.  All rights reserved.
7  * (c) UNIX System Laboratories, Inc.
8  * All or some portions of this file are derived from material licensed
9  * to the University of California by American Telephone and Telegraph
10  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
11  * the permission of UNIX System Laboratories, Inc.
12  *
13  * Redistribution and use in source and binary forms, with or without
14  * modification, are permitted provided that the following conditions
15  * are met:
16  * 1. Redistributions of source code must retain the above copyright
17  *    notice, this list of conditions and the following disclaimer.
18  * 2. Redistributions in binary form must reproduce the above copyright
19  *    notice, this list of conditions and the following disclaimer in the
20  *    documentation and/or other materials provided with the distribution.
21  * 3. Neither the name of the University nor the names of its contributors
22  *    may be used to endorse or promote products derived from this software
23  *    without specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35  * SUCH DAMAGE.
36  *
37  *	@(#)kern_prot.c	8.6 (Berkeley) 1/21/94
38  */
39 
40 /*
41  * System calls related to processes and protection
42  */
43 
44 #include <sys/param.h>
45 #include <sys/acct.h>
46 #include <sys/systm.h>
47 #include <sys/ucred.h>
48 #include <sys/proc.h>
49 #include <sys/filedesc.h>
50 #include <sys/pool.h>
51 
52 #include <sys/mount.h>
53 #include <sys/syscallargs.h>
54 
55 #ifdef	__HAVE_MD_TCB
56 # include <machine/tcb.h>
57 #endif
58 
59 inline void
60 crset(struct ucred *newcr, const struct ucred *cr)
61 {
62 	KASSERT(cr->cr_ref > 0);
63 	memcpy(
64 	    (char *)newcr    + offsetof(struct ucred, cr_startcopy),
65 	    (const char *)cr + offsetof(struct ucred, cr_startcopy),
66 	    sizeof(*cr)      - offsetof(struct ucred, cr_startcopy));
67 }
68 
69 int
70 sys_getpid(struct proc *p, void *v, register_t *retval)
71 {
72 
73 	*retval = p->p_p->ps_pid;
74 	return (0);
75 }
76 
77 int
78 sys_getthrid(struct proc *p, void *v, register_t *retval)
79 {
80 
81 	*retval = p->p_pid + THREAD_PID_OFFSET;
82 	return (0);
83 }
84 
85 int
86 sys_getppid(struct proc *p, void *v, register_t *retval)
87 {
88 
89 	*retval = p->p_p->ps_pptr->ps_pid;
90 	return (0);
91 }
92 
93 /* Get process group ID; note that POSIX getpgrp takes no parameter */
94 int
95 sys_getpgrp(struct proc *p, void *v, register_t *retval)
96 {
97 
98 	*retval = p->p_p->ps_pgrp->pg_id;
99 	return (0);
100 }
101 
102 /*
103  * SysVR.4 compatible getpgid()
104  */
105 int
106 sys_getpgid(struct proc *curp, void *v, register_t *retval)
107 {
108 	struct sys_getpgid_args /* {
109 		syscallarg(pid_t) pid;
110 	} */ *uap = v;
111 	struct process *targpr = curp->p_p;
112 
113 	if (SCARG(uap, pid) == 0 || SCARG(uap, pid) == targpr->ps_pid)
114 		goto found;
115 	if ((targpr = prfind(SCARG(uap, pid))) == NULL)
116 		return (ESRCH);
117 	if (targpr->ps_session != curp->p_p->ps_session)
118 		return (EPERM);
119 found:
120 	*retval = targpr->ps_pgid;
121 	return (0);
122 }
123 
124 int
125 sys_getsid(struct proc *curp, void *v, register_t *retval)
126 {
127 	struct sys_getsid_args /* {
128 		syscallarg(pid_t) pid;
129 	} */ *uap = v;
130 	struct process *targpr = curp->p_p;
131 
132 	if (SCARG(uap, pid) == 0 || SCARG(uap, pid) == targpr->ps_pid)
133 		goto found;
134 	if ((targpr = prfind(SCARG(uap, pid))) == NULL)
135 		return (ESRCH);
136 	if (targpr->ps_session != curp->p_p->ps_session)
137 		return (EPERM);
138 found:
139 	/* Skip exiting processes */
140 	if (targpr->ps_pgrp->pg_session->s_leader == NULL)
141 		return (ESRCH);
142 	*retval = targpr->ps_pgrp->pg_session->s_leader->ps_pid;
143 	return (0);
144 }
145 
146 int
147 sys_getuid(struct proc *p, void *v, register_t *retval)
148 {
149 
150 	*retval = p->p_ucred->cr_ruid;
151 	return (0);
152 }
153 
154 int
155 sys_geteuid(struct proc *p, void *v, register_t *retval)
156 {
157 
158 	*retval = p->p_ucred->cr_uid;
159 	return (0);
160 }
161 
162 int
163 sys_issetugid(struct proc *p, void *v, register_t *retval)
164 {
165 	if (p->p_p->ps_flags & PS_SUGIDEXEC)
166 		*retval = 1;
167 	else
168 		*retval = 0;
169 	return (0);
170 }
171 
172 int
173 sys_getgid(struct proc *p, void *v, register_t *retval)
174 {
175 
176 	*retval = p->p_ucred->cr_rgid;
177 	return (0);
178 }
179 
180 /*
181  * Get effective group ID.  The "egid" is groups[0], and could be obtained
182  * via getgroups.  This syscall exists because it is somewhat painful to do
183  * correctly in a library function.
184  */
185 int
186 sys_getegid(struct proc *p, void *v, register_t *retval)
187 {
188 
189 	*retval = p->p_ucred->cr_gid;
190 	return (0);
191 }
192 
193 int
194 sys_getgroups(struct proc *p, void *v, register_t *retval)
195 {
196 	struct sys_getgroups_args /* {
197 		syscallarg(int) gidsetsize;
198 		syscallarg(gid_t *) gidset;
199 	} */ *uap = v;
200 	struct ucred *uc = p->p_ucred;
201 	u_int ngrp;
202 	int error;
203 
204 	if ((ngrp = SCARG(uap, gidsetsize)) == 0) {
205 		*retval = uc->cr_ngroups;
206 		return (0);
207 	}
208 	if (ngrp < uc->cr_ngroups)
209 		return (EINVAL);
210 	ngrp = uc->cr_ngroups;
211 	error = copyout(uc->cr_groups, SCARG(uap, gidset),
212 	    ngrp * sizeof(gid_t));
213 	if (error)
214 		return (error);
215 	*retval = ngrp;
216 	return (0);
217 }
218 
219 int
220 sys_setsid(struct proc *p, void *v, register_t *retval)
221 {
222 	struct session *newsess;
223 	struct pgrp *newpgrp;
224 	struct process *pr = p->p_p;
225 	pid_t pid = pr->ps_pid;
226 
227 	newsess = pool_get(&session_pool, PR_WAITOK);
228 	timeout_set(&newsess->s_verauthto, zapverauth, newsess);
229 	newpgrp = pool_get(&pgrp_pool, PR_WAITOK);
230 
231 	if (pr->ps_pgid == pid || pgfind(pid)) {
232 		pool_put(&pgrp_pool, newpgrp);
233 		pool_put(&session_pool, newsess);
234 		return (EPERM);
235 	} else {
236 		(void) enterpgrp(pr, pid, newpgrp, newsess);
237 		*retval = pid;
238 		return (0);
239 	}
240 }
241 
242 /*
243  * set process group (setpgid/old setpgrp)
244  *
245  * caller does setpgid(targpid, targpgid)
246  *
247  * pid must be caller or child of caller (ESRCH)
248  * if a child
249  *	pid must be in same session (EPERM)
250  *	pid can't have done an exec (EACCES)
251  * if pgid != pid
252  * 	there must exist some pid in same session having pgid (EPERM)
253  * pid must not be session leader (EPERM)
254  */
255 int
256 sys_setpgid(struct proc *curp, void *v, register_t *retval)
257 {
258 	struct sys_setpgid_args /* {
259 		syscallarg(pid_t) pid;
260 		syscallarg(pid_t) pgid;
261 	} */ *uap = v;
262 	struct process *curpr = curp->p_p;
263 	struct process *targpr;		/* target process */
264 	struct pgrp *pgrp, *newpgrp;	/* target pgrp */
265 	pid_t pid, pgid;
266 	int error;
267 
268 	pid = SCARG(uap, pid);
269 	pgid = SCARG(uap, pgid);
270 
271 	if (pgid < 0)
272 		return (EINVAL);
273 
274 	newpgrp = pool_get(&pgrp_pool, PR_WAITOK);
275 
276 	if (pid != 0 && pid != curpr->ps_pid) {
277 		if ((targpr = prfind(pid)) == 0 || !inferior(targpr, curpr)) {
278 			error = ESRCH;
279 			goto out;
280 		}
281 		if (targpr->ps_session != curpr->ps_session) {
282 			error = EPERM;
283 			goto out;
284 		}
285 		if (targpr->ps_flags & PS_EXEC) {
286 			error = EACCES;
287 			goto out;
288 		}
289 	} else
290 		targpr = curpr;
291 	if (SESS_LEADER(targpr)) {
292 		error = EPERM;
293 		goto out;
294 	}
295 	if (pgid == 0)
296 		pgid = targpr->ps_pid;
297 	else if (pgid != targpr->ps_pid)
298 		if ((pgrp = pgfind(pgid)) == 0 ||
299 		    pgrp->pg_session != curpr->ps_session) {
300 			error = EPERM;
301 			goto out;
302 		}
303 	return (enterpgrp(targpr, pgid, newpgrp, NULL));
304 out:
305 	pool_put(&pgrp_pool, newpgrp);
306 	return (error);
307 }
308 
309 int
310 sys_getresuid(struct proc *p, void *v, register_t *retval)
311 {
312 	struct sys_getresuid_args /* {
313 		syscallarg(uid_t *) ruid;
314 		syscallarg(uid_t *) euid;
315 		syscallarg(uid_t *) suid;
316 	} */ *uap = v;
317 	struct ucred *uc = p->p_ucred;
318 	uid_t *ruid, *euid, *suid;
319 	int error1 = 0, error2 = 0, error3 = 0;
320 
321 	ruid = SCARG(uap, ruid);
322 	euid = SCARG(uap, euid);
323 	suid = SCARG(uap, suid);
324 
325 	if (ruid != NULL)
326 		error1 = copyout(&uc->cr_ruid, ruid, sizeof(*ruid));
327 	if (euid != NULL)
328 		error2 = copyout(&uc->cr_uid, euid, sizeof(*euid));
329 	if (suid != NULL)
330 		error3 = copyout(&uc->cr_svuid, suid, sizeof(*suid));
331 
332 	return (error1 ? error1 : error2 ? error2 : error3);
333 }
334 
335 int
336 sys_setresuid(struct proc *p, void *v, register_t *retval)
337 {
338 	struct sys_setresuid_args /* {
339 		syscallarg(uid_t) ruid;
340 		syscallarg(uid_t) euid;
341 		syscallarg(uid_t) suid;
342 	} */ *uap = v;
343 	struct process *pr = p->p_p;
344 	struct ucred *pruc, *newcred, *uc = p->p_ucred;
345 	uid_t ruid, euid, suid;
346 	int error;
347 
348 	ruid = SCARG(uap, ruid);
349 	euid = SCARG(uap, euid);
350 	suid = SCARG(uap, suid);
351 
352 	/*
353 	 * make permission checks against the thread's ucred,
354 	 * but the actual changes will be to the process's ucred
355 	 */
356 	pruc = pr->ps_ucred;
357 	if ((ruid == (uid_t)-1 || ruid == pruc->cr_ruid) &&
358 	    (euid == (uid_t)-1 || euid == pruc->cr_uid) &&
359 	    (suid == (uid_t)-1 || suid == pruc->cr_svuid))
360 		return (0);			/* no change */
361 
362 	/*
363 	 * Any of the real, effective, and saved uids may be changed
364 	 * to the current value of one of the three (root is not limited).
365 	 */
366 	if (ruid != (uid_t)-1 &&
367 	    ruid != uc->cr_ruid &&
368 	    ruid != uc->cr_uid &&
369 	    ruid != uc->cr_svuid &&
370 	    (error = suser(p, 0)))
371 		return (error);
372 
373 	if (euid != (uid_t)-1 &&
374 	    euid != uc->cr_ruid &&
375 	    euid != uc->cr_uid &&
376 	    euid != uc->cr_svuid &&
377 	    (error = suser(p, 0)))
378 		return (error);
379 
380 	if (suid != (uid_t)-1 &&
381 	    suid != uc->cr_ruid &&
382 	    suid != uc->cr_uid &&
383 	    suid != uc->cr_svuid &&
384 	    (error = suser(p, 0)))
385 		return (error);
386 
387 	/*
388 	 * Copy credentials so other references do not see our changes.
389 	 * ps_ucred may change during the crget().
390 	 */
391 	newcred = crget();
392 	pruc = pr->ps_ucred;
393 	crset(newcred, pruc);
394 
395 	/*
396 	 * Note that unlike the other set*uid() calls, each
397 	 * uid type is set independently of the others.
398 	 */
399 	if (ruid != (uid_t)-1)
400 		newcred->cr_ruid = ruid;
401 	if (euid != (uid_t)-1)
402 		newcred->cr_uid = euid;
403 	if (suid != (uid_t)-1)
404 		newcred->cr_svuid = suid;
405 	pr->ps_ucred = newcred;
406 	atomic_setbits_int(&p->p_p->ps_flags, PS_SUGID);
407 
408 	/* now that we can sleep, transfer proc count to new user */
409 	if (ruid != (uid_t)-1 && ruid != pruc->cr_ruid) {
410 		chgproccnt(pruc->cr_ruid, -1);
411 		chgproccnt(ruid, 1);
412 	}
413 	crfree(pruc);
414 
415 	return (0);
416 }
417 
418 int
419 sys_getresgid(struct proc *p, void *v, register_t *retval)
420 {
421 	struct sys_getresgid_args /* {
422 		syscallarg(gid_t *) rgid;
423 		syscallarg(gid_t *) egid;
424 		syscallarg(gid_t *) sgid;
425 	} */ *uap = v;
426 	struct ucred *uc = p->p_ucred;
427 	gid_t *rgid, *egid, *sgid;
428 	int error1 = 0, error2 = 0, error3 = 0;
429 
430 	rgid = SCARG(uap, rgid);
431 	egid = SCARG(uap, egid);
432 	sgid = SCARG(uap, sgid);
433 
434 	if (rgid != NULL)
435 		error1 = copyout(&uc->cr_rgid, rgid, sizeof(*rgid));
436 	if (egid != NULL)
437 		error2 = copyout(&uc->cr_gid, egid, sizeof(*egid));
438 	if (sgid != NULL)
439 		error3 = copyout(&uc->cr_svgid, sgid, sizeof(*sgid));
440 
441 	return (error1 ? error1 : error2 ? error2 : error3);
442 }
443 
444 int
445 sys_setresgid(struct proc *p, void *v, register_t *retval)
446 {
447 	struct sys_setresgid_args /* {
448 		syscallarg(gid_t) rgid;
449 		syscallarg(gid_t) egid;
450 		syscallarg(gid_t) sgid;
451 	} */ *uap = v;
452 	struct process *pr = p->p_p;
453 	struct ucred *pruc, *newcred, *uc = p->p_ucred;
454 	gid_t rgid, egid, sgid;
455 	int error;
456 
457 	rgid = SCARG(uap, rgid);
458 	egid = SCARG(uap, egid);
459 	sgid = SCARG(uap, sgid);
460 
461 	/*
462 	 * make permission checks against the thread's ucred,
463 	 * but the actual changes will be to the process's ucred
464 	 */
465 	pruc = pr->ps_ucred;
466 	if ((rgid == (gid_t)-1 || rgid == pruc->cr_rgid) &&
467 	    (egid == (gid_t)-1 || egid == pruc->cr_gid) &&
468 	    (sgid == (gid_t)-1 || sgid == pruc->cr_svgid))
469 		return (0);			/* no change */
470 
471 	/*
472 	 * Any of the real, effective, and saved gids may be changed
473 	 * to the current value of one of the three (root is not limited).
474 	 */
475 	if (rgid != (gid_t)-1 &&
476 	    rgid != uc->cr_rgid &&
477 	    rgid != uc->cr_gid &&
478 	    rgid != uc->cr_svgid &&
479 	    (error = suser(p, 0)))
480 		return (error);
481 
482 	if (egid != (gid_t)-1 &&
483 	    egid != uc->cr_rgid &&
484 	    egid != uc->cr_gid &&
485 	    egid != uc->cr_svgid &&
486 	    (error = suser(p, 0)))
487 		return (error);
488 
489 	if (sgid != (gid_t)-1 &&
490 	    sgid != uc->cr_rgid &&
491 	    sgid != uc->cr_gid &&
492 	    sgid != uc->cr_svgid &&
493 	    (error = suser(p, 0)))
494 		return (error);
495 
496 	/*
497 	 * Copy credentials so other references do not see our changes.
498 	 * ps_ucred may change during the crget().
499 	 */
500 	newcred = crget();
501 	pruc = pr->ps_ucred;
502 	crset(newcred, pruc);
503 
504 	/*
505 	 * Note that unlike the other set*gid() calls, each
506 	 * gid type is set independently of the others.
507 	 */
508 	if (rgid != (gid_t)-1)
509 		newcred->cr_rgid = rgid;
510 	if (egid != (gid_t)-1)
511 		newcred->cr_gid = egid;
512 	if (sgid != (gid_t)-1)
513 		newcred->cr_svgid = sgid;
514 	pr->ps_ucred = newcred;
515 	atomic_setbits_int(&p->p_p->ps_flags, PS_SUGID);
516 	crfree(pruc);
517 	return (0);
518 }
519 
520 int
521 sys_setregid(struct proc *p, void *v, register_t *retval)
522 {
523 	struct sys_setregid_args /* {
524 		syscallarg(gid_t) rgid;
525 		syscallarg(gid_t) egid;
526 	} */ *uap = v;
527 	struct process *pr = p->p_p;
528 	struct ucred *pruc, *newcred, *uc = p->p_ucred;
529 	gid_t rgid, egid;
530 	int error;
531 
532 	rgid = SCARG(uap, rgid);
533 	egid = SCARG(uap, egid);
534 
535 	/*
536 	 * make permission checks against the thread's ucred,
537 	 * but the actual changes will be to the process's ucred
538 	 *
539 	 * The saved gid check here is complicated: we reset the
540 	 * saved gid to the real gid if the real gid is specified
541 	 * *and* either it's changing _or_ the saved gid won't equal
542 	 * the effective gid.  So, the svgid *won't* change when
543 	 * the rgid isn't specified or when the rgid isn't changing
544 	 * and the svgid equals the requested egid.
545 	 */
546 	pruc = pr->ps_ucred;
547 	if ((rgid == (gid_t)-1 || rgid == pruc->cr_rgid) &&
548 	    (egid == (gid_t)-1 || egid == pruc->cr_gid) &&
549 	    (rgid == (gid_t)-1 || (rgid == pruc->cr_rgid &&
550 	    pruc->cr_svgid == (egid != (gid_t)-1 ? egid : pruc->cr_gid))))
551 		return (0);			/* no change */
552 
553 	/*
554 	 * Any of the real, effective, and saved gids may be changed
555 	 * to the current value of one of the three (root is not limited).
556 	 */
557 	if (rgid != (gid_t)-1 &&
558 	    rgid != uc->cr_rgid &&
559 	    rgid != uc->cr_gid &&
560 	    rgid != uc->cr_svgid &&
561 	    (error = suser(p, 0)))
562 		return (error);
563 
564 	if (egid != (gid_t)-1 &&
565 	    egid != uc->cr_rgid &&
566 	    egid != uc->cr_gid &&
567 	    egid != uc->cr_svgid &&
568 	    (error = suser(p, 0)))
569 		return (error);
570 
571 	/*
572 	 * Copy credentials so other references do not see our changes.
573 	 * ps_ucred may change during the crget().
574 	 */
575 	newcred = crget();
576 	pruc = pr->ps_ucred;
577 	crset(newcred, pruc);
578 
579 	if (rgid != (gid_t)-1)
580 		newcred->cr_rgid = rgid;
581 	if (egid != (gid_t)-1)
582 		newcred->cr_gid = egid;
583 
584 	/*
585 	 * The saved gid presents a bit of a dilemma, as it did not
586 	 * exist when setregid(2) was conceived.  We only set the saved
587 	 * gid when the real gid is specified and either its value would
588 	 * change, or where the saved and effective gids are different.
589 	 */
590 	if (rgid != (gid_t)-1 && (rgid != pruc->cr_rgid ||
591 	    pruc->cr_svgid != (egid != (gid_t)-1 ? egid : pruc->cr_gid)))
592 		newcred->cr_svgid = rgid;
593 	pr->ps_ucred = newcred;
594 	atomic_setbits_int(&p->p_p->ps_flags, PS_SUGID);
595 	crfree(pruc);
596 	return (0);
597 }
598 
599 int
600 sys_setreuid(struct proc *p, void *v, register_t *retval)
601 {
602 	struct sys_setreuid_args /* {
603 		syscallarg(uid_t) ruid;
604 		syscallarg(uid_t) euid;
605 	} */ *uap = v;
606 	struct process *pr = p->p_p;
607 	struct ucred *pruc, *newcred, *uc = p->p_ucred;
608 	uid_t ruid, euid;
609 	int error;
610 
611 	ruid = SCARG(uap, ruid);
612 	euid = SCARG(uap, euid);
613 
614 	/*
615 	 * make permission checks against the thread's ucred,
616 	 * but the actual changes will be to the process's ucred
617 	 *
618 	 * The saved uid check here is complicated: we reset the
619 	 * saved uid to the real uid if the real uid is specified
620 	 * *and* either it's changing _or_ the saved uid won't equal
621 	 * the effective uid.  So, the svuid *won't* change when
622 	 * the ruid isn't specified or when the ruid isn't changing
623 	 * and the svuid equals the requested euid.
624 	 */
625 	pruc = pr->ps_ucred;
626 	if ((ruid == (uid_t)-1 || ruid == pruc->cr_ruid) &&
627 	    (euid == (uid_t)-1 || euid == pruc->cr_uid) &&
628 	    (ruid == (uid_t)-1 || (ruid == pruc->cr_ruid &&
629 	    pruc->cr_svuid == (euid != (uid_t)-1 ? euid : pruc->cr_uid))))
630 		return (0);			/* no change */
631 
632 	/*
633 	 * Any of the real, effective, and saved uids may be changed
634 	 * to the current value of one of the three (root is not limited).
635 	 */
636 	if (ruid != (uid_t)-1 &&
637 	    ruid != uc->cr_ruid &&
638 	    ruid != uc->cr_uid &&
639 	    ruid != uc->cr_svuid &&
640 	    (error = suser(p, 0)))
641 		return (error);
642 
643 	if (euid != (uid_t)-1 &&
644 	    euid != uc->cr_ruid &&
645 	    euid != uc->cr_uid &&
646 	    euid != uc->cr_svuid &&
647 	    (error = suser(p, 0)))
648 		return (error);
649 
650 	/*
651 	 * Copy credentials so other references do not see our changes.
652 	 * ps_ucred may change during the crget().
653 	 */
654 	newcred = crget();
655 	pruc = pr->ps_ucred;
656 	crset(newcred, pruc);
657 
658 	if (ruid != (uid_t)-1)
659 		newcred->cr_ruid = ruid;
660 	if (euid != (uid_t)-1)
661 		newcred->cr_uid = euid;
662 
663 	/*
664 	 * The saved uid presents a bit of a dilemma, as it did not
665 	 * exist when setreuid(2) was conceived.  We only set the saved
666 	 * uid when the real uid is specified and either its value would
667 	 * change, or where the saved and effective uids are different.
668 	 */
669 	if (ruid != (uid_t)-1 && (ruid != pruc->cr_ruid ||
670 	    pruc->cr_svuid != (euid != (uid_t)-1 ? euid : pruc->cr_uid)))
671 		newcred->cr_svuid = ruid;
672 	pr->ps_ucred = newcred;
673 	atomic_setbits_int(&p->p_p->ps_flags, PS_SUGID);
674 
675 	/* now that we can sleep, transfer proc count to new user */
676 	if (ruid != (uid_t)-1 && ruid != pruc->cr_ruid) {
677 		chgproccnt(pruc->cr_ruid, -1);
678 		chgproccnt(ruid, 1);
679 	}
680 	crfree(pruc);
681 
682 	return (0);
683 }
684 
685 int
686 sys_setuid(struct proc *p, void *v, register_t *retval)
687 {
688 	struct sys_setuid_args /* {
689 		syscallarg(uid_t) uid;
690 	} */ *uap = v;
691 	struct process *pr = p->p_p;
692 	struct ucred *pruc, *newcred, *uc = p->p_ucred;
693 	uid_t uid;
694 	int did_real, error;
695 
696 	uid = SCARG(uap, uid);
697 
698 	pruc = pr->ps_ucred;
699 	if (pruc->cr_uid == uid &&
700 	    pruc->cr_ruid == uid &&
701 	    pruc->cr_svuid == uid)
702 		return (0);
703 
704 	if (uid != uc->cr_ruid &&
705 	    uid != uc->cr_svuid &&
706 	    uid != uc->cr_uid &&
707 	    (error = suser(p, 0)))
708 		return (error);
709 
710 	/*
711 	 * Copy credentials so other references do not see our changes.
712 	 * ps_ucred may change during the crget().
713 	 */
714 	newcred = crget();
715 	pruc = pr->ps_ucred;
716 	crset(newcred, pruc);
717 
718 	/*
719 	 * Everything's okay, do it.
720 	 */
721 	if (uid == pruc->cr_uid || suser(p, 0) == 0) {
722 		did_real = 1;
723 		newcred->cr_ruid = uid;
724 		newcred->cr_svuid = uid;
725 	} else
726 		did_real = 0;
727 	newcred->cr_uid = uid;
728 	pr->ps_ucred = newcred;
729 	atomic_setbits_int(&p->p_p->ps_flags, PS_SUGID);
730 
731 	/*
732 	 * Transfer proc count to new user.
733 	 */
734 	if (did_real && uid != pruc->cr_ruid) {
735 		chgproccnt(pruc->cr_ruid, -1);
736 		chgproccnt(uid, 1);
737 	}
738 	crfree(pruc);
739 
740 	return (0);
741 }
742 
743 int
744 sys_seteuid(struct proc *p, void *v, register_t *retval)
745 {
746 	struct sys_seteuid_args /* {
747 		syscallarg(uid_t) euid;
748 	} */ *uap = v;
749 	struct process *pr = p->p_p;
750 	struct ucred *pruc, *newcred, *uc = p->p_ucred;
751 	uid_t euid;
752 	int error;
753 
754 	euid = SCARG(uap, euid);
755 
756 	if (pr->ps_ucred->cr_uid == euid)
757 		return (0);
758 
759 	if (euid != uc->cr_ruid && euid != uc->cr_svuid &&
760 	    (error = suser(p, 0)))
761 		return (error);
762 
763 	/*
764 	 * Copy credentials so other references do not see our changes.
765 	 * ps_ucred may change during the crget().
766 	 */
767 	newcred = crget();
768 	pruc = pr->ps_ucred;
769 	crset(newcred, pruc);
770 	newcred->cr_uid = euid;
771 	pr->ps_ucred = newcred;
772 	atomic_setbits_int(&p->p_p->ps_flags, PS_SUGID);
773 	crfree(pruc);
774 	return (0);
775 }
776 
777 int
778 sys_setgid(struct proc *p, void *v, register_t *retval)
779 {
780 	struct sys_setgid_args /* {
781 		syscallarg(gid_t) gid;
782 	} */ *uap = v;
783 	struct process *pr = p->p_p;
784 	struct ucred *pruc, *newcred, *uc = p->p_ucred;
785 	gid_t gid;
786 	int error;
787 
788 	gid = SCARG(uap, gid);
789 
790 	pruc = pr->ps_ucred;
791 	if (pruc->cr_gid == gid &&
792 	    pruc->cr_rgid == gid &&
793 	    pruc->cr_svgid == gid)
794 		return (0);
795 
796 	if (gid != uc->cr_rgid &&
797 	    gid != uc->cr_svgid &&
798 	    gid != uc->cr_gid &&
799 	    (error = suser(p, 0)))
800 		return (error);
801 
802 	/*
803 	 * Copy credentials so other references do not see our changes.
804 	 * ps_ucred may change during the crget().
805 	 */
806 	newcred = crget();
807 	pruc = pr->ps_ucred;
808 	crset(newcred, pruc);
809 
810 	if (gid == pruc->cr_gid || suser(p, 0) == 0) {
811 		newcred->cr_rgid = gid;
812 		newcred->cr_svgid = gid;
813 	}
814 	newcred->cr_gid = gid;
815 	pr->ps_ucred = newcred;
816 	atomic_setbits_int(&p->p_p->ps_flags, PS_SUGID);
817 	crfree(pruc);
818 	return (0);
819 }
820 
821 int
822 sys_setegid(struct proc *p, void *v, register_t *retval)
823 {
824 	struct sys_setegid_args /* {
825 		syscallarg(gid_t) egid;
826 	} */ *uap = v;
827 	struct process *pr = p->p_p;
828 	struct ucred *pruc, *newcred, *uc = p->p_ucred;
829 	gid_t egid;
830 	int error;
831 
832 	egid = SCARG(uap, egid);
833 
834 	if (pr->ps_ucred->cr_gid == egid)
835 		return (0);
836 
837 	if (egid != uc->cr_rgid && egid != uc->cr_svgid &&
838 	    (error = suser(p, 0)))
839 		return (error);
840 
841 	/*
842 	 * Copy credentials so other references do not see our changes.
843 	 * ps_ucred may change during the crget().
844 	 */
845 	newcred = crget();
846 	pruc = pr->ps_ucred;
847 	crset(newcred, pruc);
848 	newcred->cr_gid = egid;
849 	pr->ps_ucred = newcred;
850 	atomic_setbits_int(&p->p_p->ps_flags, PS_SUGID);
851 	crfree(pruc);
852 	return (0);
853 }
854 
855 int
856 sys_setgroups(struct proc *p, void *v, register_t *retval)
857 {
858 	struct sys_setgroups_args /* {
859 		syscallarg(int) gidsetsize;
860 		syscallarg(const gid_t *) gidset;
861 	} */ *uap = v;
862 	struct process *pr = p->p_p;
863 	struct ucred *pruc, *newcred;
864 	gid_t groups[NGROUPS_MAX];
865 	u_int ngrp;
866 	int error;
867 
868 	if ((error = suser(p, 0)) != 0)
869 		return (error);
870 	ngrp = SCARG(uap, gidsetsize);
871 	if (ngrp > NGROUPS_MAX)
872 		return (EINVAL);
873 	error = copyin(SCARG(uap, gidset), groups, ngrp * sizeof(gid_t));
874 	if (error == 0) {
875 		newcred = crget();
876 		pruc = pr->ps_ucred;
877 		crset(newcred, pruc);
878 		memcpy(newcred->cr_groups, groups, ngrp * sizeof(gid_t));
879 		newcred->cr_ngroups = ngrp;
880 		pr->ps_ucred = newcred;
881 		atomic_setbits_int(&p->p_p->ps_flags, PS_SUGID);
882 		crfree(pruc);
883 	}
884 	return (error);
885 }
886 
887 /*
888  * Check if gid is a member of the group set.
889  */
890 int
891 groupmember(gid_t gid, struct ucred *cred)
892 {
893 	gid_t *gp;
894 	gid_t *egp;
895 
896 	if (cred->cr_gid == gid)
897 		return (1);
898 	egp = &(cred->cr_groups[cred->cr_ngroups]);
899 	for (gp = cred->cr_groups; gp < egp; gp++)
900 		if (*gp == gid)
901 			return (1);
902 	return (0);
903 }
904 
905 /*
906  * Test whether this process has special user powers.
907  * Returns 0 or error.
908  */
909 int
910 suser(struct proc *p, u_int flags)
911 {
912 	struct ucred *cred = p->p_ucred;
913 
914 	if (cred->cr_uid == 0) {
915 		if (!(flags & SUSER_NOACCT))
916 			p->p_p->ps_acflag |= ASU;
917 		return (0);
918 	}
919 	return (EPERM);
920 }
921 
922 /*
923  * replacement for old suser, for callers who don't have a process
924  */
925 int
926 suser_ucred(struct ucred *cred)
927 {
928 	if (cred->cr_uid == 0)
929 		return (0);
930 	return (EPERM);
931 }
932 
933 /*
934  * Allocate a zeroed cred structure.
935  */
936 struct ucred *
937 crget(void)
938 {
939 	struct ucred *cr;
940 
941 	cr = pool_get(&ucred_pool, PR_WAITOK|PR_ZERO);
942 	cr->cr_ref = 1;
943 	return (cr);
944 }
945 
946 /*
947  * Free a cred structure.
948  * Throws away space when ref count gets to 0.
949  */
950 void
951 crfree(struct ucred *cr)
952 {
953 
954 	if (--cr->cr_ref == 0)
955 		pool_put(&ucred_pool, cr);
956 }
957 
958 /*
959  * Copy cred structure to a new one and free the old one.
960  */
961 struct ucred *
962 crcopy(struct ucred *cr)
963 {
964 	struct ucred *newcr;
965 
966 	if (cr->cr_ref == 1)
967 		return (cr);
968 	newcr = crget();
969 	*newcr = *cr;
970 	crfree(cr);
971 	newcr->cr_ref = 1;
972 	return (newcr);
973 }
974 
975 /*
976  * Dup cred struct to a new held one.
977  */
978 struct ucred *
979 crdup(struct ucred *cr)
980 {
981 	struct ucred *newcr;
982 
983 	newcr = crget();
984 	*newcr = *cr;
985 	newcr->cr_ref = 1;
986 	return (newcr);
987 }
988 
989 /*
990  * Convert the userspace xucred to a kernel ucred
991  */
992 int
993 crfromxucred(struct ucred *cr, const struct xucred *xcr)
994 {
995 	if (xcr->cr_ngroups < 0 || xcr->cr_ngroups > NGROUPS_MAX)
996 		return (EINVAL);
997 	cr->cr_ref = 1;
998 	cr->cr_uid = xcr->cr_uid;
999 	cr->cr_gid = xcr->cr_gid;
1000 	cr->cr_ngroups = xcr->cr_ngroups;
1001 	memcpy(cr->cr_groups, xcr->cr_groups,
1002 	    sizeof(cr->cr_groups[0]) * xcr->cr_ngroups);
1003 	return (0);
1004 }
1005 
1006 /*
1007  * Get login name, if available.
1008  */
1009 int
1010 sys_getlogin59(struct proc *p, void *v, register_t *retval)
1011 {
1012 	struct sys_getlogin59_args /* {
1013 		syscallarg(char *) namebuf;
1014 		syscallarg(u_int) namelen;
1015 	} */ *uap = v;
1016 	struct session *s = p->p_p->ps_pgrp->pg_session;
1017 
1018 	if (SCARG(uap, namelen) > sizeof(s->s_login))
1019 		SCARG(uap, namelen) = sizeof(s->s_login);
1020 	return (copyout((caddr_t)s->s_login,
1021 	    (caddr_t)SCARG(uap, namebuf), SCARG(uap, namelen)));
1022 }
1023 
1024 /*
1025  * Get login name, if available.
1026  */
1027 int
1028 sys_getlogin_r(struct proc *p, void *v, register_t *retval)
1029 {
1030 	struct sys_getlogin_r_args /* {
1031 		syscallarg(char *) namebuf;
1032 		syscallarg(size_t) namelen;
1033 	} */ *uap = v;
1034 	size_t namelen = SCARG(uap, namelen);
1035 	struct session *s = p->p_p->ps_pgrp->pg_session;
1036 	int error;
1037 
1038 	if (namelen > sizeof(s->s_login))
1039 		namelen = sizeof(s->s_login);
1040 	error = copyoutstr(s->s_login, SCARG(uap, namebuf), namelen, NULL);
1041 	if (error == ENAMETOOLONG)
1042 		error = ERANGE;
1043 	*retval = error;
1044 	return (0);
1045 }
1046 
1047 /*
1048  * Set login name.
1049  */
1050 int
1051 sys_setlogin(struct proc *p, void *v, register_t *retval)
1052 {
1053 	struct sys_setlogin_args /* {
1054 		syscallarg(const char *) namebuf;
1055 	} */ *uap = v;
1056 	struct session *s = p->p_p->ps_pgrp->pg_session;
1057 	char buf[sizeof(s->s_login)];
1058 	int error;
1059 
1060 	if ((error = suser(p, 0)) != 0)
1061 		return (error);
1062 	error = copyinstr(SCARG(uap, namebuf), buf, sizeof(buf), NULL);
1063 	if (error == 0)
1064 		strlcpy(s->s_login, buf, sizeof(s->s_login));
1065 	else if (error == ENAMETOOLONG)
1066 		error = EINVAL;
1067 	return (error);
1068 }
1069 
1070 /*
1071  * Check if a process is allowed to raise its privileges.
1072  */
1073 int
1074 proc_cansugid(struct proc *p)
1075 {
1076 	/* ptrace(2)d processes shouldn't. */
1077 	if ((p->p_p->ps_flags & PS_TRACED) != 0)
1078 		return (0);
1079 
1080 	/* processes with shared filedescriptors shouldn't. */
1081 	if (p->p_fd->fd_refcnt > 1)
1082 		return (0);
1083 
1084 	/* Allow. */
1085 	return (1);
1086 }
1087 
1088 /*
1089  * Set address of the proc's thread-control-block
1090  */
1091 int
1092 sys___set_tcb(struct proc *p, void *v, register_t *retval)
1093 {
1094 	struct sys___set_tcb_args /* {
1095 		syscallarg(void *) tcb;
1096 	} */ *uap = v;
1097 
1098 	TCB_SET(p, SCARG(uap, tcb));
1099 	return (0);
1100 }
1101 
1102 /*
1103  * Get address of the proc's thread-control-block
1104  */
1105 int
1106 sys___get_tcb(struct proc *p, void *v, register_t *retval)
1107 {
1108 	*retval = (register_t)TCB_GET(p);
1109 	return (0);
1110 }
1111 
1112 /*
1113  * Refresh the thread's reference to the process's credentials
1114  */
1115 void
1116 dorefreshcreds(struct process *pr, struct proc *p)
1117 {
1118 	struct ucred *uc = p->p_ucred;
1119 
1120 	KERNEL_LOCK();		/* XXX should be PROCESS_RLOCK(pr) */
1121 	if (uc != pr->ps_ucred) {
1122 		p->p_ucred = pr->ps_ucred;
1123 		crhold(p->p_ucred);
1124 		crfree(uc);
1125 	}
1126 	KERNEL_UNLOCK();
1127 }
1128