kernel - Major signal path adjustments to fix races, tsleep race fixes, +more
[dragonfly.git] / sys / kern / kern_prot.c
CommitLineData
984263bc
MD
1/*
2 * Copyright (c) 1982, 1986, 1989, 1990, 1991, 1993
3 * The Regents of the University of California. All rights reserved.
4 * (c) UNIX System Laboratories, Inc.
5 * All or some portions of this file are derived from material licensed
6 * to the University of California by American Telephone and Telegraph
7 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
8 * the permission of UNIX System Laboratories, Inc.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the University of
21 * California, Berkeley and its contributors.
22 * 4. Neither the name of the University nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 *
38 * @(#)kern_prot.c 8.6 (Berkeley) 1/21/94
39 * $FreeBSD: src/sys/kern/kern_prot.c,v 1.53.2.9 2002/03/09 05:20:26 dd Exp $
420eedf5 40 * $DragonFly: src/sys/kern/kern_prot.c,v 1.29 2008/02/16 15:53:39 matthias Exp $
984263bc
MD
41 */
42
43/*
44 * System calls related to processes and protection
45 */
46
47#include "opt_compat.h"
48
49#include <sys/param.h>
50#include <sys/acct.h>
51#include <sys/systm.h>
52#include <sys/sysproto.h>
53#include <sys/kernel.h>
3b564f1f 54#include <sys/lock.h>
984263bc 55#include <sys/proc.h>
28eeae89 56#include <sys/priv.h>
984263bc
MD
57#include <sys/malloc.h>
58#include <sys/pioctl.h>
59#include <sys/resourcevar.h>
41c20dac 60#include <sys/jail.h>
508ceb09 61#include <sys/lockf.h>
d9b2033e
MD
62#include <sys/spinlock.h>
63
64#include <sys/thread2.h>
65#include <sys/spinlock2.h>
984263bc
MD
66
67static MALLOC_DEFINE(M_CRED, "cred", "credentials");
68
984263bc 69int
753fd850 70sys_getpid(struct getpid_args *uap)
984263bc 71{
41c20dac 72 struct proc *p = curproc;
984263bc 73
c7114eea 74 uap->sysmsg_fds[0] = p->p_pid;
984263bc 75#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
ccd05f15 76 lwkt_gettoken(&proc_token);
c7114eea 77 uap->sysmsg_fds[1] = p->p_pptr->p_pid;
ccd05f15 78 lwkt_reltoken(&proc_token);
984263bc
MD
79#endif
80 return (0);
81}
82
984263bc 83int
753fd850 84sys_getppid(struct getppid_args *uap)
984263bc 85{
41c20dac 86 struct proc *p = curproc;
984263bc 87
ccd05f15 88 lwkt_gettoken(&proc_token);
c7114eea 89 uap->sysmsg_result = p->p_pptr->p_pid;
ccd05f15 90 lwkt_reltoken(&proc_token);
3919ced0 91
984263bc 92 return (0);
f9366a82
SS
93}
94
3919ced0
MD
95/*
96 * MPSAFE
97 */
f9366a82
SS
98int
99sys_lwp_gettid(struct lwp_gettid_args *uap)
100{
101 struct lwp *lp = curthread->td_lwp;
102
103 uap->sysmsg_result = lp->lwp_tid;
104 return (0);
984263bc
MD
105}
106
107/*
108 * Get process group ID; note that POSIX getpgrp takes no parameter
109 *
3919ced0 110 * MPSAFE XXX pgrp
984263bc 111 */
984263bc 112int
753fd850 113sys_getpgrp(struct getpgrp_args *uap)
984263bc 114{
41c20dac 115 struct proc *p = curproc;
984263bc 116
c7114eea 117 uap->sysmsg_result = p->p_pgrp->pg_id;
984263bc
MD
118 return (0);
119}
120
a64ba182 121/*
420eedf5 122 * Get an arbitrary pid's process group id
a64ba182 123 */
984263bc 124int
753fd850 125sys_getpgid(struct getpgid_args *uap)
984263bc 126{
41c20dac 127 struct proc *p = curproc;
984263bc 128 struct proc *pt;
3919ced0 129 int error;
984263bc 130
3919ced0 131 error = 0;
984263bc 132
3919ced0
MD
133 if (uap->pid == 0) {
134 pt = p;
58c2553a 135 PHOLD(pt);
3919ced0
MD
136 } else {
137 pt = pfind(uap->pid);
138 if (pt == NULL)
139 error = ESRCH;
140 }
58c2553a 141 /* XXX MPSAFE on pgrp? */
3919ced0
MD
142 if (error == 0)
143 uap->sysmsg_result = pt->p_pgrp->pg_id;
58c2553a
MD
144 if (pt)
145 PRELE(pt);
3919ced0 146 return (error);
984263bc
MD
147}
148
149/*
420eedf5 150 * Get an arbitrary pid's session id.
984263bc 151 */
984263bc 152int
753fd850 153sys_getsid(struct getsid_args *uap)
984263bc 154{
41c20dac 155 struct proc *p = curproc;
984263bc 156 struct proc *pt;
3919ced0 157 int error;
984263bc 158
3919ced0 159 error = 0;
984263bc 160
3919ced0
MD
161 if (uap->pid == 0) {
162 pt = p;
58c2553a 163 PHOLD(pt);
3919ced0
MD
164 } else {
165 pt = pfind(uap->pid);
166 if (pt == NULL)
167 error = ESRCH;
168 }
169 if (error == 0)
170 uap->sysmsg_result = pt->p_session->s_sid;
58c2553a
MD
171 if (pt)
172 PRELE(pt);
3919ced0 173 return (error);
984263bc
MD
174}
175
176
177/*
3919ced0
MD
178 * getuid()
179 *
9910d07b 180 * MPSAFE
984263bc 181 */
984263bc 182int
753fd850 183sys_getuid(struct getuid_args *uap)
984263bc 184{
9910d07b 185 struct ucred *cred = curthread->td_ucred;
984263bc 186
9910d07b 187 uap->sysmsg_fds[0] = cred->cr_ruid;
984263bc 188#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
9910d07b 189 uap->sysmsg_fds[1] = cred->cr_uid;
984263bc
MD
190#endif
191 return (0);
192}
193
194/*
3919ced0
MD
195 * geteuid()
196 *
9910d07b 197 * MPSAFE
984263bc 198 */
984263bc 199int
753fd850 200sys_geteuid(struct geteuid_args *uap)
984263bc 201{
9910d07b 202 struct ucred *cred = curthread->td_ucred;
984263bc 203
9910d07b 204 uap->sysmsg_result = cred->cr_uid;
984263bc
MD
205 return (0);
206}
207
208/*
3919ced0
MD
209 * getgid()
210 *
9910d07b 211 * MPSAFE
984263bc 212 */
984263bc 213int
753fd850 214sys_getgid(struct getgid_args *uap)
984263bc 215{
9910d07b 216 struct ucred *cred = curthread->td_ucred;
984263bc 217
9910d07b 218 uap->sysmsg_fds[0] = cred->cr_rgid;
984263bc 219#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
9910d07b 220 uap->sysmsg_fds[1] = cred->cr_groups[0];
984263bc
MD
221#endif
222 return (0);
223}
224
225/*
226 * Get effective group ID. The "egid" is groups[0], and could be obtained
227 * via getgroups. This syscall exists because it is somewhat painful to do
228 * correctly in a library function.
6ad3ed15 229 *
3919ced0 230 * MPSAFE
984263bc 231 */
984263bc 232int
753fd850 233sys_getegid(struct getegid_args *uap)
984263bc 234{
9910d07b 235 struct ucred *cred = curthread->td_ucred;
984263bc 236
9910d07b 237 uap->sysmsg_result = cred->cr_groups[0];
984263bc
MD
238 return (0);
239}
240
3919ced0
MD
241/*
242 * MPSAFE
243 */
984263bc 244int
753fd850 245sys_getgroups(struct getgroups_args *uap)
984263bc 246{
41c20dac
MD
247 struct ucred *cr;
248 u_int ngrp;
984263bc
MD
249 int error;
250
9910d07b 251 cr = curthread->td_ucred;
984263bc 252 if ((ngrp = uap->gidsetsize) == 0) {
c7114eea 253 uap->sysmsg_result = cr->cr_ngroups;
984263bc
MD
254 return (0);
255 }
41c20dac 256 if (ngrp < cr->cr_ngroups)
984263bc 257 return (EINVAL);
41c20dac 258 ngrp = cr->cr_ngroups;
3919ced0
MD
259 error = copyout((caddr_t)cr->cr_groups,
260 (caddr_t)uap->gidset, ngrp * sizeof(gid_t));
261 if (error == 0)
262 uap->sysmsg_result = ngrp;
263 return (error);
984263bc
MD
264}
265
984263bc 266int
753fd850 267sys_setsid(struct setsid_args *uap)
984263bc 268{
41c20dac 269 struct proc *p = curproc;
58c2553a 270 struct pgrp *pg = NULL;
3919ced0 271 int error;
984263bc 272
58c2553a
MD
273 lwkt_gettoken(&p->p_token);
274 if (p->p_pgid == p->p_pid || (pg = pgfind(p->p_pid)) != NULL) {
3919ced0 275 error = EPERM;
58c2553a
MD
276 if (pg)
277 pgrel(pg);
984263bc 278 } else {
3919ced0 279 enterpgrp(p, p->p_pid, 1);
c7114eea 280 uap->sysmsg_result = p->p_pid;
3919ced0 281 error = 0;
984263bc 282 }
58c2553a 283 lwkt_reltoken(&p->p_token);
3919ced0 284 return (error);
984263bc
MD
285}
286
287/*
288 * set process group (setpgid/old setpgrp)
289 *
290 * caller does setpgid(targpid, targpgid)
291 *
292 * pid must be caller or child of caller (ESRCH)
293 * if a child
294 * pid must be in same session (EPERM)
295 * pid can't have done an exec (EACCES)
296 * if pgid != pid
297 * there must exist some pid in same session having pgid (EPERM)
298 * pid must not be session leader (EPERM)
299 */
984263bc 300int
753fd850 301sys_setpgid(struct setpgid_args *uap)
984263bc 302{
41c20dac
MD
303 struct proc *curp = curproc;
304 struct proc *targp; /* target process */
58c2553a 305 struct pgrp *pgrp = NULL; /* target pgrp */
3919ced0 306 int error;
984263bc
MD
307
308 if (uap->pgid < 0)
309 return (EINVAL);
3919ced0 310
984263bc 311 if (uap->pid != 0 && uap->pid != curp->p_pid) {
58c2553a
MD
312 if ((targp = pfind(uap->pid)) == NULL || !inferior(targp)) {
313 if (targp)
314 PRELE(targp);
3919ced0 315 error = ESRCH;
58c2553a 316 targp = NULL;
3919ced0
MD
317 goto done;
318 }
58c2553a
MD
319 lwkt_gettoken(&targp->p_token);
320 /* targp now referenced and its token is held */
321
3919ced0
MD
322 if (targp->p_pgrp == NULL ||
323 targp->p_session != curp->p_session) {
324 error = EPERM;
325 goto done;
326 }
4643740a 327 if (targp->p_flags & P_EXEC) {
3919ced0
MD
328 error = EACCES;
329 goto done;
330 }
331 } else {
984263bc 332 targp = curp;
58c2553a
MD
333 PHOLD(targp);
334 lwkt_gettoken(&targp->p_token);
3919ced0
MD
335 }
336 if (SESS_LEADER(targp)) {
337 error = EPERM;
338 goto done;
339 }
340 if (uap->pgid == 0) {
984263bc 341 uap->pgid = targp->p_pid;
3919ced0 342 } else if (uap->pgid != targp->p_pid) {
58c2553a 343 if ((pgrp = pgfind(uap->pgid)) == NULL ||
3919ced0
MD
344 pgrp->pg_session != curp->p_session) {
345 error = EPERM;
346 goto done;
347 }
348 }
349 error = enterpgrp(targp, uap->pgid, 0);
350done:
58c2553a
MD
351 if (pgrp)
352 pgrel(pgrp);
353 if (targp) {
354 lwkt_reltoken(&targp->p_token);
355 PRELE(targp);
356 }
3919ced0 357 return (error);
984263bc
MD
358}
359
360/*
361 * Use the clause in B.4.2.2 that allows setuid/setgid to be 4.2/4.3BSD
9a7c6212 362 * compatible. It says that setting the uid/gid to euid/egid is a special
984263bc
MD
363 * case of "appropriate privilege". Once the rules are expanded out, this
364 * basically means that setuid(nnn) sets all three id's, in all permitted
365 * cases unless _POSIX_SAVED_IDS is enabled. In that case, setuid(getuid())
366 * does not set the saved id - this is dangerous for traditional BSD
367 * programs. For this reason, we *really* do not want to set
368 * _POSIX_SAVED_IDS and do not want to clear POSIX_APPENDIX_B_4_2_2.
369 */
370#define POSIX_APPENDIX_B_4_2_2
371
984263bc 372int
753fd850 373sys_setuid(struct setuid_args *uap)
984263bc 374{
41c20dac
MD
375 struct proc *p = curproc;
376 struct ucred *cr;
377 uid_t uid;
984263bc
MD
378 int error;
379
ccd05f15 380 lwkt_gettoken(&proc_token);
41c20dac
MD
381 cr = p->p_ucred;
382
984263bc
MD
383 /*
384 * See if we have "permission" by POSIX 1003.1 rules.
385 *
386 * Note that setuid(geteuid()) is a special case of
387 * "appropriate privileges" in appendix B.4.2.2. We need
9a7c6212 388 * to use this clause to be compatible with traditional BSD
984263bc
MD
389 * semantics. Basically, it means that "setuid(xx)" sets all
390 * three id's (assuming you have privs).
391 *
392 * Notes on the logic. We do things in three steps.
393 * 1: We determine if the euid is going to change, and do EPERM
394 * right away. We unconditionally change the euid later if this
395 * test is satisfied, simplifying that part of the logic.
396 * 2: We determine if the real and/or saved uid's are going to
397 * change. Determined by compile options.
398 * 3: Change euid last. (after tests in #2 for "appropriate privs")
399 */
400 uid = uap->uid;
41c20dac 401 if (uid != cr->cr_ruid && /* allow setuid(getuid()) */
984263bc 402#ifdef _POSIX_SAVED_IDS
41c20dac 403 uid != crc->cr_svuid && /* allow setuid(saved gid) */
984263bc
MD
404#endif
405#ifdef POSIX_APPENDIX_B_4_2_2 /* Use BSD-compat clause from B.4.2.2 */
41c20dac 406 uid != cr->cr_uid && /* allow setuid(geteuid()) */
984263bc 407#endif
3a591c90 408 (error = priv_check_cred(cr, PRIV_CRED_SETUID, 0)))
3919ced0 409 goto done;
984263bc
MD
410
411#ifdef _POSIX_SAVED_IDS
412 /*
413 * Do we have "appropriate privileges" (are we root or uid == euid)
414 * If so, we are changing the real uid and/or saved uid.
415 */
416 if (
417#ifdef POSIX_APPENDIX_B_4_2_2 /* Use the clause from B.4.2.2 */
41c20dac 418 uid == cr->cr_uid ||
984263bc 419#endif
3a591c90 420 priv_check_cred(cr, PRIV_CRED_SETUID, 0) == 0) /* we are using privs */
984263bc
MD
421#endif
422 {
423 /*
424 * Set the real uid and transfer proc count to new user.
425 */
41c20dac 426 if (uid != cr->cr_ruid) {
be170d6b 427 cr = change_ruid(uid);
41c20dac 428 setsugid();
984263bc
MD
429 }
430 /*
431 * Set saved uid
432 *
433 * XXX always set saved uid even if not _POSIX_SAVED_IDS, as
434 * the security of seteuid() depends on it. B.4.2.2 says it
435 * is important that we should do this.
436 */
41c20dac 437 if (cr->cr_svuid != uid) {
115ccd83 438 cr = cratom(&p->p_ucred);
41c20dac
MD
439 cr->cr_svuid = uid;
440 setsugid();
984263bc
MD
441 }
442 }
443
444 /*
445 * In all permitted cases, we are changing the euid.
446 * Copy credentials so other references do not see our changes.
447 */
41c20dac
MD
448 if (cr->cr_uid != uid) {
449 change_euid(uid);
450 setsugid();
984263bc 451 }
3919ced0
MD
452 error = 0;
453done:
ccd05f15 454 lwkt_reltoken(&proc_token);
3919ced0 455 return (error);
984263bc
MD
456}
457
984263bc 458int
753fd850 459sys_seteuid(struct seteuid_args *uap)
984263bc 460{
41c20dac
MD
461 struct proc *p = curproc;
462 struct ucred *cr;
463 uid_t euid;
984263bc
MD
464 int error;
465
ccd05f15 466 lwkt_gettoken(&proc_token);
41c20dac 467 cr = p->p_ucred;
984263bc 468 euid = uap->euid;
41c20dac
MD
469 if (euid != cr->cr_ruid && /* allow seteuid(getuid()) */
470 euid != cr->cr_svuid && /* allow seteuid(saved uid) */
3919ced0 471 (error = priv_check_cred(cr, PRIV_CRED_SETEUID, 0))) {
ccd05f15 472 lwkt_reltoken(&proc_token);
984263bc 473 return (error);
3919ced0
MD
474 }
475
984263bc
MD
476 /*
477 * Everything's okay, do it. Copy credentials so other references do
478 * not see our changes.
479 */
41c20dac
MD
480 if (cr->cr_uid != euid) {
481 change_euid(euid);
482 setsugid();
984263bc 483 }
ccd05f15 484 lwkt_reltoken(&proc_token);
984263bc
MD
485 return (0);
486}
487
984263bc 488int
753fd850 489sys_setgid(struct setgid_args *uap)
984263bc 490{
41c20dac
MD
491 struct proc *p = curproc;
492 struct ucred *cr;
493 gid_t gid;
984263bc
MD
494 int error;
495
ccd05f15 496 lwkt_gettoken(&proc_token);
41c20dac
MD
497 cr = p->p_ucred;
498
984263bc
MD
499 /*
500 * See if we have "permission" by POSIX 1003.1 rules.
501 *
502 * Note that setgid(getegid()) is a special case of
503 * "appropriate privileges" in appendix B.4.2.2. We need
9a7c6212 504 * to use this clause to be compatible with traditional BSD
984263bc
MD
505 * semantics. Basically, it means that "setgid(xx)" sets all
506 * three id's (assuming you have privs).
507 *
508 * For notes on the logic here, see setuid() above.
509 */
510 gid = uap->gid;
41c20dac 511 if (gid != cr->cr_rgid && /* allow setgid(getgid()) */
984263bc 512#ifdef _POSIX_SAVED_IDS
41c20dac 513 gid != cr->cr_svgid && /* allow setgid(saved gid) */
984263bc
MD
514#endif
515#ifdef POSIX_APPENDIX_B_4_2_2 /* Use BSD-compat clause from B.4.2.2 */
41c20dac 516 gid != cr->cr_groups[0] && /* allow setgid(getegid()) */
984263bc 517#endif
3919ced0
MD
518 (error = priv_check_cred(cr, PRIV_CRED_SETGID, 0))) {
519 goto done;
520 }
984263bc
MD
521
522#ifdef _POSIX_SAVED_IDS
523 /*
524 * Do we have "appropriate privileges" (are we root or gid == egid)
525 * If so, we are changing the real uid and saved gid.
526 */
527 if (
528#ifdef POSIX_APPENDIX_B_4_2_2 /* use the clause from B.4.2.2 */
41c20dac 529 gid == cr->cr_groups[0] ||
984263bc 530#endif
3a591c90 531 priv_check_cred(cr, PRIV_CRED_SETGID, 0) == 0) /* we are using privs */
984263bc
MD
532#endif
533 {
534 /*
535 * Set real gid
536 */
41c20dac 537 if (cr->cr_rgid != gid) {
115ccd83 538 cr = cratom(&p->p_ucred);
41c20dac
MD
539 cr->cr_rgid = gid;
540 setsugid();
984263bc
MD
541 }
542 /*
543 * Set saved gid
544 *
545 * XXX always set saved gid even if not _POSIX_SAVED_IDS, as
546 * the security of setegid() depends on it. B.4.2.2 says it
547 * is important that we should do this.
548 */
41c20dac 549 if (cr->cr_svgid != gid) {
115ccd83 550 cr = cratom(&p->p_ucred);
41c20dac
MD
551 cr->cr_svgid = gid;
552 setsugid();
984263bc
MD
553 }
554 }
555 /*
556 * In all cases permitted cases, we are changing the egid.
557 * Copy credentials so other references do not see our changes.
558 */
41c20dac 559 if (cr->cr_groups[0] != gid) {
e9a372eb 560 cr = cratom(&p->p_ucred);
41c20dac
MD
561 cr->cr_groups[0] = gid;
562 setsugid();
984263bc 563 }
3919ced0
MD
564 error = 0;
565done:
ccd05f15 566 lwkt_reltoken(&proc_token);
3919ced0 567 return (error);
984263bc
MD
568}
569
984263bc 570int
753fd850 571sys_setegid(struct setegid_args *uap)
984263bc 572{
41c20dac
MD
573 struct proc *p = curproc;
574 struct ucred *cr;
575 gid_t egid;
984263bc
MD
576 int error;
577
ccd05f15 578 lwkt_gettoken(&proc_token);
41c20dac 579 cr = p->p_ucred;
984263bc 580 egid = uap->egid;
41c20dac
MD
581 if (egid != cr->cr_rgid && /* allow setegid(getgid()) */
582 egid != cr->cr_svgid && /* allow setegid(saved gid) */
3919ced0
MD
583 (error = priv_check_cred(cr, PRIV_CRED_SETEGID, 0))) {
584 goto done;
585 }
41c20dac 586 if (cr->cr_groups[0] != egid) {
e9a372eb 587 cr = cratom(&p->p_ucred);
41c20dac
MD
588 cr->cr_groups[0] = egid;
589 setsugid();
984263bc 590 }
3919ced0
MD
591 error = 0;
592done:
ccd05f15 593 lwkt_reltoken(&proc_token);
3919ced0 594 return (error);
984263bc
MD
595}
596
984263bc 597int
753fd850 598sys_setgroups(struct setgroups_args *uap)
984263bc 599{
41c20dac
MD
600 struct proc *p = curproc;
601 struct ucred *cr;
602 u_int ngrp;
984263bc
MD
603 int error;
604
ccd05f15 605 lwkt_gettoken(&proc_token);
41c20dac
MD
606 cr = p->p_ucred;
607
3a591c90 608 if ((error = priv_check_cred(cr, PRIV_CRED_SETGROUPS, 0)))
3919ced0 609 goto done;
984263bc 610 ngrp = uap->gidsetsize;
3919ced0
MD
611 if (ngrp > NGROUPS) {
612 error = EINVAL;
613 goto done;
614 }
984263bc
MD
615 /*
616 * XXX A little bit lazy here. We could test if anything has
e9a372eb 617 * changed before cratom() and setting P_SUGID.
984263bc 618 */
e9a372eb 619 cr = cratom(&p->p_ucred);
984263bc
MD
620 if (ngrp < 1) {
621 /*
622 * setgroups(0, NULL) is a legitimate way of clearing the
623 * groups vector on non-BSD systems (which generally do not
624 * have the egid in the groups[0]). We risk security holes
625 * when running non-BSD software if we do not do the same.
626 */
41c20dac 627 cr->cr_ngroups = 1;
984263bc 628 } else {
3919ced0
MD
629 error = copyin(uap->gidset, cr->cr_groups,
630 ngrp * sizeof(gid_t));
631 if (error)
632 goto done;
41c20dac 633 cr->cr_ngroups = ngrp;
984263bc 634 }
41c20dac 635 setsugid();
3919ced0
MD
636 error = 0;
637done:
ccd05f15 638 lwkt_reltoken(&proc_token);
3919ced0 639 return (error);
984263bc
MD
640}
641
984263bc 642int
753fd850 643sys_setreuid(struct setreuid_args *uap)
984263bc 644{
41c20dac
MD
645 struct proc *p = curproc;
646 struct ucred *cr;
647 uid_t ruid, euid;
984263bc
MD
648 int error;
649
ccd05f15 650 lwkt_gettoken(&proc_token);
41c20dac
MD
651 cr = p->p_ucred;
652
984263bc
MD
653 ruid = uap->ruid;
654 euid = uap->euid;
41c20dac
MD
655 if (((ruid != (uid_t)-1 && ruid != cr->cr_ruid && ruid != cr->cr_svuid) ||
656 (euid != (uid_t)-1 && euid != cr->cr_uid &&
657 euid != cr->cr_ruid && euid != cr->cr_svuid)) &&
3919ced0
MD
658 (error = priv_check_cred(cr, PRIV_CRED_SETREUID, 0)) != 0) {
659 goto done;
660 }
984263bc 661
41c20dac 662 if (euid != (uid_t)-1 && cr->cr_uid != euid) {
be170d6b 663 cr = change_euid(euid);
41c20dac 664 setsugid();
984263bc 665 }
41c20dac 666 if (ruid != (uid_t)-1 && cr->cr_ruid != ruid) {
be170d6b 667 cr = change_ruid(ruid);
41c20dac 668 setsugid();
984263bc 669 }
41c20dac
MD
670 if ((ruid != (uid_t)-1 || cr->cr_uid != cr->cr_ruid) &&
671 cr->cr_svuid != cr->cr_uid) {
e9a372eb 672 cr = cratom(&p->p_ucred);
41c20dac
MD
673 cr->cr_svuid = cr->cr_uid;
674 setsugid();
984263bc 675 }
3919ced0
MD
676 error = 0;
677done:
ccd05f15 678 lwkt_reltoken(&proc_token);
3919ced0 679 return (error);
984263bc
MD
680}
681
984263bc 682int
753fd850 683sys_setregid(struct setregid_args *uap)
984263bc 684{
41c20dac
MD
685 struct proc *p = curproc;
686 struct ucred *cr;
687 gid_t rgid, egid;
984263bc
MD
688 int error;
689
ccd05f15 690 lwkt_gettoken(&proc_token);
41c20dac
MD
691 cr = p->p_ucred;
692
984263bc
MD
693 rgid = uap->rgid;
694 egid = uap->egid;
41c20dac
MD
695 if (((rgid != (gid_t)-1 && rgid != cr->cr_rgid && rgid != cr->cr_svgid) ||
696 (egid != (gid_t)-1 && egid != cr->cr_groups[0] &&
697 egid != cr->cr_rgid && egid != cr->cr_svgid)) &&
3919ced0
MD
698 (error = priv_check_cred(cr, PRIV_CRED_SETREGID, 0)) != 0) {
699 goto done;
700 }
984263bc 701
41c20dac 702 if (egid != (gid_t)-1 && cr->cr_groups[0] != egid) {
e9a372eb 703 cr = cratom(&p->p_ucred);
41c20dac
MD
704 cr->cr_groups[0] = egid;
705 setsugid();
984263bc 706 }
41c20dac 707 if (rgid != (gid_t)-1 && cr->cr_rgid != rgid) {
e9a372eb 708 cr = cratom(&p->p_ucred);
41c20dac
MD
709 cr->cr_rgid = rgid;
710 setsugid();
984263bc 711 }
41c20dac
MD
712 if ((rgid != (gid_t)-1 || cr->cr_groups[0] != cr->cr_rgid) &&
713 cr->cr_svgid != cr->cr_groups[0]) {
e9a372eb 714 cr = cratom(&p->p_ucred);
41c20dac
MD
715 cr->cr_svgid = cr->cr_groups[0];
716 setsugid();
984263bc 717 }
3919ced0
MD
718 error = 0;
719done:
ccd05f15 720 lwkt_reltoken(&proc_token);
3919ced0 721 return (error);
984263bc
MD
722}
723
724/*
725 * setresuid(ruid, euid, suid) is like setreuid except control over the
726 * saved uid is explicit.
727 */
984263bc 728int
753fd850 729sys_setresuid(struct setresuid_args *uap)
984263bc 730{
41c20dac
MD
731 struct proc *p = curproc;
732 struct ucred *cr;
733 uid_t ruid, euid, suid;
984263bc
MD
734 int error;
735
ccd05f15 736 lwkt_gettoken(&proc_token);
41c20dac 737 cr = p->p_ucred;
3919ced0 738
984263bc
MD
739 ruid = uap->ruid;
740 euid = uap->euid;
741 suid = uap->suid;
41c20dac
MD
742 if (((ruid != (uid_t)-1 && ruid != cr->cr_ruid && ruid != cr->cr_svuid &&
743 ruid != cr->cr_uid) ||
744 (euid != (uid_t)-1 && euid != cr->cr_ruid && euid != cr->cr_svuid &&
745 euid != cr->cr_uid) ||
746 (suid != (uid_t)-1 && suid != cr->cr_ruid && suid != cr->cr_svuid &&
747 suid != cr->cr_uid)) &&
3919ced0
MD
748 (error = priv_check_cred(cr, PRIV_CRED_SETRESUID, 0)) != 0) {
749 goto done;
750 }
41c20dac 751 if (euid != (uid_t)-1 && cr->cr_uid != euid) {
be170d6b 752 cr = change_euid(euid);
41c20dac 753 setsugid();
984263bc 754 }
41c20dac 755 if (ruid != (uid_t)-1 && cr->cr_ruid != ruid) {
be170d6b 756 cr = change_ruid(ruid);
41c20dac 757 setsugid();
984263bc 758 }
41c20dac 759 if (suid != (uid_t)-1 && cr->cr_svuid != suid) {
e9a372eb 760 cr = cratom(&p->p_ucred);
41c20dac
MD
761 cr->cr_svuid = suid;
762 setsugid();
984263bc 763 }
3919ced0
MD
764 error = 0;
765done:
ccd05f15 766 lwkt_reltoken(&proc_token);
3919ced0 767 return (error);
984263bc
MD
768}
769
770/*
771 * setresgid(rgid, egid, sgid) is like setregid except control over the
772 * saved gid is explicit.
773 */
984263bc 774int
753fd850 775sys_setresgid(struct setresgid_args *uap)
984263bc 776{
41c20dac
MD
777 struct proc *p = curproc;
778 struct ucred *cr;
779 gid_t rgid, egid, sgid;
984263bc
MD
780 int error;
781
ccd05f15 782 lwkt_gettoken(&proc_token);
41c20dac 783 cr = p->p_ucred;
984263bc
MD
784 rgid = uap->rgid;
785 egid = uap->egid;
786 sgid = uap->sgid;
41c20dac
MD
787 if (((rgid != (gid_t)-1 && rgid != cr->cr_rgid && rgid != cr->cr_svgid &&
788 rgid != cr->cr_groups[0]) ||
789 (egid != (gid_t)-1 && egid != cr->cr_rgid && egid != cr->cr_svgid &&
790 egid != cr->cr_groups[0]) ||
791 (sgid != (gid_t)-1 && sgid != cr->cr_rgid && sgid != cr->cr_svgid &&
792 sgid != cr->cr_groups[0])) &&
3919ced0
MD
793 (error = priv_check_cred(cr, PRIV_CRED_SETRESGID, 0)) != 0) {
794 goto done;
795 }
984263bc 796
41c20dac 797 if (egid != (gid_t)-1 && cr->cr_groups[0] != egid) {
e9a372eb 798 cr = cratom(&p->p_ucred);
41c20dac
MD
799 cr->cr_groups[0] = egid;
800 setsugid();
984263bc 801 }
41c20dac 802 if (rgid != (gid_t)-1 && cr->cr_rgid != rgid) {
e9a372eb 803 cr = cratom(&p->p_ucred);
41c20dac
MD
804 cr->cr_rgid = rgid;
805 setsugid();
984263bc 806 }
41c20dac 807 if (sgid != (gid_t)-1 && cr->cr_svgid != sgid) {
e9a372eb 808 cr = cratom(&p->p_ucred);
41c20dac
MD
809 cr->cr_svgid = sgid;
810 setsugid();
984263bc 811 }
3919ced0
MD
812 error = 0;
813done:
ccd05f15 814 lwkt_reltoken(&proc_token);
3919ced0 815 return (error);
984263bc
MD
816}
817
984263bc 818int
753fd850 819sys_getresuid(struct getresuid_args *uap)
984263bc 820{
41c20dac 821 struct proc *p = curproc;
3919ced0 822 struct ucred *cr;
984263bc
MD
823 int error1 = 0, error2 = 0, error3 = 0;
824
ccd05f15 825 lwkt_gettoken(&proc_token);
3919ced0 826 cr = p->p_ucred;
984263bc 827 if (uap->ruid)
41c20dac
MD
828 error1 = copyout((caddr_t)&cr->cr_ruid,
829 (caddr_t)uap->ruid, sizeof(cr->cr_ruid));
984263bc 830 if (uap->euid)
41c20dac
MD
831 error2 = copyout((caddr_t)&cr->cr_uid,
832 (caddr_t)uap->euid, sizeof(cr->cr_uid));
984263bc 833 if (uap->suid)
41c20dac
MD
834 error3 = copyout((caddr_t)&cr->cr_svuid,
835 (caddr_t)uap->suid, sizeof(cr->cr_svuid));
ccd05f15 836 lwkt_reltoken(&proc_token);
984263bc
MD
837 return error1 ? error1 : (error2 ? error2 : error3);
838}
839
3919ced0 840/*
9910d07b 841 * MPSAFE
3919ced0 842 */
984263bc 843int
753fd850 844sys_getresgid(struct getresgid_args *uap)
984263bc 845{
3919ced0 846 struct ucred *cr;
984263bc
MD
847 int error1 = 0, error2 = 0, error3 = 0;
848
9910d07b 849 cr = curthread->td_ucred;
984263bc 850 if (uap->rgid)
9910d07b
MD
851 error1 = copyout(&cr->cr_rgid, uap->rgid,
852 sizeof(cr->cr_rgid));
984263bc 853 if (uap->egid)
9910d07b
MD
854 error2 = copyout(&cr->cr_groups[0], uap->egid,
855 sizeof(cr->cr_groups[0]));
984263bc 856 if (uap->sgid)
9910d07b
MD
857 error3 = copyout(&cr->cr_svgid, uap->sgid,
858 sizeof(cr->cr_svgid));
984263bc
MD
859 return error1 ? error1 : (error2 ? error2 : error3);
860}
861
862
3919ced0
MD
863/*
864 * NOTE: OpenBSD sets a P_SUGIDEXEC flag set at execve() time,
865 * we use P_SUGID because we consider changing the owners as
866 * "tainting" as well.
867 * This is significant for procs that start as root and "become"
868 * a user without an exec - programs cannot know *everything*
869 * that libc *might* have put in their data segment.
870 *
871 * MPSAFE
872 */
984263bc 873int
753fd850 874sys_issetugid(struct issetugid_args *uap)
984263bc 875{
4643740a 876 uap->sysmsg_result = (curproc->p_flags & P_SUGID) ? 1 : 0;
984263bc
MD
877 return (0);
878}
879
880/*
881 * Check if gid is a member of the group set.
882 */
883int
41c20dac 884groupmember(gid_t gid, struct ucred *cred)
984263bc 885{
41c20dac 886 gid_t *gp;
984263bc
MD
887 gid_t *egp;
888
889 egp = &(cred->cr_groups[cred->cr_ngroups]);
4f645dbb 890 for (gp = cred->cr_groups; gp < egp; gp++) {
984263bc
MD
891 if (*gp == gid)
892 return (1);
4f645dbb 893 }
984263bc
MD
894 return (0);
895}
896
897/*
d46b588e
MN
898 * Test whether the specified credentials have the privilege
899 * in question.
900 *
901 * A kernel thread without a process context is assumed to have
902 * the privilege in question. In situations where the caller always
903 * expect a cred to exist, the cred should be passed separately and
904 * priv_check_cred() should be used instead of priv_check().
dadab5e9 905 *
984263bc 906 * Returns 0 or error.
1ee6e3c6
MD
907 *
908 * MPSAFE
984263bc
MD
909 */
910int
d46b588e 911priv_check(struct thread *td, int priv)
984263bc 912{
9910d07b
MD
913 if (td->td_lwp != NULL)
914 return priv_check_cred(td->td_ucred, priv, 0);
915 return (0);
984263bc
MD
916}
917
e4700d00 918/*
d46b588e
MN
919 * Check a credential for privilege.
920 *
e4700d00 921 * A non-null credential is expected unless NULL_CRED_OKAY is set.
1ee6e3c6
MD
922 *
923 * MPSAFE
e4700d00 924 */
984263bc 925int
d46b588e 926priv_check_cred(struct ucred *cred, int priv, int flags)
984263bc 927{
cd554aa4
MN
928 int error;
929
d46b588e
MN
930 KASSERT(PRIV_VALID(priv), ("priv_check_cred: invalid privilege"));
931
932 KASSERT(cred != NULL || flags & NULL_CRED_OKAY,
933 ("priv_check_cred: NULL cred!"));
41c20dac 934
e4700d00 935 if (cred == NULL) {
d46b588e 936 if (flags & NULL_CRED_OKAY)
e4700d00
JH
937 return (0);
938 else
939 return (EPERM);
940 }
984263bc
MD
941 if (cred->cr_uid != 0)
942 return (EPERM);
cd554aa4 943
1b6db7be
MN
944 error = prison_priv_check(cred, priv);
945 if (error)
946 return (error);
cd554aa4 947
dadab5e9 948 /* NOTE: accounting for suser access (p_acflag/ASU) removed */
984263bc
MD
949 return (0);
950}
951
952/*
953 * Return zero if p1 can fondle p2, return errno (EPERM/ESRCH) otherwise.
954 */
984263bc 955int
41c20dac 956p_trespass(struct ucred *cr1, struct ucred *cr2)
984263bc 957{
41c20dac 958 if (cr1 == cr2)
984263bc 959 return (0);
41c20dac 960 if (!PRISON_CHECK(cr1, cr2))
984263bc 961 return (ESRCH);
41c20dac 962 if (cr1->cr_ruid == cr2->cr_ruid)
984263bc 963 return (0);
41c20dac 964 if (cr1->cr_uid == cr2->cr_ruid)
984263bc 965 return (0);
41c20dac 966 if (cr1->cr_ruid == cr2->cr_uid)
984263bc 967 return (0);
41c20dac 968 if (cr1->cr_uid == cr2->cr_uid)
984263bc 969 return (0);
14272f2d 970 if (priv_check_cred(cr1, PRIV_PROC_TRESPASS, 0) == 0)
984263bc
MD
971 return (0);
972 return (EPERM);
973}
974
975/*
d9b2033e
MD
976 * MPSAFE
977 */
978static __inline void
979_crinit(struct ucred *cr)
980{
d9b2033e 981 cr->cr_ref = 1;
d9b2033e
MD
982}
983
984/*
985 * MPSAFE
986 */
987void
988crinit(struct ucred *cr)
989{
4eee9a80 990 bzero(cr, sizeof(*cr));
d9b2033e
MD
991 _crinit(cr);
992}
993
994/*
984263bc 995 * Allocate a zeroed cred structure.
d9b2033e
MD
996 *
997 * MPSAFE
984263bc
MD
998 */
999struct ucred *
77153250 1000crget(void)
984263bc 1001{
1fd87d54 1002 struct ucred *cr;
984263bc 1003
4eee9a80 1004 cr = kmalloc(sizeof(*cr), M_CRED, M_WAITOK|M_ZERO);
d9b2033e 1005 _crinit(cr);
984263bc
MD
1006 return (cr);
1007}
1008
1009/*
e9a372eb
MD
1010 * Claim another reference to a ucred structure. Can be used with special
1011 * creds.
d9b2033e
MD
1012 *
1013 * It must be possible to call this routine with spinlocks held, meaning
1014 * that this routine itself cannot obtain a spinlock.
1015 *
1016 * MPSAFE
984263bc 1017 */
dadab5e9 1018struct ucred *
41c20dac 1019crhold(struct ucred *cr)
984263bc 1020{
e9a372eb 1021 if (cr != NOCRED && cr != FSCRED)
d9b2033e 1022 atomic_add_int(&cr->cr_ref, 1);
dadab5e9 1023 return(cr);
984263bc
MD
1024}
1025
1026/*
d9b2033e
MD
1027 * Drop a reference from the cred structure, free it if the reference count
1028 * reaches 0.
1029 *
1030 * NOTE: because we used atomic_add_int() above, without a spinlock, we
1031 * must also use atomic_subtract_int() below. A spinlock is required
1032 * in crfree() to handle multiple callers racing the refcount to 0.
1033 *
61f96b6f 1034 * MPSAFE
984263bc
MD
1035 */
1036void
41c20dac 1037crfree(struct ucred *cr)
984263bc 1038{
d9b2033e 1039 if (cr->cr_ref <= 0)
984263bc 1040 panic("Freeing already free credential! %p", cr);
61f96b6f 1041 if (atomic_fetchadd_int(&cr->cr_ref, -1) == 1) {
984263bc
MD
1042 /*
1043 * Some callers of crget(), such as nfs_statfs(),
1044 * allocate a temporary credential, but don't
1045 * allocate a uidinfo structure.
1046 */
792033e7
MD
1047 if (cr->cr_uidinfo != NULL) {
1048 uidrop(cr->cr_uidinfo);
1049 cr->cr_uidinfo = NULL;
1050 }
1051 if (cr->cr_ruidinfo != NULL) {
1052 uidrop(cr->cr_ruidinfo);
1053 cr->cr_ruidinfo = NULL;
1054 }
41c20dac
MD
1055
1056 /*
1057 * Destroy empty prisons
1058 */
b40e316c
JS
1059 if (jailed(cr))
1060 prison_free(cr->cr_prison);
41c20dac
MD
1061 cr->cr_prison = NULL; /* safety */
1062
984263bc
MD
1063 FREE((caddr_t)cr, M_CRED);
1064 }
1065}
1066
1067/*
e9a372eb
MD
1068 * Atomize a cred structure so it can be modified without polluting
1069 * other references to it.
61f96b6f
MD
1070 *
1071 * MPSAFE (however, *pcr must be stable)
e9a372eb
MD
1072 */
1073struct ucred *
1074cratom(struct ucred **pcr)
1075{
1076 struct ucred *oldcr;
1077 struct ucred *newcr;
1078
1079 oldcr = *pcr;
1080 if (oldcr->cr_ref == 1)
1081 return (oldcr);
1082 newcr = crget();
1083 *newcr = *oldcr;
1084 if (newcr->cr_uidinfo)
1085 uihold(newcr->cr_uidinfo);
1086 if (newcr->cr_ruidinfo)
1087 uihold(newcr->cr_ruidinfo);
b40e316c
JS
1088 if (jailed(newcr))
1089 prison_hold(newcr->cr_prison);
e9a372eb
MD
1090 newcr->cr_ref = 1;
1091 crfree(oldcr);
1092 *pcr = newcr;
1093 return (newcr);
1094}
1095
1096#if 0 /* no longer used but keep around for a little while */
1097/*
984263bc 1098 * Copy cred structure to a new one and free the old one.
61f96b6f
MD
1099 *
1100 * MPSAFE (*cr must be stable)
984263bc
MD
1101 */
1102struct ucred *
41c20dac 1103crcopy(struct ucred *cr)
984263bc
MD
1104{
1105 struct ucred *newcr;
1106
1107 if (cr->cr_ref == 1)
1108 return (cr);
1109 newcr = crget();
1110 *newcr = *cr;
41c20dac
MD
1111 if (newcr->cr_uidinfo)
1112 uihold(newcr->cr_uidinfo);
1113 if (newcr->cr_ruidinfo)
1114 uihold(newcr->cr_ruidinfo);
b40e316c
JS
1115 if (jailed(newcr))
1116 prison_hold(newcr->cr_prison);
984263bc 1117 newcr->cr_ref = 1;
41c20dac 1118 crfree(cr);
984263bc
MD
1119 return (newcr);
1120}
e9a372eb 1121#endif
984263bc
MD
1122
1123/*
1124 * Dup cred struct to a new held one.
1125 */
1126struct ucred *
77153250 1127crdup(struct ucred *cr)
984263bc
MD
1128{
1129 struct ucred *newcr;
1130
1131 newcr = crget();
1132 *newcr = *cr;
41c20dac
MD
1133 if (newcr->cr_uidinfo)
1134 uihold(newcr->cr_uidinfo);
1135 if (newcr->cr_ruidinfo)
1136 uihold(newcr->cr_ruidinfo);
b40e316c
JS
1137 if (jailed(newcr))
1138 prison_hold(newcr->cr_prison);
984263bc
MD
1139 newcr->cr_ref = 1;
1140 return (newcr);
1141}
1142
1143/*
1144 * Fill in a struct xucred based on a struct ucred.
1145 */
1146void
77153250 1147cru2x(struct ucred *cr, struct xucred *xcr)
984263bc
MD
1148{
1149
1150 bzero(xcr, sizeof(*xcr));
1151 xcr->cr_version = XUCRED_VERSION;
1152 xcr->cr_uid = cr->cr_uid;
1153 xcr->cr_ngroups = cr->cr_ngroups;
1154 bcopy(cr->cr_groups, xcr->cr_groups, sizeof(cr->cr_groups));
1155}
1156
1157/*
1158 * Get login name, if available.
1159 */
984263bc 1160int
753fd850 1161sys_getlogin(struct getlogin_args *uap)
984263bc 1162{
41c20dac 1163 struct proc *p = curproc;
3919ced0
MD
1164 char buf[MAXLOGNAME];
1165 int error;
984263bc 1166
3919ced0 1167 if (uap->namelen > MAXLOGNAME) /* namelen is unsigned */
984263bc 1168 uap->namelen = MAXLOGNAME;
3919ced0 1169 bzero(buf, sizeof(buf));
ccd05f15 1170 lwkt_gettoken(&proc_token);
3919ced0 1171 bcopy(p->p_pgrp->pg_session->s_login, buf, uap->namelen);
ccd05f15 1172 lwkt_reltoken(&proc_token);
3919ced0
MD
1173
1174 error = copyout(buf, uap->namebuf, uap->namelen);
1175 return (error);
984263bc
MD
1176}
1177
1178/*
1179 * Set login name.
1180 */
984263bc 1181int
753fd850 1182sys_setlogin(struct setlogin_args *uap)
984263bc 1183{
9910d07b
MD
1184 struct thread *td = curthread;
1185 struct proc *p;
1186 struct ucred *cred;
3919ced0 1187 char buf[MAXLOGNAME];
984263bc 1188 int error;
984263bc 1189
9910d07b
MD
1190 cred = td->td_ucred;
1191 p = td->td_proc;
1192
1193 if ((error = priv_check_cred(cred, PRIV_PROC_SETLOGIN, 0)))
984263bc 1194 return (error);
3919ced0
MD
1195 bzero(buf, sizeof(buf));
1196 error = copyinstr(uap->namebuf, buf, sizeof(buf), NULL);
984263bc
MD
1197 if (error == ENAMETOOLONG)
1198 error = EINVAL;
3919ced0 1199 if (error == 0) {
ccd05f15 1200 lwkt_gettoken(&proc_token);
3919ced0 1201 memcpy(p->p_pgrp->pg_session->s_login, buf, sizeof(buf));
ccd05f15 1202 lwkt_reltoken(&proc_token);
3919ced0 1203 }
984263bc
MD
1204 return (error);
1205}
1206
1207void
77153250 1208setsugid(void)
984263bc 1209{
41c20dac
MD
1210 struct proc *p = curproc;
1211
1212 KKASSERT(p != NULL);
616516c8 1213 lwkt_gettoken(&p->p_token);
4643740a 1214 p->p_flags |= P_SUGID;
984263bc
MD
1215 if (!(p->p_pfsflags & PF_ISUGID))
1216 p->p_stops = 0;
616516c8 1217 lwkt_reltoken(&p->p_token);
984263bc
MD
1218}
1219
1220/*
1221 * Helper function to change the effective uid of a process
1222 */
be170d6b 1223struct ucred *
41c20dac 1224change_euid(uid_t euid)
984263bc 1225{
41c20dac
MD
1226 struct proc *p = curproc;
1227 struct ucred *cr;
984263bc 1228
41c20dac 1229 KKASSERT(p != NULL);
94507578 1230 lf_count_adjust(p, 0);
e9a372eb 1231 cr = cratom(&p->p_ucred);
41c20dac 1232 cr->cr_uid = euid;
792033e7 1233 uireplace(&cr->cr_uidinfo, uifind(euid));
94507578 1234 lf_count_adjust(p, 1);
be170d6b 1235 return (cr);
984263bc
MD
1236}
1237
1238/*
1239 * Helper function to change the real uid of a process
1240 *
1241 * The per-uid process count for this process is transfered from
1242 * the old uid to the new uid.
1243 */
be170d6b 1244struct ucred *
41c20dac 1245change_ruid(uid_t ruid)
984263bc 1246{
41c20dac
MD
1247 struct proc *p = curproc;
1248 struct ucred *cr;
984263bc 1249
41c20dac
MD
1250 KKASSERT(p != NULL);
1251
e9a372eb 1252 cr = cratom(&p->p_ucred);
be170d6b 1253 chgproccnt(cr->cr_ruidinfo, -1, 0);
41c20dac 1254 cr->cr_ruid = ruid;
792033e7 1255 uireplace(&cr->cr_ruidinfo, uifind(ruid));
be170d6b
SS
1256 chgproccnt(cr->cr_ruidinfo, 1, 0);
1257 return (cr);
984263bc 1258}