source: rtems-libbsd/freebsd/kern/kern_prot.c @ e3501b5

4.1155-freebsd-126-freebsd-12freebsd-9.3
Last change on this file since e3501b5 was e3501b5, checked in by Sebastian Huber <sebastian.huber@…>, on 04/18/12 at 12:00:54

Add parts of the UCRED(9) implementation

  • Property mode set to 100644
File size: 51.4 KB
Line 
1#include <freebsd/machine/rtems-bsd-config.h>
2
3/*-
4 * Copyright (c) 1982, 1986, 1989, 1990, 1991, 1993
5 *      The Regents of the University of California.
6 * (c) UNIX System Laboratories, Inc.
7 * Copyright (c) 2000-2001 Robert N. M. Watson.
8 * All rights reserved.
9 *
10 * All or some portions of this file are derived from material licensed
11 * to the University of California by American Telephone and Telegraph
12 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
13 * the permission of UNIX System Laboratories, Inc.
14 *
15 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions
17 * are met:
18 * 1. Redistributions of source code must retain the above copyright
19 *    notice, this list of conditions and the following disclaimer.
20 * 2. Redistributions in binary form must reproduce the above copyright
21 *    notice, this list of conditions and the following disclaimer in the
22 *    documentation and/or other materials provided with the distribution.
23 * 4. Neither the name of the University nor the names of its contributors
24 *    may be used to endorse or promote products derived from this software
25 *    without specific prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 * SUCH DAMAGE.
38 *
39 *      @(#)kern_prot.c 8.6 (Berkeley) 1/21/94
40 */
41
42/*
43 * System calls related to processes and protection
44 */
45
46#include <freebsd/sys/cdefs.h>
47__FBSDID("$FreeBSD$");
48
49#include <freebsd/local/opt_compat.h>
50#include <freebsd/local/opt_inet.h>
51#include <freebsd/local/opt_inet6.h>
52
53#include <freebsd/sys/param.h>
54#include <freebsd/sys/systm.h>
55#ifndef __rtems__
56#include <freebsd/sys/acct.h>
57#include <freebsd/sys/kdb.h>
58#endif /* __rtems__ */
59#include <freebsd/sys/kernel.h>
60#include <freebsd/sys/lock.h>
61#include <freebsd/sys/malloc.h>
62#include <freebsd/sys/mutex.h>
63#include <freebsd/sys/refcount.h>
64#include <freebsd/sys/sx.h>
65#include <freebsd/sys/priv.h>
66#include <freebsd/sys/proc.h>
67#include <freebsd/sys/sysproto.h>
68#include <freebsd/sys/jail.h>
69#ifndef __rtems__
70#include <freebsd/sys/pioctl.h>
71#endif /* __rtems__ */
72#include <freebsd/sys/resourcevar.h>
73#include <freebsd/sys/socket.h>
74#include <freebsd/sys/socketvar.h>
75#include <freebsd/sys/syscallsubr.h>
76#include <freebsd/sys/sysctl.h>
77
78#if defined(INET) || defined(INET6)
79#include <freebsd/netinet/in.h>
80#include <freebsd/netinet/in_pcb.h>
81#endif
82
83#include <freebsd/security/audit/audit.h>
84#include <freebsd/security/mac/mac_framework.h>
85
86static MALLOC_DEFINE(M_CRED, "cred", "credentials");
87
88SYSCTL_NODE(_security, OID_AUTO, bsd, CTLFLAG_RW, 0, "BSD security policy");
89
90static void crextend(struct ucred *cr, int n);
91#ifndef __rtems__
92static void crsetgroups_locked(struct ucred *cr, int ngrp,
93    gid_t *groups);
94
95#ifndef _SYS_SYSPROTO_HH_
96struct getpid_args {
97        int     dummy;
98};
99#endif
100/* ARGSUSED */
101int
102getpid(struct thread *td, struct getpid_args *uap)
103{
104        struct proc *p = td->td_proc;
105
106        td->td_retval[0] = p->p_pid;
107#if defined(COMPAT_43)
108        PROC_LOCK(p);
109        td->td_retval[1] = p->p_pptr->p_pid;
110        PROC_UNLOCK(p);
111#endif
112        return (0);
113}
114
115#ifndef _SYS_SYSPROTO_HH_
116struct getppid_args {
117        int     dummy;
118};
119#endif
120/* ARGSUSED */
121int
122getppid(struct thread *td, struct getppid_args *uap)
123{
124        struct proc *p = td->td_proc;
125
126        PROC_LOCK(p);
127        td->td_retval[0] = p->p_pptr->p_pid;
128        PROC_UNLOCK(p);
129        return (0);
130}
131
132/*
133 * Get process group ID; note that POSIX getpgrp takes no parameter.
134 */
135#ifndef _SYS_SYSPROTO_HH_
136struct getpgrp_args {
137        int     dummy;
138};
139#endif
140int
141getpgrp(struct thread *td, struct getpgrp_args *uap)
142{
143        struct proc *p = td->td_proc;
144
145        PROC_LOCK(p);
146        td->td_retval[0] = p->p_pgrp->pg_id;
147        PROC_UNLOCK(p);
148        return (0);
149}
150
151/* Get an arbitary pid's process group id */
152#ifndef _SYS_SYSPROTO_HH_
153struct getpgid_args {
154        pid_t   pid;
155};
156#endif
157int
158getpgid(struct thread *td, struct getpgid_args *uap)
159{
160        struct proc *p;
161        int error;
162
163        if (uap->pid == 0) {
164                p = td->td_proc;
165                PROC_LOCK(p);
166        } else {
167                p = pfind(uap->pid);
168                if (p == NULL)
169                        return (ESRCH);
170                error = p_cansee(td, p);
171                if (error) {
172                        PROC_UNLOCK(p);
173                        return (error);
174                }
175        }
176        td->td_retval[0] = p->p_pgrp->pg_id;
177        PROC_UNLOCK(p);
178        return (0);
179}
180
181/*
182 * Get an arbitary pid's session id.
183 */
184#ifndef _SYS_SYSPROTO_HH_
185struct getsid_args {
186        pid_t   pid;
187};
188#endif
189int
190getsid(struct thread *td, struct getsid_args *uap)
191{
192        struct proc *p;
193        int error;
194
195        if (uap->pid == 0) {
196                p = td->td_proc;
197                PROC_LOCK(p);
198        } else {
199                p = pfind(uap->pid);
200                if (p == NULL)
201                        return (ESRCH);
202                error = p_cansee(td, p);
203                if (error) {
204                        PROC_UNLOCK(p);
205                        return (error);
206                }
207        }
208        td->td_retval[0] = p->p_session->s_sid;
209        PROC_UNLOCK(p);
210        return (0);
211}
212
213#ifndef _SYS_SYSPROTO_HH_
214struct getuid_args {
215        int     dummy;
216};
217#endif
218/* ARGSUSED */
219int
220getuid(struct thread *td, struct getuid_args *uap)
221{
222
223        td->td_retval[0] = td->td_ucred->cr_ruid;
224#if defined(COMPAT_43)
225        td->td_retval[1] = td->td_ucred->cr_uid;
226#endif
227        return (0);
228}
229
230#ifndef _SYS_SYSPROTO_HH_
231struct geteuid_args {
232        int     dummy;
233};
234#endif
235/* ARGSUSED */
236int
237geteuid(struct thread *td, struct geteuid_args *uap)
238{
239
240        td->td_retval[0] = td->td_ucred->cr_uid;
241        return (0);
242}
243
244#ifndef _SYS_SYSPROTO_HH_
245struct getgid_args {
246        int     dummy;
247};
248#endif
249/* ARGSUSED */
250int
251getgid(struct thread *td, struct getgid_args *uap)
252{
253
254        td->td_retval[0] = td->td_ucred->cr_rgid;
255#if defined(COMPAT_43)
256        td->td_retval[1] = td->td_ucred->cr_groups[0];
257#endif
258        return (0);
259}
260
261/*
262 * Get effective group ID.  The "egid" is groups[0], and could be obtained
263 * via getgroups.  This syscall exists because it is somewhat painful to do
264 * correctly in a library function.
265 */
266#ifndef _SYS_SYSPROTO_HH_
267struct getegid_args {
268        int     dummy;
269};
270#endif
271/* ARGSUSED */
272int
273getegid(struct thread *td, struct getegid_args *uap)
274{
275
276        td->td_retval[0] = td->td_ucred->cr_groups[0];
277        return (0);
278}
279
280#ifndef _SYS_SYSPROTO_HH_
281struct getgroups_args {
282        u_int   gidsetsize;
283        gid_t   *gidset;
284};
285#endif
286int
287getgroups(struct thread *td, register struct getgroups_args *uap)
288{
289        gid_t *groups;
290        u_int ngrp;
291        int error;
292
293        if (uap->gidsetsize < td->td_ucred->cr_ngroups) {
294                if (uap->gidsetsize == 0)
295                        ngrp = 0;
296                else
297                        return (EINVAL);
298        } else
299                ngrp = td->td_ucred->cr_ngroups;
300        groups = malloc(ngrp * sizeof(*groups), M_TEMP, M_WAITOK);
301        error = kern_getgroups(td, &ngrp, groups);
302        if (error)
303                goto out;
304        if (uap->gidsetsize > 0)
305                error = copyout(groups, uap->gidset, ngrp * sizeof(gid_t));
306        if (error == 0)
307                td->td_retval[0] = ngrp;
308out:
309        free(groups, M_TEMP);
310        return (error);
311}
312
313int
314kern_getgroups(struct thread *td, u_int *ngrp, gid_t *groups)
315{
316        struct ucred *cred;
317
318        cred = td->td_ucred;
319        if (*ngrp == 0) {
320                *ngrp = cred->cr_ngroups;
321                return (0);
322        }
323        if (*ngrp < cred->cr_ngroups)
324                return (EINVAL);
325        *ngrp = cred->cr_ngroups;
326        bcopy(cred->cr_groups, groups, *ngrp * sizeof(gid_t));
327        return (0);
328}
329
330#ifndef _SYS_SYSPROTO_HH_
331struct setsid_args {
332        int     dummy;
333};
334#endif
335/* ARGSUSED */
336int
337setsid(register struct thread *td, struct setsid_args *uap)
338{
339        struct pgrp *pgrp;
340        int error;
341        struct proc *p = td->td_proc;
342        struct pgrp *newpgrp;
343        struct session *newsess;
344
345        error = 0;
346        pgrp = NULL;
347
348        newpgrp = malloc(sizeof(struct pgrp), M_PGRP, M_WAITOK | M_ZERO);
349        newsess = malloc(sizeof(struct session), M_SESSION, M_WAITOK | M_ZERO);
350
351        sx_xlock(&proctree_lock);
352
353        if (p->p_pgid == p->p_pid || (pgrp = pgfind(p->p_pid)) != NULL) {
354                if (pgrp != NULL)
355                        PGRP_UNLOCK(pgrp);
356                error = EPERM;
357        } else {
358                (void)enterpgrp(p, p->p_pid, newpgrp, newsess);
359                td->td_retval[0] = p->p_pid;
360                newpgrp = NULL;
361                newsess = NULL;
362        }
363
364        sx_xunlock(&proctree_lock);
365
366        if (newpgrp != NULL)
367                free(newpgrp, M_PGRP);
368        if (newsess != NULL)
369                free(newsess, M_SESSION);
370
371        return (error);
372}
373
374/*
375 * set process group (setpgid/old setpgrp)
376 *
377 * caller does setpgid(targpid, targpgid)
378 *
379 * pid must be caller or child of caller (ESRCH)
380 * if a child
381 *      pid must be in same session (EPERM)
382 *      pid can't have done an exec (EACCES)
383 * if pgid != pid
384 *      there must exist some pid in same session having pgid (EPERM)
385 * pid must not be session leader (EPERM)
386 */
387#ifndef _SYS_SYSPROTO_HH_
388struct setpgid_args {
389        int     pid;            /* target process id */
390        int     pgid;           /* target pgrp id */
391};
392#endif
393/* ARGSUSED */
394int
395setpgid(struct thread *td, register struct setpgid_args *uap)
396{
397        struct proc *curp = td->td_proc;
398        register struct proc *targp;    /* target process */
399        register struct pgrp *pgrp;     /* target pgrp */
400        int error;
401        struct pgrp *newpgrp;
402
403        if (uap->pgid < 0)
404                return (EINVAL);
405
406        error = 0;
407
408        newpgrp = malloc(sizeof(struct pgrp), M_PGRP, M_WAITOK | M_ZERO);
409
410        sx_xlock(&proctree_lock);
411        if (uap->pid != 0 && uap->pid != curp->p_pid) {
412                if ((targp = pfind(uap->pid)) == NULL) {
413                        error = ESRCH;
414                        goto done;
415                }
416                if (!inferior(targp)) {
417                        PROC_UNLOCK(targp);
418                        error = ESRCH;
419                        goto done;
420                }
421                if ((error = p_cansee(td, targp))) {
422                        PROC_UNLOCK(targp);
423                        goto done;
424                }
425                if (targp->p_pgrp == NULL ||
426                    targp->p_session != curp->p_session) {
427                        PROC_UNLOCK(targp);
428                        error = EPERM;
429                        goto done;
430                }
431                if (targp->p_flag & P_EXEC) {
432                        PROC_UNLOCK(targp);
433                        error = EACCES;
434                        goto done;
435                }
436                PROC_UNLOCK(targp);
437        } else
438                targp = curp;
439        if (SESS_LEADER(targp)) {
440                error = EPERM;
441                goto done;
442        }
443        if (uap->pgid == 0)
444                uap->pgid = targp->p_pid;
445        if ((pgrp = pgfind(uap->pgid)) == NULL) {
446                if (uap->pgid == targp->p_pid) {
447                        error = enterpgrp(targp, uap->pgid, newpgrp,
448                            NULL);
449                        if (error == 0)
450                                newpgrp = NULL;
451                } else
452                        error = EPERM;
453        } else {
454                if (pgrp == targp->p_pgrp) {
455                        PGRP_UNLOCK(pgrp);
456                        goto done;
457                }
458                if (pgrp->pg_id != targp->p_pid &&
459                    pgrp->pg_session != curp->p_session) {
460                        PGRP_UNLOCK(pgrp);
461                        error = EPERM;
462                        goto done;
463                }
464                PGRP_UNLOCK(pgrp);
465                error = enterthispgrp(targp, pgrp);
466        }
467done:
468        sx_xunlock(&proctree_lock);
469        KASSERT((error == 0) || (newpgrp != NULL),
470            ("setpgid failed and newpgrp is NULL"));
471        if (newpgrp != NULL)
472                free(newpgrp, M_PGRP);
473        return (error);
474}
475
476/*
477 * Use the clause in B.4.2.2 that allows setuid/setgid to be 4.2/4.3BSD
478 * compatible.  It says that setting the uid/gid to euid/egid is a special
479 * case of "appropriate privilege".  Once the rules are expanded out, this
480 * basically means that setuid(nnn) sets all three id's, in all permitted
481 * cases unless _POSIX_SAVED_IDS is enabled.  In that case, setuid(getuid())
482 * does not set the saved id - this is dangerous for traditional BSD
483 * programs.  For this reason, we *really* do not want to set
484 * _POSIX_SAVED_IDS and do not want to clear POSIX_APPENDIX_B_4_2_2.
485 */
486#define POSIX_APPENDIX_B_4_2_2
487
488#ifndef _SYS_SYSPROTO_HH_
489struct setuid_args {
490        uid_t   uid;
491};
492#endif
493/* ARGSUSED */
494int
495setuid(struct thread *td, struct setuid_args *uap)
496{
497        struct proc *p = td->td_proc;
498        struct ucred *newcred, *oldcred;
499        uid_t uid;
500        struct uidinfo *uip;
501        int error;
502
503        uid = uap->uid;
504        AUDIT_ARG_UID(uid);
505        newcred = crget();
506        uip = uifind(uid);
507        PROC_LOCK(p);
508        /*
509         * Copy credentials so other references do not see our changes.
510         */
511        oldcred = crcopysafe(p, newcred);
512
513#ifdef MAC
514        error = mac_cred_check_setuid(oldcred, uid);
515        if (error)
516                goto fail;
517#endif
518
519        /*
520         * See if we have "permission" by POSIX 1003.1 rules.
521         *
522         * Note that setuid(geteuid()) is a special case of
523         * "appropriate privileges" in appendix B.4.2.2.  We need
524         * to use this clause to be compatible with traditional BSD
525         * semantics.  Basically, it means that "setuid(xx)" sets all
526         * three id's (assuming you have privs).
527         *
528         * Notes on the logic.  We do things in three steps.
529         * 1: We determine if the euid is going to change, and do EPERM
530         *    right away.  We unconditionally change the euid later if this
531         *    test is satisfied, simplifying that part of the logic.
532         * 2: We determine if the real and/or saved uids are going to
533         *    change.  Determined by compile options.
534         * 3: Change euid last. (after tests in #2 for "appropriate privs")
535         */
536        if (uid != oldcred->cr_ruid &&          /* allow setuid(getuid()) */
537#ifdef _POSIX_SAVED_IDS
538            uid != oldcred->cr_svuid &&         /* allow setuid(saved gid) */
539#endif
540#ifdef POSIX_APPENDIX_B_4_2_2   /* Use BSD-compat clause from B.4.2.2 */
541            uid != oldcred->cr_uid &&           /* allow setuid(geteuid()) */
542#endif
543            (error = priv_check_cred(oldcred, PRIV_CRED_SETUID, 0)) != 0)
544                goto fail;
545
546#ifdef _POSIX_SAVED_IDS
547        /*
548         * Do we have "appropriate privileges" (are we root or uid == euid)
549         * If so, we are changing the real uid and/or saved uid.
550         */
551        if (
552#ifdef POSIX_APPENDIX_B_4_2_2   /* Use the clause from B.4.2.2 */
553            uid == oldcred->cr_uid ||
554#endif
555            /* We are using privs. */
556            priv_check_cred(oldcred, PRIV_CRED_SETUID, 0) == 0)
557#endif
558        {
559                /*
560                 * Set the real uid and transfer proc count to new user.
561                 */
562                if (uid != oldcred->cr_ruid) {
563                        change_ruid(newcred, uip);
564                        setsugid(p);
565                }
566                /*
567                 * Set saved uid
568                 *
569                 * XXX always set saved uid even if not _POSIX_SAVED_IDS, as
570                 * the security of seteuid() depends on it.  B.4.2.2 says it
571                 * is important that we should do this.
572                 */
573                if (uid != oldcred->cr_svuid) {
574                        change_svuid(newcred, uid);
575                        setsugid(p);
576                }
577        }
578
579        /*
580         * In all permitted cases, we are changing the euid.
581         */
582        if (uid != oldcred->cr_uid) {
583                change_euid(newcred, uip);
584                setsugid(p);
585        }
586        p->p_ucred = newcred;
587        PROC_UNLOCK(p);
588        uifree(uip);
589        crfree(oldcred);
590        return (0);
591
592fail:
593        PROC_UNLOCK(p);
594        uifree(uip);
595        crfree(newcred);
596        return (error);
597}
598
599#ifndef _SYS_SYSPROTO_HH_
600struct seteuid_args {
601        uid_t   euid;
602};
603#endif
604/* ARGSUSED */
605int
606seteuid(struct thread *td, struct seteuid_args *uap)
607{
608        struct proc *p = td->td_proc;
609        struct ucred *newcred, *oldcred;
610        uid_t euid;
611        struct uidinfo *euip;
612        int error;
613
614        euid = uap->euid;
615        AUDIT_ARG_EUID(euid);
616        newcred = crget();
617        euip = uifind(euid);
618        PROC_LOCK(p);
619        /*
620         * Copy credentials so other references do not see our changes.
621         */
622        oldcred = crcopysafe(p, newcred);
623
624#ifdef MAC
625        error = mac_cred_check_seteuid(oldcred, euid);
626        if (error)
627                goto fail;
628#endif
629
630        if (euid != oldcred->cr_ruid &&         /* allow seteuid(getuid()) */
631            euid != oldcred->cr_svuid &&        /* allow seteuid(saved uid) */
632            (error = priv_check_cred(oldcred, PRIV_CRED_SETEUID, 0)) != 0)
633                goto fail;
634
635        /*
636         * Everything's okay, do it.
637         */
638        if (oldcred->cr_uid != euid) {
639                change_euid(newcred, euip);
640                setsugid(p);
641        }
642        p->p_ucred = newcred;
643        PROC_UNLOCK(p);
644        uifree(euip);
645        crfree(oldcred);
646        return (0);
647
648fail:
649        PROC_UNLOCK(p);
650        uifree(euip);
651        crfree(newcred);
652        return (error);
653}
654
655#ifndef _SYS_SYSPROTO_HH_
656struct setgid_args {
657        gid_t   gid;
658};
659#endif
660/* ARGSUSED */
661int
662setgid(struct thread *td, struct setgid_args *uap)
663{
664        struct proc *p = td->td_proc;
665        struct ucred *newcred, *oldcred;
666        gid_t gid;
667        int error;
668
669        gid = uap->gid;
670        AUDIT_ARG_GID(gid);
671        newcred = crget();
672        PROC_LOCK(p);
673        oldcred = crcopysafe(p, newcred);
674
675#ifdef MAC
676        error = mac_cred_check_setgid(oldcred, gid);
677        if (error)
678                goto fail;
679#endif
680
681        /*
682         * See if we have "permission" by POSIX 1003.1 rules.
683         *
684         * Note that setgid(getegid()) is a special case of
685         * "appropriate privileges" in appendix B.4.2.2.  We need
686         * to use this clause to be compatible with traditional BSD
687         * semantics.  Basically, it means that "setgid(xx)" sets all
688         * three id's (assuming you have privs).
689         *
690         * For notes on the logic here, see setuid() above.
691         */
692        if (gid != oldcred->cr_rgid &&          /* allow setgid(getgid()) */
693#ifdef _POSIX_SAVED_IDS
694            gid != oldcred->cr_svgid &&         /* allow setgid(saved gid) */
695#endif
696#ifdef POSIX_APPENDIX_B_4_2_2   /* Use BSD-compat clause from B.4.2.2 */
697            gid != oldcred->cr_groups[0] && /* allow setgid(getegid()) */
698#endif
699            (error = priv_check_cred(oldcred, PRIV_CRED_SETGID, 0)) != 0)
700                goto fail;
701
702#ifdef _POSIX_SAVED_IDS
703        /*
704         * Do we have "appropriate privileges" (are we root or gid == egid)
705         * If so, we are changing the real uid and saved gid.
706         */
707        if (
708#ifdef POSIX_APPENDIX_B_4_2_2   /* use the clause from B.4.2.2 */
709            gid == oldcred->cr_groups[0] ||
710#endif
711            /* We are using privs. */
712            priv_check_cred(oldcred, PRIV_CRED_SETGID, 0) == 0)
713#endif
714        {
715                /*
716                 * Set real gid
717                 */
718                if (oldcred->cr_rgid != gid) {
719                        change_rgid(newcred, gid);
720                        setsugid(p);
721                }
722                /*
723                 * Set saved gid
724                 *
725                 * XXX always set saved gid even if not _POSIX_SAVED_IDS, as
726                 * the security of setegid() depends on it.  B.4.2.2 says it
727                 * is important that we should do this.
728                 */
729                if (oldcred->cr_svgid != gid) {
730                        change_svgid(newcred, gid);
731                        setsugid(p);
732                }
733        }
734        /*
735         * In all cases permitted cases, we are changing the egid.
736         * Copy credentials so other references do not see our changes.
737         */
738        if (oldcred->cr_groups[0] != gid) {
739                change_egid(newcred, gid);
740                setsugid(p);
741        }
742        p->p_ucred = newcred;
743        PROC_UNLOCK(p);
744        crfree(oldcred);
745        return (0);
746
747fail:
748        PROC_UNLOCK(p);
749        crfree(newcred);
750        return (error);
751}
752
753#ifndef _SYS_SYSPROTO_HH_
754struct setegid_args {
755        gid_t   egid;
756};
757#endif
758/* ARGSUSED */
759int
760setegid(struct thread *td, struct setegid_args *uap)
761{
762        struct proc *p = td->td_proc;
763        struct ucred *newcred, *oldcred;
764        gid_t egid;
765        int error;
766
767        egid = uap->egid;
768        AUDIT_ARG_EGID(egid);
769        newcred = crget();
770        PROC_LOCK(p);
771        oldcred = crcopysafe(p, newcred);
772
773#ifdef MAC
774        error = mac_cred_check_setegid(oldcred, egid);
775        if (error)
776                goto fail;
777#endif
778
779        if (egid != oldcred->cr_rgid &&         /* allow setegid(getgid()) */
780            egid != oldcred->cr_svgid &&        /* allow setegid(saved gid) */
781            (error = priv_check_cred(oldcred, PRIV_CRED_SETEGID, 0)) != 0)
782                goto fail;
783
784        if (oldcred->cr_groups[0] != egid) {
785                change_egid(newcred, egid);
786                setsugid(p);
787        }
788        p->p_ucred = newcred;
789        PROC_UNLOCK(p);
790        crfree(oldcred);
791        return (0);
792
793fail:
794        PROC_UNLOCK(p);
795        crfree(newcred);
796        return (error);
797}
798
799#ifndef _SYS_SYSPROTO_HH_
800struct setgroups_args {
801        u_int   gidsetsize;
802        gid_t   *gidset;
803};
804#endif
805/* ARGSUSED */
806int
807setgroups(struct thread *td, struct setgroups_args *uap)
808{
809        gid_t *groups = NULL;
810        int error;
811
812        if (uap->gidsetsize > ngroups_max + 1)
813                return (EINVAL);
814        groups = malloc(uap->gidsetsize * sizeof(gid_t), M_TEMP, M_WAITOK);
815        error = copyin(uap->gidset, groups, uap->gidsetsize * sizeof(gid_t));
816        if (error)
817                goto out;
818        error = kern_setgroups(td, uap->gidsetsize, groups);
819out:
820        free(groups, M_TEMP);
821        return (error);
822}
823
824int
825kern_setgroups(struct thread *td, u_int ngrp, gid_t *groups)
826{
827        struct proc *p = td->td_proc;
828        struct ucred *newcred, *oldcred;
829        int error;
830
831        if (ngrp > ngroups_max + 1)
832                return (EINVAL);
833        AUDIT_ARG_GROUPSET(groups, ngrp);
834        newcred = crget();
835        crextend(newcred, ngrp);
836        PROC_LOCK(p);
837        oldcred = crcopysafe(p, newcred);
838
839#ifdef MAC
840        error = mac_cred_check_setgroups(oldcred, ngrp, groups);
841        if (error)
842                goto fail;
843#endif
844
845        error = priv_check_cred(oldcred, PRIV_CRED_SETGROUPS, 0);
846        if (error)
847                goto fail;
848
849        if (ngrp < 1) {
850                /*
851                 * setgroups(0, NULL) is a legitimate way of clearing the
852                 * groups vector on non-BSD systems (which generally do not
853                 * have the egid in the groups[0]).  We risk security holes
854                 * when running non-BSD software if we do not do the same.
855                 */
856                newcred->cr_ngroups = 1;
857        } else {
858                crsetgroups_locked(newcred, ngrp, groups);
859        }
860        setsugid(p);
861        p->p_ucred = newcred;
862        PROC_UNLOCK(p);
863        crfree(oldcred);
864        return (0);
865
866fail:
867        PROC_UNLOCK(p);
868        crfree(newcred);
869        return (error);
870}
871
872#ifndef _SYS_SYSPROTO_HH_
873struct setreuid_args {
874        uid_t   ruid;
875        uid_t   euid;
876};
877#endif
878/* ARGSUSED */
879int
880setreuid(register struct thread *td, struct setreuid_args *uap)
881{
882        struct proc *p = td->td_proc;
883        struct ucred *newcred, *oldcred;
884        uid_t euid, ruid;
885        struct uidinfo *euip, *ruip;
886        int error;
887
888        euid = uap->euid;
889        ruid = uap->ruid;
890        AUDIT_ARG_EUID(euid);
891        AUDIT_ARG_RUID(ruid);
892        newcred = crget();
893        euip = uifind(euid);
894        ruip = uifind(ruid);
895        PROC_LOCK(p);
896        oldcred = crcopysafe(p, newcred);
897
898#ifdef MAC
899        error = mac_cred_check_setreuid(oldcred, ruid, euid);
900        if (error)
901                goto fail;
902#endif
903
904        if (((ruid != (uid_t)-1 && ruid != oldcred->cr_ruid &&
905              ruid != oldcred->cr_svuid) ||
906             (euid != (uid_t)-1 && euid != oldcred->cr_uid &&
907              euid != oldcred->cr_ruid && euid != oldcred->cr_svuid)) &&
908            (error = priv_check_cred(oldcred, PRIV_CRED_SETREUID, 0)) != 0)
909                goto fail;
910
911        if (euid != (uid_t)-1 && oldcred->cr_uid != euid) {
912                change_euid(newcred, euip);
913                setsugid(p);
914        }
915        if (ruid != (uid_t)-1 && oldcred->cr_ruid != ruid) {
916                change_ruid(newcred, ruip);
917                setsugid(p);
918        }
919        if ((ruid != (uid_t)-1 || newcred->cr_uid != newcred->cr_ruid) &&
920            newcred->cr_svuid != newcred->cr_uid) {
921                change_svuid(newcred, newcred->cr_uid);
922                setsugid(p);
923        }
924        p->p_ucred = newcred;
925        PROC_UNLOCK(p);
926        uifree(ruip);
927        uifree(euip);
928        crfree(oldcred);
929        return (0);
930
931fail:
932        PROC_UNLOCK(p);
933        uifree(ruip);
934        uifree(euip);
935        crfree(newcred);
936        return (error);
937}
938
939#ifndef _SYS_SYSPROTO_HH_
940struct setregid_args {
941        gid_t   rgid;
942        gid_t   egid;
943};
944#endif
945/* ARGSUSED */
946int
947setregid(register struct thread *td, struct setregid_args *uap)
948{
949        struct proc *p = td->td_proc;
950        struct ucred *newcred, *oldcred;
951        gid_t egid, rgid;
952        int error;
953
954        egid = uap->egid;
955        rgid = uap->rgid;
956        AUDIT_ARG_EGID(egid);
957        AUDIT_ARG_RGID(rgid);
958        newcred = crget();
959        PROC_LOCK(p);
960        oldcred = crcopysafe(p, newcred);
961
962#ifdef MAC
963        error = mac_cred_check_setregid(oldcred, rgid, egid);
964        if (error)
965                goto fail;
966#endif
967
968        if (((rgid != (gid_t)-1 && rgid != oldcred->cr_rgid &&
969            rgid != oldcred->cr_svgid) ||
970             (egid != (gid_t)-1 && egid != oldcred->cr_groups[0] &&
971             egid != oldcred->cr_rgid && egid != oldcred->cr_svgid)) &&
972            (error = priv_check_cred(oldcred, PRIV_CRED_SETREGID, 0)) != 0)
973                goto fail;
974
975        if (egid != (gid_t)-1 && oldcred->cr_groups[0] != egid) {
976                change_egid(newcred, egid);
977                setsugid(p);
978        }
979        if (rgid != (gid_t)-1 && oldcred->cr_rgid != rgid) {
980                change_rgid(newcred, rgid);
981                setsugid(p);
982        }
983        if ((rgid != (gid_t)-1 || newcred->cr_groups[0] != newcred->cr_rgid) &&
984            newcred->cr_svgid != newcred->cr_groups[0]) {
985                change_svgid(newcred, newcred->cr_groups[0]);
986                setsugid(p);
987        }
988        p->p_ucred = newcred;
989        PROC_UNLOCK(p);
990        crfree(oldcred);
991        return (0);
992
993fail:
994        PROC_UNLOCK(p);
995        crfree(newcred);
996        return (error);
997}
998
999/*
1000 * setresuid(ruid, euid, suid) is like setreuid except control over the saved
1001 * uid is explicit.
1002 */
1003#ifndef _SYS_SYSPROTO_HH_
1004struct setresuid_args {
1005        uid_t   ruid;
1006        uid_t   euid;
1007        uid_t   suid;
1008};
1009#endif
1010/* ARGSUSED */
1011int
1012setresuid(register struct thread *td, struct setresuid_args *uap)
1013{
1014        struct proc *p = td->td_proc;
1015        struct ucred *newcred, *oldcred;
1016        uid_t euid, ruid, suid;
1017        struct uidinfo *euip, *ruip;
1018        int error;
1019
1020        euid = uap->euid;
1021        ruid = uap->ruid;
1022        suid = uap->suid;
1023        AUDIT_ARG_EUID(euid);
1024        AUDIT_ARG_RUID(ruid);
1025        AUDIT_ARG_SUID(suid);
1026        newcred = crget();
1027        euip = uifind(euid);
1028        ruip = uifind(ruid);
1029        PROC_LOCK(p);
1030        oldcred = crcopysafe(p, newcred);
1031
1032#ifdef MAC
1033        error = mac_cred_check_setresuid(oldcred, ruid, euid, suid);
1034        if (error)
1035                goto fail;
1036#endif
1037
1038        if (((ruid != (uid_t)-1 && ruid != oldcred->cr_ruid &&
1039             ruid != oldcred->cr_svuid &&
1040              ruid != oldcred->cr_uid) ||
1041             (euid != (uid_t)-1 && euid != oldcred->cr_ruid &&
1042            euid != oldcred->cr_svuid &&
1043              euid != oldcred->cr_uid) ||
1044             (suid != (uid_t)-1 && suid != oldcred->cr_ruid &&
1045            suid != oldcred->cr_svuid &&
1046              suid != oldcred->cr_uid)) &&
1047            (error = priv_check_cred(oldcred, PRIV_CRED_SETRESUID, 0)) != 0)
1048                goto fail;
1049
1050        if (euid != (uid_t)-1 && oldcred->cr_uid != euid) {
1051                change_euid(newcred, euip);
1052                setsugid(p);
1053        }
1054        if (ruid != (uid_t)-1 && oldcred->cr_ruid != ruid) {
1055                change_ruid(newcred, ruip);
1056                setsugid(p);
1057        }
1058        if (suid != (uid_t)-1 && oldcred->cr_svuid != suid) {
1059                change_svuid(newcred, suid);
1060                setsugid(p);
1061        }
1062        p->p_ucred = newcred;
1063        PROC_UNLOCK(p);
1064        uifree(ruip);
1065        uifree(euip);
1066        crfree(oldcred);
1067        return (0);
1068
1069fail:
1070        PROC_UNLOCK(p);
1071        uifree(ruip);
1072        uifree(euip);
1073        crfree(newcred);
1074        return (error);
1075
1076}
1077
1078/*
1079 * setresgid(rgid, egid, sgid) is like setregid except control over the saved
1080 * gid is explicit.
1081 */
1082#ifndef _SYS_SYSPROTO_HH_
1083struct setresgid_args {
1084        gid_t   rgid;
1085        gid_t   egid;
1086        gid_t   sgid;
1087};
1088#endif
1089/* ARGSUSED */
1090int
1091setresgid(register struct thread *td, struct setresgid_args *uap)
1092{
1093        struct proc *p = td->td_proc;
1094        struct ucred *newcred, *oldcred;
1095        gid_t egid, rgid, sgid;
1096        int error;
1097
1098        egid = uap->egid;
1099        rgid = uap->rgid;
1100        sgid = uap->sgid;
1101        AUDIT_ARG_EGID(egid);
1102        AUDIT_ARG_RGID(rgid);
1103        AUDIT_ARG_SGID(sgid);
1104        newcred = crget();
1105        PROC_LOCK(p);
1106        oldcred = crcopysafe(p, newcred);
1107
1108#ifdef MAC
1109        error = mac_cred_check_setresgid(oldcred, rgid, egid, sgid);
1110        if (error)
1111                goto fail;
1112#endif
1113
1114        if (((rgid != (gid_t)-1 && rgid != oldcred->cr_rgid &&
1115              rgid != oldcred->cr_svgid &&
1116              rgid != oldcred->cr_groups[0]) ||
1117             (egid != (gid_t)-1 && egid != oldcred->cr_rgid &&
1118              egid != oldcred->cr_svgid &&
1119              egid != oldcred->cr_groups[0]) ||
1120             (sgid != (gid_t)-1 && sgid != oldcred->cr_rgid &&
1121              sgid != oldcred->cr_svgid &&
1122              sgid != oldcred->cr_groups[0])) &&
1123            (error = priv_check_cred(oldcred, PRIV_CRED_SETRESGID, 0)) != 0)
1124                goto fail;
1125
1126        if (egid != (gid_t)-1 && oldcred->cr_groups[0] != egid) {
1127                change_egid(newcred, egid);
1128                setsugid(p);
1129        }
1130        if (rgid != (gid_t)-1 && oldcred->cr_rgid != rgid) {
1131                change_rgid(newcred, rgid);
1132                setsugid(p);
1133        }
1134        if (sgid != (gid_t)-1 && oldcred->cr_svgid != sgid) {
1135                change_svgid(newcred, sgid);
1136                setsugid(p);
1137        }
1138        p->p_ucred = newcred;
1139        PROC_UNLOCK(p);
1140        crfree(oldcred);
1141        return (0);
1142
1143fail:
1144        PROC_UNLOCK(p);
1145        crfree(newcred);
1146        return (error);
1147}
1148
1149#ifndef _SYS_SYSPROTO_HH_
1150struct getresuid_args {
1151        uid_t   *ruid;
1152        uid_t   *euid;
1153        uid_t   *suid;
1154};
1155#endif
1156/* ARGSUSED */
1157int
1158getresuid(register struct thread *td, struct getresuid_args *uap)
1159{
1160        struct ucred *cred;
1161        int error1 = 0, error2 = 0, error3 = 0;
1162
1163        cred = td->td_ucred;
1164        if (uap->ruid)
1165                error1 = copyout(&cred->cr_ruid,
1166                    uap->ruid, sizeof(cred->cr_ruid));
1167        if (uap->euid)
1168                error2 = copyout(&cred->cr_uid,
1169                    uap->euid, sizeof(cred->cr_uid));
1170        if (uap->suid)
1171                error3 = copyout(&cred->cr_svuid,
1172                    uap->suid, sizeof(cred->cr_svuid));
1173        return (error1 ? error1 : error2 ? error2 : error3);
1174}
1175
1176#ifndef _SYS_SYSPROTO_HH_
1177struct getresgid_args {
1178        gid_t   *rgid;
1179        gid_t   *egid;
1180        gid_t   *sgid;
1181};
1182#endif
1183/* ARGSUSED */
1184int
1185getresgid(register struct thread *td, struct getresgid_args *uap)
1186{
1187        struct ucred *cred;
1188        int error1 = 0, error2 = 0, error3 = 0;
1189
1190        cred = td->td_ucred;
1191        if (uap->rgid)
1192                error1 = copyout(&cred->cr_rgid,
1193                    uap->rgid, sizeof(cred->cr_rgid));
1194        if (uap->egid)
1195                error2 = copyout(&cred->cr_groups[0],
1196                    uap->egid, sizeof(cred->cr_groups[0]));
1197        if (uap->sgid)
1198                error3 = copyout(&cred->cr_svgid,
1199                    uap->sgid, sizeof(cred->cr_svgid));
1200        return (error1 ? error1 : error2 ? error2 : error3);
1201}
1202
1203#ifndef _SYS_SYSPROTO_HH_
1204struct issetugid_args {
1205        int dummy;
1206};
1207#endif
1208/* ARGSUSED */
1209int
1210issetugid(register struct thread *td, struct issetugid_args *uap)
1211{
1212        struct proc *p = td->td_proc;
1213
1214        /*
1215         * Note: OpenBSD sets a P_SUGIDEXEC flag set at execve() time,
1216         * we use P_SUGID because we consider changing the owners as
1217         * "tainting" as well.
1218         * This is significant for procs that start as root and "become"
1219         * a user without an exec - programs cannot know *everything*
1220         * that libc *might* have put in their data segment.
1221         */
1222        PROC_LOCK(p);
1223        td->td_retval[0] = (p->p_flag & P_SUGID) ? 1 : 0;
1224        PROC_UNLOCK(p);
1225        return (0);
1226}
1227
1228int
1229__setugid(struct thread *td, struct __setugid_args *uap)
1230{
1231#ifdef REGRESSION
1232        struct proc *p;
1233
1234        p = td->td_proc;
1235        switch (uap->flag) {
1236        case 0:
1237                PROC_LOCK(p);
1238                p->p_flag &= ~P_SUGID;
1239                PROC_UNLOCK(p);
1240                return (0);
1241        case 1:
1242                PROC_LOCK(p);
1243                p->p_flag |= P_SUGID;
1244                PROC_UNLOCK(p);
1245                return (0);
1246        default:
1247                return (EINVAL);
1248        }
1249#else /* !REGRESSION */
1250
1251        return (ENOSYS);
1252#endif /* REGRESSION */
1253}
1254#endif /* __rtems__ */
1255
1256/*
1257 * Check if gid is a member of the group set.
1258 */
1259int
1260groupmember(gid_t gid, struct ucred *cred)
1261{
1262        int l;
1263        int h;
1264        int m;
1265
1266        if (cred->cr_groups[0] == gid)
1267                return(1);
1268
1269        /*
1270         * If gid was not our primary group, perform a binary search
1271         * of the supplemental groups.  This is possible because we
1272         * sort the groups in crsetgroups().
1273         */
1274        l = 1;
1275        h = cred->cr_ngroups;
1276        while (l < h) {
1277                m = l + ((h - l) / 2);
1278                if (cred->cr_groups[m] < gid)
1279                        l = m + 1;
1280                else
1281                        h = m;
1282        }
1283        if ((l < cred->cr_ngroups) && (cred->cr_groups[l] == gid))
1284                return (1);
1285
1286        return (0);
1287}
1288
1289#ifndef __rtems__
1290/*
1291 * Test the active securelevel against a given level.  securelevel_gt()
1292 * implements (securelevel > level).  securelevel_ge() implements
1293 * (securelevel >= level).  Note that the logic is inverted -- these
1294 * functions return EPERM on "success" and 0 on "failure".
1295 *
1296 * Due to care taken when setting the securelevel, we know that no jail will
1297 * be less secure that its parent (or the physical system), so it is sufficient
1298 * to test the current jail only.
1299 *
1300 * XXXRW: Possibly since this has to do with privilege, it should move to
1301 * kern_priv.c.
1302 */
1303int
1304securelevel_gt(struct ucred *cr, int level)
1305{
1306
1307        return (cr->cr_prison->pr_securelevel > level ? EPERM : 0);
1308}
1309
1310int
1311securelevel_ge(struct ucred *cr, int level)
1312{
1313
1314        return (cr->cr_prison->pr_securelevel >= level ? EPERM : 0);
1315}
1316
1317#endif /* __rtems__ */
1318
1319/*
1320 * 'see_other_uids' determines whether or not visibility of processes
1321 * and sockets with credentials holding different real uids is possible
1322 * using a variety of system MIBs.
1323 * XXX: data declarations should be together near the beginning of the file.
1324 */
1325static int      see_other_uids = 1;
1326SYSCTL_INT(_security_bsd, OID_AUTO, see_other_uids, CTLFLAG_RW,
1327    &see_other_uids, 0,
1328    "Unprivileged processes may see subjects/objects with different real uid");
1329
1330/*-
1331 * Determine if u1 "can see" the subject specified by u2, according to the
1332 * 'see_other_uids' policy.
1333 * Returns: 0 for permitted, ESRCH otherwise
1334 * Locks: none
1335 * References: *u1 and *u2 must not change during the call
1336 *             u1 may equal u2, in which case only one reference is required
1337 */
1338static int
1339cr_seeotheruids(struct ucred *u1, struct ucred *u2)
1340{
1341
1342        if (!see_other_uids && u1->cr_ruid != u2->cr_ruid) {
1343                if (priv_check_cred(u1, PRIV_SEEOTHERUIDS, 0) != 0)
1344                        return (ESRCH);
1345        }
1346        return (0);
1347}
1348
1349/*
1350 * 'see_other_gids' determines whether or not visibility of processes
1351 * and sockets with credentials holding different real gids is possible
1352 * using a variety of system MIBs.
1353 * XXX: data declarations should be together near the beginning of the file.
1354 */
1355static int      see_other_gids = 1;
1356SYSCTL_INT(_security_bsd, OID_AUTO, see_other_gids, CTLFLAG_RW,
1357    &see_other_gids, 0,
1358    "Unprivileged processes may see subjects/objects with different real gid");
1359
1360/*
1361 * Determine if u1 can "see" the subject specified by u2, according to the
1362 * 'see_other_gids' policy.
1363 * Returns: 0 for permitted, ESRCH otherwise
1364 * Locks: none
1365 * References: *u1 and *u2 must not change during the call
1366 *             u1 may equal u2, in which case only one reference is required
1367 */
1368static int
1369cr_seeothergids(struct ucred *u1, struct ucred *u2)
1370{
1371        int i, match;
1372       
1373        if (!see_other_gids) {
1374                match = 0;
1375                for (i = 0; i < u1->cr_ngroups; i++) {
1376                        if (groupmember(u1->cr_groups[i], u2))
1377                                match = 1;
1378                        if (match)
1379                                break;
1380                }
1381                if (!match) {
1382                        if (priv_check_cred(u1, PRIV_SEEOTHERGIDS, 0) != 0)
1383                                return (ESRCH);
1384                }
1385        }
1386        return (0);
1387}
1388
1389/*-
1390 * Determine if u1 "can see" the subject specified by u2.
1391 * Returns: 0 for permitted, an errno value otherwise
1392 * Locks: none
1393 * References: *u1 and *u2 must not change during the call
1394 *             u1 may equal u2, in which case only one reference is required
1395 */
1396int
1397cr_cansee(struct ucred *u1, struct ucred *u2)
1398{
1399        int error;
1400
1401        if ((error = prison_check(u1, u2)))
1402                return (error);
1403#ifdef MAC
1404        if ((error = mac_cred_check_visible(u1, u2)))
1405                return (error);
1406#endif
1407        if ((error = cr_seeotheruids(u1, u2)))
1408                return (error);
1409        if ((error = cr_seeothergids(u1, u2)))
1410                return (error);
1411        return (0);
1412}
1413
1414#ifndef __rtems__
1415
1416/*-
1417 * Determine if td "can see" the subject specified by p.
1418 * Returns: 0 for permitted, an errno value otherwise
1419 * Locks: Sufficient locks to protect p->p_ucred must be held.  td really
1420 *        should be curthread.
1421 * References: td and p must be valid for the lifetime of the call
1422 */
1423int
1424p_cansee(struct thread *td, struct proc *p)
1425{
1426
1427        /* Wrap cr_cansee() for all functionality. */
1428        KASSERT(td == curthread, ("%s: td not curthread", __func__));
1429        PROC_LOCK_ASSERT(p, MA_OWNED);
1430        return (cr_cansee(td->td_ucred, p->p_ucred));
1431}
1432
1433/*
1434 * 'conservative_signals' prevents the delivery of a broad class of
1435 * signals by unprivileged processes to processes that have changed their
1436 * credentials since the last invocation of execve().  This can prevent
1437 * the leakage of cached information or retained privileges as a result
1438 * of a common class of signal-related vulnerabilities.  However, this
1439 * may interfere with some applications that expect to be able to
1440 * deliver these signals to peer processes after having given up
1441 * privilege.
1442 */
1443static int      conservative_signals = 1;
1444SYSCTL_INT(_security_bsd, OID_AUTO, conservative_signals, CTLFLAG_RW,
1445    &conservative_signals, 0, "Unprivileged processes prevented from "
1446    "sending certain signals to processes whose credentials have changed");
1447/*-
1448 * Determine whether cred may deliver the specified signal to proc.
1449 * Returns: 0 for permitted, an errno value otherwise.
1450 * Locks: A lock must be held for proc.
1451 * References: cred and proc must be valid for the lifetime of the call.
1452 */
1453int
1454cr_cansignal(struct ucred *cred, struct proc *proc, int signum)
1455{
1456        int error;
1457
1458        PROC_LOCK_ASSERT(proc, MA_OWNED);
1459        /*
1460         * Jail semantics limit the scope of signalling to proc in the
1461         * same jail as cred, if cred is in jail.
1462         */
1463        error = prison_check(cred, proc->p_ucred);
1464        if (error)
1465                return (error);
1466#ifdef MAC
1467        if ((error = mac_proc_check_signal(cred, proc, signum)))
1468                return (error);
1469#endif
1470        if ((error = cr_seeotheruids(cred, proc->p_ucred)))
1471                return (error);
1472        if ((error = cr_seeothergids(cred, proc->p_ucred)))
1473                return (error);
1474
1475        /*
1476         * UNIX signal semantics depend on the status of the P_SUGID
1477         * bit on the target process.  If the bit is set, then additional
1478         * restrictions are placed on the set of available signals.
1479         */
1480        if (conservative_signals && (proc->p_flag & P_SUGID)) {
1481                switch (signum) {
1482                case 0:
1483                case SIGKILL:
1484                case SIGINT:
1485                case SIGTERM:
1486                case SIGALRM:
1487                case SIGSTOP:
1488                case SIGTTIN:
1489                case SIGTTOU:
1490                case SIGTSTP:
1491                case SIGHUP:
1492                case SIGUSR1:
1493                case SIGUSR2:
1494                        /*
1495                         * Generally, permit job and terminal control
1496                         * signals.
1497                         */
1498                        break;
1499                default:
1500                        /* Not permitted without privilege. */
1501                        error = priv_check_cred(cred, PRIV_SIGNAL_SUGID, 0);
1502                        if (error)
1503                                return (error);
1504                }
1505        }
1506
1507        /*
1508         * Generally, the target credential's ruid or svuid must match the
1509         * subject credential's ruid or euid.
1510         */
1511        if (cred->cr_ruid != proc->p_ucred->cr_ruid &&
1512            cred->cr_ruid != proc->p_ucred->cr_svuid &&
1513            cred->cr_uid != proc->p_ucred->cr_ruid &&
1514            cred->cr_uid != proc->p_ucred->cr_svuid) {
1515                error = priv_check_cred(cred, PRIV_SIGNAL_DIFFCRED, 0);
1516                if (error)
1517                        return (error);
1518        }
1519
1520        return (0);
1521}
1522
1523/*-
1524 * Determine whether td may deliver the specified signal to p.
1525 * Returns: 0 for permitted, an errno value otherwise
1526 * Locks: Sufficient locks to protect various components of td and p
1527 *        must be held.  td must be curthread, and a lock must be
1528 *        held for p.
1529 * References: td and p must be valid for the lifetime of the call
1530 */
1531int
1532p_cansignal(struct thread *td, struct proc *p, int signum)
1533{
1534
1535        KASSERT(td == curthread, ("%s: td not curthread", __func__));
1536        PROC_LOCK_ASSERT(p, MA_OWNED);
1537        if (td->td_proc == p)
1538                return (0);
1539
1540        /*
1541         * UNIX signalling semantics require that processes in the same
1542         * session always be able to deliver SIGCONT to one another,
1543         * overriding the remaining protections.
1544         */
1545        /* XXX: This will require an additional lock of some sort. */
1546        if (signum == SIGCONT && td->td_proc->p_session == p->p_session)
1547                return (0);
1548        /*
1549         * Some compat layers use SIGTHR and higher signals for
1550         * communication between different kernel threads of the same
1551         * process, so that they expect that it's always possible to
1552         * deliver them, even for suid applications where cr_cansignal() can
1553         * deny such ability for security consideration.  It should be
1554         * pretty safe to do since the only way to create two processes
1555         * with the same p_leader is via rfork(2).
1556         */
1557        if (td->td_proc->p_leader != NULL && signum >= SIGTHR &&
1558            signum < SIGTHR + 4 && td->td_proc->p_leader == p->p_leader)
1559                return (0);
1560
1561        return (cr_cansignal(td->td_ucred, p, signum));
1562}
1563
1564/*-
1565 * Determine whether td may reschedule p.
1566 * Returns: 0 for permitted, an errno value otherwise
1567 * Locks: Sufficient locks to protect various components of td and p
1568 *        must be held.  td must be curthread, and a lock must
1569 *        be held for p.
1570 * References: td and p must be valid for the lifetime of the call
1571 */
1572int
1573p_cansched(struct thread *td, struct proc *p)
1574{
1575        int error;
1576
1577        KASSERT(td == curthread, ("%s: td not curthread", __func__));
1578        PROC_LOCK_ASSERT(p, MA_OWNED);
1579        if (td->td_proc == p)
1580                return (0);
1581        if ((error = prison_check(td->td_ucred, p->p_ucred)))
1582                return (error);
1583#ifdef MAC
1584        if ((error = mac_proc_check_sched(td->td_ucred, p)))
1585                return (error);
1586#endif
1587        if ((error = cr_seeotheruids(td->td_ucred, p->p_ucred)))
1588                return (error);
1589        if ((error = cr_seeothergids(td->td_ucred, p->p_ucred)))
1590                return (error);
1591        if (td->td_ucred->cr_ruid != p->p_ucred->cr_ruid &&
1592            td->td_ucred->cr_uid != p->p_ucred->cr_ruid) {
1593                error = priv_check(td, PRIV_SCHED_DIFFCRED);
1594                if (error)
1595                        return (error);
1596        }
1597        return (0);
1598}
1599
1600/*
1601 * The 'unprivileged_proc_debug' flag may be used to disable a variety of
1602 * unprivileged inter-process debugging services, including some procfs
1603 * functionality, ptrace(), and ktrace().  In the past, inter-process
1604 * debugging has been involved in a variety of security problems, and sites
1605 * not requiring the service might choose to disable it when hardening
1606 * systems.
1607 *
1608 * XXX: Should modifying and reading this variable require locking?
1609 * XXX: data declarations should be together near the beginning of the file.
1610 */
1611static int      unprivileged_proc_debug = 1;
1612SYSCTL_INT(_security_bsd, OID_AUTO, unprivileged_proc_debug, CTLFLAG_RW,
1613    &unprivileged_proc_debug, 0,
1614    "Unprivileged processes may use process debugging facilities");
1615
1616/*-
1617 * Determine whether td may debug p.
1618 * Returns: 0 for permitted, an errno value otherwise
1619 * Locks: Sufficient locks to protect various components of td and p
1620 *        must be held.  td must be curthread, and a lock must
1621 *        be held for p.
1622 * References: td and p must be valid for the lifetime of the call
1623 */
1624int
1625p_candebug(struct thread *td, struct proc *p)
1626{
1627        int credentialchanged, error, grpsubset, i, uidsubset;
1628
1629        KASSERT(td == curthread, ("%s: td not curthread", __func__));
1630        PROC_LOCK_ASSERT(p, MA_OWNED);
1631        if (!unprivileged_proc_debug) {
1632                error = priv_check(td, PRIV_DEBUG_UNPRIV);
1633                if (error)
1634                        return (error);
1635        }
1636        if (td->td_proc == p)
1637                return (0);
1638        if ((error = prison_check(td->td_ucred, p->p_ucred)))
1639                return (error);
1640#ifdef MAC
1641        if ((error = mac_proc_check_debug(td->td_ucred, p)))
1642                return (error);
1643#endif
1644        if ((error = cr_seeotheruids(td->td_ucred, p->p_ucred)))
1645                return (error);
1646        if ((error = cr_seeothergids(td->td_ucred, p->p_ucred)))
1647                return (error);
1648
1649        /*
1650         * Is p's group set a subset of td's effective group set?  This
1651         * includes p's egid, group access list, rgid, and svgid.
1652         */
1653        grpsubset = 1;
1654        for (i = 0; i < p->p_ucred->cr_ngroups; i++) {
1655                if (!groupmember(p->p_ucred->cr_groups[i], td->td_ucred)) {
1656                        grpsubset = 0;
1657                        break;
1658                }
1659        }
1660        grpsubset = grpsubset &&
1661            groupmember(p->p_ucred->cr_rgid, td->td_ucred) &&
1662            groupmember(p->p_ucred->cr_svgid, td->td_ucred);
1663
1664        /*
1665         * Are the uids present in p's credential equal to td's
1666         * effective uid?  This includes p's euid, svuid, and ruid.
1667         */
1668        uidsubset = (td->td_ucred->cr_uid == p->p_ucred->cr_uid &&
1669            td->td_ucred->cr_uid == p->p_ucred->cr_svuid &&
1670            td->td_ucred->cr_uid == p->p_ucred->cr_ruid);
1671
1672        /*
1673         * Has the credential of the process changed since the last exec()?
1674         */
1675        credentialchanged = (p->p_flag & P_SUGID);
1676
1677        /*
1678         * If p's gids aren't a subset, or the uids aren't a subset,
1679         * or the credential has changed, require appropriate privilege
1680         * for td to debug p.
1681         */
1682        if (!grpsubset || !uidsubset) {
1683                error = priv_check(td, PRIV_DEBUG_DIFFCRED);
1684                if (error)
1685                        return (error);
1686        }
1687
1688        if (credentialchanged) {
1689                error = priv_check(td, PRIV_DEBUG_SUGID);
1690                if (error)
1691                        return (error);
1692        }
1693
1694        /* Can't trace init when securelevel > 0. */
1695        if (p == initproc) {
1696                error = securelevel_gt(td->td_ucred, 0);
1697                if (error)
1698                        return (error);
1699        }
1700
1701        /*
1702         * Can't trace a process that's currently exec'ing.
1703         *
1704         * XXX: Note, this is not a security policy decision, it's a
1705         * basic correctness/functionality decision.  Therefore, this check
1706         * should be moved to the caller's of p_candebug().
1707         */
1708        if ((p->p_flag & P_INEXEC) != 0)
1709                return (EBUSY);
1710
1711        return (0);
1712}
1713#endif /* __rtems__ */
1714
1715/*-
1716 * Determine whether the subject represented by cred can "see" a socket.
1717 * Returns: 0 for permitted, ENOENT otherwise.
1718 */
1719int
1720cr_canseesocket(struct ucred *cred, struct socket *so)
1721{
1722        int error;
1723
1724        error = prison_check(cred, so->so_cred);
1725        if (error)
1726                return (ENOENT);
1727#ifdef MAC
1728        error = mac_socket_check_visible(cred, so);
1729        if (error)
1730                return (error);
1731#endif
1732        if (cr_seeotheruids(cred, so->so_cred))
1733                return (ENOENT);
1734        if (cr_seeothergids(cred, so->so_cred))
1735                return (ENOENT);
1736
1737        return (0);
1738}
1739
1740#if defined(INET) || defined(INET6)
1741/*-
1742 * Determine whether the subject represented by cred can "see" a socket.
1743 * Returns: 0 for permitted, ENOENT otherwise.
1744 */
1745int
1746cr_canseeinpcb(struct ucred *cred, struct inpcb *inp)
1747{
1748        int error;
1749
1750        error = prison_check(cred, inp->inp_cred);
1751        if (error)
1752                return (ENOENT);
1753#ifdef MAC
1754        INP_LOCK_ASSERT(inp);
1755        error = mac_inpcb_check_visible(cred, inp);
1756        if (error)
1757                return (error);
1758#endif
1759        if (cr_seeotheruids(cred, inp->inp_cred))
1760                return (ENOENT);
1761        if (cr_seeothergids(cred, inp->inp_cred))
1762                return (ENOENT);
1763
1764        return (0);
1765}
1766#endif
1767
1768#ifndef __rtems__
1769/*-
1770 * Determine whether td can wait for the exit of p.
1771 * Returns: 0 for permitted, an errno value otherwise
1772 * Locks: Sufficient locks to protect various components of td and p
1773 *        must be held.  td must be curthread, and a lock must
1774 *        be held for p.
1775 * References: td and p must be valid for the lifetime of the call
1776
1777 */
1778int
1779p_canwait(struct thread *td, struct proc *p)
1780{
1781        int error;
1782
1783        KASSERT(td == curthread, ("%s: td not curthread", __func__));
1784        PROC_LOCK_ASSERT(p, MA_OWNED);
1785        if ((error = prison_check(td->td_ucred, p->p_ucred)))
1786                return (error);
1787#ifdef MAC
1788        if ((error = mac_proc_check_wait(td->td_ucred, p)))
1789                return (error);
1790#endif
1791#if 0
1792        /* XXXMAC: This could have odd effects on some shells. */
1793        if ((error = cr_seeotheruids(td->td_ucred, p->p_ucred)))
1794                return (error);
1795#endif
1796
1797        return (0);
1798}
1799#endif /* __rtems__ */
1800
1801/*
1802 * Allocate a zeroed cred structure.
1803 */
1804struct ucred *
1805crget(void)
1806{
1807        register struct ucred *cr;
1808
1809        cr = malloc(sizeof(*cr), M_CRED, M_WAITOK | M_ZERO);
1810        refcount_init(&cr->cr_ref, 1);
1811#ifdef AUDIT
1812        audit_cred_init(cr);
1813#endif
1814#ifdef MAC
1815        mac_cred_init(cr);
1816#endif
1817        crextend(cr, XU_NGROUPS);
1818        return (cr);
1819}
1820
1821/*
1822 * Claim another reference to a ucred structure.
1823 */
1824struct ucred *
1825crhold(struct ucred *cr)
1826{
1827
1828        refcount_acquire(&cr->cr_ref);
1829        return (cr);
1830}
1831
1832/*
1833 * Free a cred structure.  Throws away space when ref count gets to 0.
1834 */
1835void
1836crfree(struct ucred *cr)
1837{
1838
1839        KASSERT(cr->cr_ref > 0, ("bad ucred refcount: %d", cr->cr_ref));
1840        KASSERT(cr->cr_ref != 0xdeadc0de, ("dangling reference to ucred"));
1841        if (refcount_release(&cr->cr_ref)) {
1842                /*
1843                 * Some callers of crget(), such as nfs_statfs(),
1844                 * allocate a temporary credential, but don't
1845                 * allocate a uidinfo structure.
1846                 */
1847                if (cr->cr_uidinfo != NULL)
1848                        uifree(cr->cr_uidinfo);
1849                if (cr->cr_ruidinfo != NULL)
1850                        uifree(cr->cr_ruidinfo);
1851                /*
1852                 * Free a prison, if any.
1853                 */
1854                if (cr->cr_prison != NULL)
1855                        prison_free(cr->cr_prison);
1856#ifdef AUDIT
1857                audit_cred_destroy(cr);
1858#endif
1859#ifdef MAC
1860                mac_cred_destroy(cr);
1861#endif
1862                free(cr->cr_groups, M_CRED);
1863                free(cr, M_CRED);
1864        }
1865}
1866
1867#ifndef __rtems__
1868/*
1869 * Check to see if this ucred is shared.
1870 */
1871int
1872crshared(struct ucred *cr)
1873{
1874
1875        return (cr->cr_ref > 1);
1876}
1877
1878/*
1879 * Copy a ucred's contents from a template.  Does not block.
1880 */
1881void
1882crcopy(struct ucred *dest, struct ucred *src)
1883{
1884
1885        KASSERT(crshared(dest) == 0, ("crcopy of shared ucred"));
1886        bcopy(&src->cr_startcopy, &dest->cr_startcopy,
1887            (unsigned)((caddr_t)&src->cr_endcopy -
1888                (caddr_t)&src->cr_startcopy));
1889        crsetgroups(dest, src->cr_ngroups, src->cr_groups);
1890        uihold(dest->cr_uidinfo);
1891        uihold(dest->cr_ruidinfo);
1892        prison_hold(dest->cr_prison);
1893#ifdef AUDIT
1894        audit_cred_copy(src, dest);
1895#endif
1896#ifdef MAC
1897        mac_cred_copy(src, dest);
1898#endif
1899}
1900
1901/*
1902 * Dup cred struct to a new held one.
1903 */
1904struct ucred *
1905crdup(struct ucred *cr)
1906{
1907        struct ucred *newcr;
1908
1909        newcr = crget();
1910        crcopy(newcr, cr);
1911        return (newcr);
1912}
1913#endif /* __rtems__ */
1914
1915/*
1916 * Fill in a struct xucred based on a struct ucred.
1917 */
1918void
1919cru2x(struct ucred *cr, struct xucred *xcr)
1920{
1921        int ngroups;
1922
1923        bzero(xcr, sizeof(*xcr));
1924        xcr->cr_version = XUCRED_VERSION;
1925        xcr->cr_uid = cr->cr_uid;
1926
1927        ngroups = MIN(cr->cr_ngroups, XU_NGROUPS);
1928        xcr->cr_ngroups = ngroups;
1929        bcopy(cr->cr_groups, xcr->cr_groups,
1930            ngroups * sizeof(*cr->cr_groups));
1931}
1932
1933#ifndef __rtems__
1934/*
1935 * small routine to swap a thread's current ucred for the correct one taken
1936 * from the process.
1937 */
1938void
1939cred_update_thread(struct thread *td)
1940{
1941        struct proc *p;
1942        struct ucred *cred;
1943
1944        p = td->td_proc;
1945        cred = td->td_ucred;
1946        PROC_LOCK(p);
1947        td->td_ucred = crhold(p->p_ucred);
1948        PROC_UNLOCK(p);
1949        if (cred != NULL)
1950                crfree(cred);
1951}
1952
1953struct ucred *
1954crcopysafe(struct proc *p, struct ucred *cr)
1955{
1956        struct ucred *oldcred;
1957        int groups;
1958
1959        PROC_LOCK_ASSERT(p, MA_OWNED);
1960
1961        oldcred = p->p_ucred;
1962        while (cr->cr_agroups < oldcred->cr_agroups) {
1963                groups = oldcred->cr_agroups;
1964                PROC_UNLOCK(p);
1965                crextend(cr, groups);
1966                PROC_LOCK(p);
1967                oldcred = p->p_ucred;
1968        }
1969        crcopy(cr, oldcred);
1970
1971        return (oldcred);
1972}
1973#endif /* __rtems__ */
1974
1975/*
1976 * Extend the passed in credential to hold n items.
1977 */
1978static void
1979crextend(struct ucred *cr, int n)
1980{
1981        int cnt;
1982
1983        /* Truncate? */
1984        if (n <= cr->cr_agroups)
1985                return;
1986
1987        /*
1988         * We extend by 2 each time since we're using a power of two
1989         * allocator until we need enough groups to fill a page.
1990         * Once we're allocating multiple pages, only allocate as many
1991         * as we actually need.  The case of processes needing a
1992         * non-power of two number of pages seems more likely than
1993         * a real world process that adds thousands of groups one at a
1994         * time.
1995         */
1996        if ( n < PAGE_SIZE / sizeof(gid_t) ) {
1997                if (cr->cr_agroups == 0)
1998                        cnt = MINALLOCSIZE / sizeof(gid_t);
1999                else
2000                        cnt = cr->cr_agroups * 2;
2001
2002                while (cnt < n)
2003                        cnt *= 2;
2004        } else
2005                cnt = roundup2(n, PAGE_SIZE / sizeof(gid_t));
2006
2007        /* Free the old array. */
2008        if (cr->cr_groups)
2009                free(cr->cr_groups, M_CRED);
2010
2011        cr->cr_groups = malloc(cnt * sizeof(gid_t), M_CRED, M_WAITOK | M_ZERO);
2012        cr->cr_agroups = cnt;
2013}
2014
2015#ifndef __rtems__
2016/*
2017 * Copy groups in to a credential, preserving any necessary invariants.
2018 * Currently this includes the sorting of all supplemental gids.
2019 * crextend() must have been called before hand to ensure sufficient
2020 * space is available.
2021 */
2022static void
2023crsetgroups_locked(struct ucred *cr, int ngrp, gid_t *groups)
2024{
2025        int i;
2026        int j;
2027        gid_t g;
2028       
2029        KASSERT(cr->cr_agroups >= ngrp, ("cr_ngroups is too small"));
2030
2031        bcopy(groups, cr->cr_groups, ngrp * sizeof(gid_t));
2032        cr->cr_ngroups = ngrp;
2033
2034        /*
2035         * Sort all groups except cr_groups[0] to allow groupmember to
2036         * perform a binary search.
2037         *
2038         * XXX: If large numbers of groups become common this should
2039         * be replaced with shell sort like linux uses or possibly
2040         * heap sort.
2041         */
2042        for (i = 2; i < ngrp; i++) {
2043                g = cr->cr_groups[i];
2044                for (j = i-1; j >= 1 && g < cr->cr_groups[j]; j--)
2045                        cr->cr_groups[j + 1] = cr->cr_groups[j];
2046                cr->cr_groups[j + 1] = g;
2047        }
2048}
2049
2050/*
2051 * Copy groups in to a credential after expanding it if required.
2052 * Truncate the list to (ngroups_max + 1) if it is too large.
2053 */
2054void
2055crsetgroups(struct ucred *cr, int ngrp, gid_t *groups)
2056{
2057
2058        if (ngrp > ngroups_max + 1)
2059                ngrp = ngroups_max + 1;
2060
2061        crextend(cr, ngrp);
2062        crsetgroups_locked(cr, ngrp, groups);
2063}
2064
2065/*
2066 * Get login name, if available.
2067 */
2068#ifndef _SYS_SYSPROTO_HH_
2069struct getlogin_args {
2070        char    *namebuf;
2071        u_int   namelen;
2072};
2073#endif
2074/* ARGSUSED */
2075int
2076getlogin(struct thread *td, struct getlogin_args *uap)
2077{
2078        int error;
2079        char login[MAXLOGNAME];
2080        struct proc *p = td->td_proc;
2081
2082        if (uap->namelen > MAXLOGNAME)
2083                uap->namelen = MAXLOGNAME;
2084        PROC_LOCK(p);
2085        SESS_LOCK(p->p_session);
2086        bcopy(p->p_session->s_login, login, uap->namelen);
2087        SESS_UNLOCK(p->p_session);
2088        PROC_UNLOCK(p);
2089        error = copyout(login, uap->namebuf, uap->namelen);
2090        return(error);
2091}
2092
2093/*
2094 * Set login name.
2095 */
2096#ifndef _SYS_SYSPROTO_HH_
2097struct setlogin_args {
2098        char    *namebuf;
2099};
2100#endif
2101/* ARGSUSED */
2102int
2103setlogin(struct thread *td, struct setlogin_args *uap)
2104{
2105        struct proc *p = td->td_proc;
2106        int error;
2107        char logintmp[MAXLOGNAME];
2108
2109        error = priv_check(td, PRIV_PROC_SETLOGIN);
2110        if (error)
2111                return (error);
2112        error = copyinstr(uap->namebuf, logintmp, sizeof(logintmp), NULL);
2113        if (error == ENAMETOOLONG)
2114                error = EINVAL;
2115        else if (!error) {
2116                PROC_LOCK(p);
2117                SESS_LOCK(p->p_session);
2118                (void) memcpy(p->p_session->s_login, logintmp,
2119                    sizeof(logintmp));
2120                SESS_UNLOCK(p->p_session);
2121                PROC_UNLOCK(p);
2122        }
2123        return (error);
2124}
2125
2126void
2127setsugid(struct proc *p)
2128{
2129
2130        PROC_LOCK_ASSERT(p, MA_OWNED);
2131        p->p_flag |= P_SUGID;
2132        if (!(p->p_pfsflags & PF_ISUGID))
2133                p->p_stops = 0;
2134}
2135
2136/*-
2137 * Change a process's effective uid.
2138 * Side effects: newcred->cr_uid and newcred->cr_uidinfo will be modified.
2139 * References: newcred must be an exclusive credential reference for the
2140 *             duration of the call.
2141 */
2142void
2143change_euid(struct ucred *newcred, struct uidinfo *euip)
2144{
2145
2146        newcred->cr_uid = euip->ui_uid;
2147        uihold(euip);
2148        uifree(newcred->cr_uidinfo);
2149        newcred->cr_uidinfo = euip;
2150}
2151
2152/*-
2153 * Change a process's effective gid.
2154 * Side effects: newcred->cr_gid will be modified.
2155 * References: newcred must be an exclusive credential reference for the
2156 *             duration of the call.
2157 */
2158void
2159change_egid(struct ucred *newcred, gid_t egid)
2160{
2161
2162        newcred->cr_groups[0] = egid;
2163}
2164
2165/*-
2166 * Change a process's real uid.
2167 * Side effects: newcred->cr_ruid will be updated, newcred->cr_ruidinfo
2168 *               will be updated, and the old and new cr_ruidinfo proc
2169 *               counts will be updated.
2170 * References: newcred must be an exclusive credential reference for the
2171 *             duration of the call.
2172 */
2173void
2174change_ruid(struct ucred *newcred, struct uidinfo *ruip)
2175{
2176
2177        (void)chgproccnt(newcred->cr_ruidinfo, -1, 0);
2178        newcred->cr_ruid = ruip->ui_uid;
2179        uihold(ruip);
2180        uifree(newcred->cr_ruidinfo);
2181        newcred->cr_ruidinfo = ruip;
2182        (void)chgproccnt(newcred->cr_ruidinfo, 1, 0);
2183}
2184
2185/*-
2186 * Change a process's real gid.
2187 * Side effects: newcred->cr_rgid will be updated.
2188 * References: newcred must be an exclusive credential reference for the
2189 *             duration of the call.
2190 */
2191void
2192change_rgid(struct ucred *newcred, gid_t rgid)
2193{
2194
2195        newcred->cr_rgid = rgid;
2196}
2197
2198/*-
2199 * Change a process's saved uid.
2200 * Side effects: newcred->cr_svuid will be updated.
2201 * References: newcred must be an exclusive credential reference for the
2202 *             duration of the call.
2203 */
2204void
2205change_svuid(struct ucred *newcred, uid_t svuid)
2206{
2207
2208        newcred->cr_svuid = svuid;
2209}
2210
2211/*-
2212 * Change a process's saved gid.
2213 * Side effects: newcred->cr_svgid will be updated.
2214 * References: newcred must be an exclusive credential reference for the
2215 *             duration of the call.
2216 */
2217void
2218change_svgid(struct ucred *newcred, gid_t svgid)
2219{
2220
2221        newcred->cr_svgid = svgid;
2222}
2223#endif /* __rtems__ */
Note: See TracBrowser for help on using the repository browser.