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