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