kernel tree reorganization stage 1: Major cvs repository work (not logged as
[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.9 2003/07/30 00:19:14 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->cr_svuid = uid;
368                         setsugid();
369                 }
370         }
371
372         /*
373          * In all permitted cases, we are changing the euid.
374          * Copy credentials so other references do not see our changes.
375          */
376         if (cr->cr_uid != uid) {
377                 change_euid(uid);
378                 setsugid();
379         }
380         return (0);
381 }
382
383 /* ARGSUSED */
384 int
385 seteuid(struct seteuid_args *uap)
386 {
387         struct proc *p = curproc;
388         struct ucred *cr;
389         uid_t euid;
390         int error;
391
392         if (p == NULL)                          /* API enforcement */
393                 return(EPERM);
394
395         cr = p->p_ucred;
396         euid = uap->euid;
397         if (euid != cr->cr_ruid &&              /* allow seteuid(getuid()) */
398             euid != cr->cr_svuid &&             /* allow seteuid(saved uid) */
399             (error = suser_cred(cr, PRISON_ROOT)))
400                 return (error);
401         /*
402          * Everything's okay, do it.  Copy credentials so other references do
403          * not see our changes.
404          */
405         if (cr->cr_uid != euid) {
406                 change_euid(euid);
407                 setsugid();
408         }
409         return (0);
410 }
411
412 /* ARGSUSED */
413 int
414 setgid(struct setgid_args *uap)
415 {
416         struct proc *p = curproc;
417         struct ucred *cr;
418         gid_t gid;
419         int error;
420
421         if (p == NULL)                          /* API enforcement */
422                 return(EPERM);
423         cr = p->p_ucred;
424
425         /*
426          * See if we have "permission" by POSIX 1003.1 rules.
427          *
428          * Note that setgid(getegid()) is a special case of
429          * "appropriate privileges" in appendix B.4.2.2.  We need
430          * to use this clause to be compatable with traditional BSD
431          * semantics.  Basically, it means that "setgid(xx)" sets all
432          * three id's (assuming you have privs).
433          *
434          * For notes on the logic here, see setuid() above.
435          */
436         gid = uap->gid;
437         if (gid != cr->cr_rgid &&               /* allow setgid(getgid()) */
438 #ifdef _POSIX_SAVED_IDS
439             gid != cr->cr_svgid &&              /* allow setgid(saved gid) */
440 #endif
441 #ifdef POSIX_APPENDIX_B_4_2_2   /* Use BSD-compat clause from B.4.2.2 */
442             gid != cr->cr_groups[0] && /* allow setgid(getegid()) */
443 #endif
444             (error = suser_cred(cr, PRISON_ROOT)))
445                 return (error);
446
447 #ifdef _POSIX_SAVED_IDS
448         /*
449          * Do we have "appropriate privileges" (are we root or gid == egid)
450          * If so, we are changing the real uid and saved gid.
451          */
452         if (
453 #ifdef POSIX_APPENDIX_B_4_2_2   /* use the clause from B.4.2.2 */
454             gid == cr->cr_groups[0] ||
455 #endif
456             suser_cred(cr, PRISON_ROOT) == 0) /* we are using privs */
457 #endif
458         {
459                 /*
460                  * Set real gid
461                  */
462                 if (cr->cr_rgid != gid) {
463                         cr->cr_rgid = gid;
464                         setsugid();
465                 }
466                 /*
467                  * Set saved gid
468                  *
469                  * XXX always set saved gid even if not _POSIX_SAVED_IDS, as
470                  * the security of setegid() depends on it.  B.4.2.2 says it
471                  * is important that we should do this.
472                  */
473                 if (cr->cr_svgid != gid) {
474                         cr->cr_svgid = gid;
475                         setsugid();
476                 }
477         }
478         /*
479          * In all cases permitted cases, we are changing the egid.
480          * Copy credentials so other references do not see our changes.
481          */
482         if (cr->cr_groups[0] != gid) {
483                 cr = cratom(&p->p_ucred);
484                 cr->cr_groups[0] = gid;
485                 setsugid();
486         }
487         return (0);
488 }
489
490 /* ARGSUSED */
491 int
492 setegid(struct setegid_args *uap)
493 {
494         struct proc *p = curproc;
495         struct ucred *cr;
496         gid_t egid;
497         int error;
498
499         if (p == NULL)                          /* API enforcement */
500                 return(EPERM);
501         cr = p->p_ucred;
502
503         egid = uap->egid;
504         if (egid != cr->cr_rgid &&              /* allow setegid(getgid()) */
505             egid != cr->cr_svgid &&             /* allow setegid(saved gid) */
506             (error = suser_cred(cr, PRISON_ROOT)))
507                 return (error);
508         if (cr->cr_groups[0] != egid) {
509                 cr = cratom(&p->p_ucred);
510                 cr->cr_groups[0] = egid;
511                 setsugid();
512         }
513         return (0);
514 }
515
516 /* ARGSUSED */
517 int
518 setgroups(struct setgroups_args *uap)
519 {
520         struct proc *p = curproc;
521         struct ucred *cr;
522         u_int ngrp;
523         int error;
524
525         if (p == NULL)                          /* API enforcement */
526                 return(EPERM);
527         cr = p->p_ucred;
528
529         if ((error = suser_cred(cr, PRISON_ROOT)))
530                 return (error);
531         ngrp = uap->gidsetsize;
532         if (ngrp > NGROUPS)
533                 return (EINVAL);
534         /*
535          * XXX A little bit lazy here.  We could test if anything has
536          * changed before cratom() and setting P_SUGID.
537          */
538         cr = cratom(&p->p_ucred);
539         if (ngrp < 1) {
540                 /*
541                  * setgroups(0, NULL) is a legitimate way of clearing the
542                  * groups vector on non-BSD systems (which generally do not
543                  * have the egid in the groups[0]).  We risk security holes
544                  * when running non-BSD software if we do not do the same.
545                  */
546                 cr->cr_ngroups = 1;
547         } else {
548                 if ((error = copyin((caddr_t)uap->gidset,
549                     (caddr_t)cr->cr_groups, ngrp * sizeof(gid_t))))
550                         return (error);
551                 cr->cr_ngroups = ngrp;
552         }
553         setsugid();
554         return (0);
555 }
556
557 /* ARGSUSED */
558 int
559 setreuid(struct setreuid_args *uap)
560 {
561         struct proc *p = curproc;
562         struct ucred *cr;
563         uid_t ruid, euid;
564         int error;
565
566         if (p == NULL)                          /* API enforcement */
567                 return(EPERM);
568         cr = p->p_ucred;
569
570         ruid = uap->ruid;
571         euid = uap->euid;
572         if (((ruid != (uid_t)-1 && ruid != cr->cr_ruid && ruid != cr->cr_svuid) ||
573              (euid != (uid_t)-1 && euid != cr->cr_uid &&
574              euid != cr->cr_ruid && euid != cr->cr_svuid)) &&
575             (error = suser_cred(cr, PRISON_ROOT)) != 0)
576                 return (error);
577
578         if (euid != (uid_t)-1 && cr->cr_uid != euid) {
579                 change_euid(euid);
580                 setsugid();
581         }
582         if (ruid != (uid_t)-1 && cr->cr_ruid != ruid) {
583                 change_ruid(ruid);
584                 setsugid();
585         }
586         if ((ruid != (uid_t)-1 || cr->cr_uid != cr->cr_ruid) &&
587             cr->cr_svuid != cr->cr_uid) {
588                 cr = cratom(&p->p_ucred);
589                 cr->cr_svuid = cr->cr_uid;
590                 setsugid();
591         }
592         return (0);
593 }
594
595 /* ARGSUSED */
596 int
597 setregid(struct setregid_args *uap)
598 {
599         struct proc *p = curproc;
600         struct ucred *cr;
601         gid_t rgid, egid;
602         int error;
603
604         if (p == NULL)                          /* API enforcement */
605                 return(EPERM);
606         cr = p->p_ucred;
607
608         rgid = uap->rgid;
609         egid = uap->egid;
610         if (((rgid != (gid_t)-1 && rgid != cr->cr_rgid && rgid != cr->cr_svgid) ||
611              (egid != (gid_t)-1 && egid != cr->cr_groups[0] &&
612              egid != cr->cr_rgid && egid != cr->cr_svgid)) &&
613             (error = suser_cred(cr, PRISON_ROOT)) != 0)
614                 return (error);
615
616         if (egid != (gid_t)-1 && cr->cr_groups[0] != egid) {
617                 cr = cratom(&p->p_ucred);
618                 cr->cr_groups[0] = egid;
619                 setsugid();
620         }
621         if (rgid != (gid_t)-1 && cr->cr_rgid != rgid) {
622                 cr = cratom(&p->p_ucred);
623                 cr->cr_rgid = rgid;
624                 setsugid();
625         }
626         if ((rgid != (gid_t)-1 || cr->cr_groups[0] != cr->cr_rgid) &&
627             cr->cr_svgid != cr->cr_groups[0]) {
628                 cr = cratom(&p->p_ucred);
629                 cr->cr_svgid = cr->cr_groups[0];
630                 setsugid();
631         }
632         return (0);
633 }
634
635 /*
636  * setresuid(ruid, euid, suid) is like setreuid except control over the
637  * saved uid is explicit.
638  */
639
640 /* ARGSUSED */
641 int
642 setresuid(struct setresuid_args *uap)
643 {
644         struct proc *p = curproc;
645         struct ucred *cr;
646         uid_t ruid, euid, suid;
647         int error;
648
649         cr = p->p_ucred;
650         ruid = uap->ruid;
651         euid = uap->euid;
652         suid = uap->suid;
653         if (((ruid != (uid_t)-1 && ruid != cr->cr_ruid && ruid != cr->cr_svuid &&
654               ruid != cr->cr_uid) ||
655              (euid != (uid_t)-1 && euid != cr->cr_ruid && euid != cr->cr_svuid &&
656               euid != cr->cr_uid) ||
657              (suid != (uid_t)-1 && suid != cr->cr_ruid && suid != cr->cr_svuid &&
658               suid != cr->cr_uid)) &&
659             (error = suser_cred(cr, PRISON_ROOT)) != 0)
660                 return (error);
661         if (euid != (uid_t)-1 && cr->cr_uid != euid) {
662                 change_euid(euid);
663                 setsugid();
664         }
665         if (ruid != (uid_t)-1 && cr->cr_ruid != ruid) {
666                 change_ruid(ruid);
667                 setsugid();
668         }
669         if (suid != (uid_t)-1 && cr->cr_svuid != suid) {
670                 cr = cratom(&p->p_ucred);
671                 cr->cr_svuid = suid;
672                 setsugid();
673         }
674         return (0);
675 }
676
677 /*
678  * setresgid(rgid, egid, sgid) is like setregid except control over the
679  * saved gid is explicit.
680  */
681
682 /* ARGSUSED */
683 int
684 setresgid(struct setresgid_args *uap)
685 {
686         struct proc *p = curproc;
687         struct ucred *cr;
688         gid_t rgid, egid, sgid;
689         int error;
690
691         cr = p->p_ucred;
692         rgid = uap->rgid;
693         egid = uap->egid;
694         sgid = uap->sgid;
695         if (((rgid != (gid_t)-1 && rgid != cr->cr_rgid && rgid != cr->cr_svgid &&
696               rgid != cr->cr_groups[0]) ||
697              (egid != (gid_t)-1 && egid != cr->cr_rgid && egid != cr->cr_svgid &&
698               egid != cr->cr_groups[0]) ||
699              (sgid != (gid_t)-1 && sgid != cr->cr_rgid && sgid != cr->cr_svgid &&
700               sgid != cr->cr_groups[0])) &&
701             (error = suser_cred(cr, PRISON_ROOT)) != 0)
702                 return (error);
703
704         if (egid != (gid_t)-1 && cr->cr_groups[0] != egid) {
705                 cr = cratom(&p->p_ucred);
706                 cr->cr_groups[0] = egid;
707                 setsugid();
708         }
709         if (rgid != (gid_t)-1 && cr->cr_rgid != rgid) {
710                 cr = cratom(&p->p_ucred);
711                 cr->cr_rgid = rgid;
712                 setsugid();
713         }
714         if (sgid != (gid_t)-1 && cr->cr_svgid != sgid) {
715                 cr = cratom(&p->p_ucred);
716                 cr->cr_svgid = sgid;
717                 setsugid();
718         }
719         return (0);
720 }
721
722 /* ARGSUSED */
723 int
724 getresuid(struct getresuid_args *uap)
725 {
726         struct proc *p = curproc;
727         struct ucred *cr = p->p_ucred;
728         int error1 = 0, error2 = 0, error3 = 0;
729
730         if (uap->ruid)
731                 error1 = copyout((caddr_t)&cr->cr_ruid,
732                     (caddr_t)uap->ruid, sizeof(cr->cr_ruid));
733         if (uap->euid)
734                 error2 = copyout((caddr_t)&cr->cr_uid,
735                     (caddr_t)uap->euid, sizeof(cr->cr_uid));
736         if (uap->suid)
737                 error3 = copyout((caddr_t)&cr->cr_svuid,
738                     (caddr_t)uap->suid, sizeof(cr->cr_svuid));
739         return error1 ? error1 : (error2 ? error2 : error3);
740 }
741
742 /* ARGSUSED */
743 int
744 getresgid(struct getresgid_args *uap)
745 {
746         struct proc *p = curproc;
747         struct ucred *cr = p->p_ucred;
748         int error1 = 0, error2 = 0, error3 = 0;
749
750         if (uap->rgid)
751                 error1 = copyout((caddr_t)&cr->cr_rgid,
752                     (caddr_t)uap->rgid, sizeof(cr->cr_rgid));
753         if (uap->egid)
754                 error2 = copyout((caddr_t)&cr->cr_groups[0],
755                     (caddr_t)uap->egid, sizeof(cr->cr_groups[0]));
756         if (uap->sgid)
757                 error3 = copyout((caddr_t)&cr->cr_svgid,
758                     (caddr_t)uap->sgid, sizeof(cr->cr_svgid));
759         return error1 ? error1 : (error2 ? error2 : error3);
760 }
761
762
763 /* ARGSUSED */
764 int
765 issetugid(struct issetugid_args *uap)
766 {
767         struct proc *p = curproc;
768         /*
769          * Note: OpenBSD sets a P_SUGIDEXEC flag set at execve() time,
770          * we use P_SUGID because we consider changing the owners as
771          * "tainting" as well.
772          * This is significant for procs that start as root and "become"
773          * a user without an exec - programs cannot know *everything*
774          * that libc *might* have put in their data segment.
775          */
776         uap->sysmsg_result = (p->p_flag & P_SUGID) ? 1 : 0;
777         return (0);
778 }
779
780 /*
781  * Check if gid is a member of the group set.
782  */
783 int
784 groupmember(gid_t gid, struct ucred *cred)
785 {
786         gid_t *gp;
787         gid_t *egp;
788
789         egp = &(cred->cr_groups[cred->cr_ngroups]);
790         for (gp = cred->cr_groups; gp < egp; gp++)
791                 if (*gp == gid)
792                         return (1);
793         return (0);
794 }
795
796 /*
797  * Test whether the specified credentials imply "super-user"
798  * privilege; if so, and we have accounting info, set the flag
799  * indicating use of super-powers.  A kernel thread without a process
800  * context is assumed to have super user capabilities.  In situations
801  * where the caller always expect a cred to exist, the cred should be
802  * passed separately and suser_cred()should be used instead of suser().
803  *
804  * Returns 0 or error.
805  */
806 int
807 suser(struct thread *td)
808 {
809         struct proc *p = td->td_proc;
810
811         if (p != NULL) {
812                 return suser_cred(p->p_ucred, 0);
813         } else {
814                 return (0);
815         }
816 }
817
818 int
819 suser_cred(struct ucred *cred, int flag)
820 {
821         KASSERT(cred != NULL, ("suser_cred: NULL cred!"));
822
823         if (cred->cr_uid != 0) 
824                 return (EPERM);
825         if (cred->cr_prison && !(flag & PRISON_ROOT))
826                 return (EPERM);
827         /* NOTE: accounting for suser access (p_acflag/ASU) removed */
828         return (0);
829 }
830
831 /*
832  * Return zero if p1 can fondle p2, return errno (EPERM/ESRCH) otherwise.
833  */
834 int
835 p_trespass(struct ucred *cr1, struct ucred *cr2)
836 {
837         if (cr1 == cr2)
838                 return (0);
839         if (!PRISON_CHECK(cr1, cr2))
840                 return (ESRCH);
841         if (cr1->cr_ruid == cr2->cr_ruid)
842                 return (0);
843         if (cr1->cr_uid == cr2->cr_ruid)
844                 return (0);
845         if (cr1->cr_ruid == cr2->cr_uid)
846                 return (0);
847         if (cr1->cr_uid == cr2->cr_uid)
848                 return (0);
849         if (suser_cred(cr1, PRISON_ROOT) == 0)
850                 return (0);
851         return (EPERM);
852 }
853
854 /*
855  * Allocate a zeroed cred structure.
856  */
857 struct ucred *
858 crget()
859 {
860         struct ucred *cr;
861
862         MALLOC(cr, struct ucred *, sizeof(*cr), M_CRED, M_WAITOK);
863         bzero((caddr_t)cr, sizeof(*cr));
864         cr->cr_ref = 1;
865         return (cr);
866 }
867
868 /*
869  * Claim another reference to a ucred structure.  Can be used with special
870  * creds.
871  */
872 struct ucred *
873 crhold(struct ucred *cr)
874 {
875         if (cr != NOCRED && cr != FSCRED)
876                 cr->cr_ref++;
877         return(cr);
878 }
879
880 /*
881  * Free a cred structure.
882  * Throws away space when ref count gets to 0.
883  */
884 void
885 crfree(struct ucred *cr)
886 {
887         if (cr->cr_ref == 0)
888                 panic("Freeing already free credential! %p", cr);
889         
890         if (--cr->cr_ref == 0) {
891                 /*
892                  * Some callers of crget(), such as nfs_statfs(),
893                  * allocate a temporary credential, but don't
894                  * allocate a uidinfo structure.
895                  */
896                 if (cr->cr_uidinfo != NULL)
897                         uifree(cr->cr_uidinfo);
898                 if (cr->cr_ruidinfo != NULL)
899                         uifree(cr->cr_ruidinfo);
900
901                 /*
902                  * Destroy empty prisons
903                  */
904                 if (cr->cr_prison && !--cr->cr_prison->pr_ref) {
905                         if (cr->cr_prison->pr_linux != NULL)
906                                 FREE(cr->cr_prison->pr_linux, M_PRISON);
907                         FREE(cr->cr_prison, M_PRISON);
908                 }
909                 cr->cr_prison = NULL;   /* safety */
910
911                 FREE((caddr_t)cr, M_CRED);
912         }
913 }
914
915 /*
916  * Atomize a cred structure so it can be modified without polluting
917  * other references to it.
918  */
919 struct ucred *
920 cratom(struct ucred **pcr)
921 {
922         struct ucred *oldcr;
923         struct ucred *newcr;
924
925         oldcr = *pcr;
926         if (oldcr->cr_ref == 1)
927                 return (oldcr);
928         newcr = crget();
929         *newcr = *oldcr;
930         if (newcr->cr_uidinfo)
931                 uihold(newcr->cr_uidinfo);
932         if (newcr->cr_ruidinfo)
933                 uihold(newcr->cr_ruidinfo);
934         if (newcr->cr_prison)
935                 ++newcr->cr_prison->pr_ref;
936         newcr->cr_ref = 1;
937         crfree(oldcr);
938         *pcr = newcr;
939         return (newcr);
940 }
941
942 #if 0   /* no longer used but keep around for a little while */
943 /*
944  * Copy cred structure to a new one and free the old one.
945  */
946 struct ucred *
947 crcopy(struct ucred *cr)
948 {
949         struct ucred *newcr;
950
951         if (cr->cr_ref == 1)
952                 return (cr);
953         newcr = crget();
954         *newcr = *cr;
955         if (newcr->cr_uidinfo)
956                 uihold(newcr->cr_uidinfo);
957         if (newcr->cr_ruidinfo)
958                 uihold(newcr->cr_ruidinfo);
959         if (newcr->cr_prison)
960                 ++newcr->cr_prison->pr_ref;
961         newcr->cr_ref = 1;
962         crfree(cr);
963         return (newcr);
964 }
965 #endif
966
967 /*
968  * Dup cred struct to a new held one.
969  */
970 struct ucred *
971 crdup(cr)
972         struct ucred *cr;
973 {
974         struct ucred *newcr;
975
976         newcr = crget();
977         *newcr = *cr;
978         if (newcr->cr_uidinfo)
979                 uihold(newcr->cr_uidinfo);
980         if (newcr->cr_ruidinfo)
981                 uihold(newcr->cr_ruidinfo);
982         if (newcr->cr_prison)
983                 ++newcr->cr_prison->pr_ref;
984         newcr->cr_ref = 1;
985         return (newcr);
986 }
987
988 /*
989  * Fill in a struct xucred based on a struct ucred.
990  */
991 void
992 cru2x(cr, xcr)
993         struct ucred *cr;
994         struct xucred *xcr;
995 {
996
997         bzero(xcr, sizeof(*xcr));
998         xcr->cr_version = XUCRED_VERSION;
999         xcr->cr_uid = cr->cr_uid;
1000         xcr->cr_ngroups = cr->cr_ngroups;
1001         bcopy(cr->cr_groups, xcr->cr_groups, sizeof(cr->cr_groups));
1002 }
1003
1004 /*
1005  * Get login name, if available.
1006  */
1007 /* ARGSUSED */
1008 int
1009 getlogin(struct getlogin_args *uap)
1010 {
1011         struct proc *p = curproc;
1012
1013         if (uap->namelen > MAXLOGNAME)
1014                 uap->namelen = MAXLOGNAME;
1015         return (copyout((caddr_t) p->p_pgrp->pg_session->s_login,
1016             (caddr_t) uap->namebuf, uap->namelen));
1017 }
1018
1019 /*
1020  * Set login name.
1021  */
1022 /* ARGSUSED */
1023 int
1024 setlogin(struct setlogin_args *uap)
1025 {
1026         struct proc *p = curproc;
1027         int error;
1028         char logintmp[MAXLOGNAME];
1029
1030         KKASSERT(p != NULL);
1031         if ((error = suser_cred(p->p_ucred, PRISON_ROOT)))
1032                 return (error);
1033         error = copyinstr((caddr_t) uap->namebuf, (caddr_t) logintmp,
1034             sizeof(logintmp), (size_t *)0);
1035         if (error == ENAMETOOLONG)
1036                 error = EINVAL;
1037         else if (!error)
1038                 (void) memcpy(p->p_pgrp->pg_session->s_login, logintmp,
1039                     sizeof(logintmp));
1040         return (error);
1041 }
1042
1043 void
1044 setsugid()
1045 {
1046         struct proc *p = curproc;
1047
1048         KKASSERT(p != NULL);
1049         p->p_flag |= P_SUGID;
1050         if (!(p->p_pfsflags & PF_ISUGID))
1051                 p->p_stops = 0;
1052 }
1053
1054 /*
1055  * Helper function to change the effective uid of a process
1056  */
1057 void
1058 change_euid(uid_t euid)
1059 {
1060         struct  proc *p = curproc;
1061         struct  ucred *cr;
1062         struct  uidinfo *uip;
1063
1064         KKASSERT(p != NULL);
1065
1066         cr = cratom(&p->p_ucred);
1067         uip = cr->cr_uidinfo;
1068         cr->cr_uid = euid;
1069         cr->cr_uidinfo = uifind(euid);
1070         uifree(uip);
1071 }
1072
1073 /*
1074  * Helper function to change the real uid of a process
1075  *
1076  * The per-uid process count for this process is transfered from
1077  * the old uid to the new uid.
1078  */
1079 void
1080 change_ruid(uid_t ruid)
1081 {
1082         struct  proc *p = curproc;
1083         struct  ucred *cr;
1084         struct  uidinfo *uip;
1085
1086         KKASSERT(p != NULL);
1087
1088         cr = cratom(&p->p_ucred);
1089         (void)chgproccnt(cr->cr_ruidinfo, -1, 0);
1090         uip = cr->cr_ruidinfo;
1091         /* It is assumed that pcred is not shared between processes */
1092         cr->cr_ruid = ruid;
1093         cr->cr_ruidinfo = uifind(ruid);
1094         (void)chgproccnt(cr->cr_ruidinfo, 1, 0);
1095         uifree(uip);
1096 }