__P(); not anymore in this directory
[dragonfly.git] / 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: 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 }