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