]>
Commit | Line | Data |
---|---|---|
1c79356b | 1 | /* |
55e303ae | 2 | * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved. |
1c79356b A |
3 | * |
4 | * @APPLE_LICENSE_HEADER_START@ | |
5 | * | |
43866e37 | 6 | * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. |
1c79356b | 7 | * |
43866e37 A |
8 | * This file contains Original Code and/or Modifications of Original Code |
9 | * as defined in and that are subject to the Apple Public Source License | |
10 | * Version 2.0 (the 'License'). You may not use this file except in | |
11 | * compliance with the License. Please obtain a copy of the License at | |
12 | * http://www.opensource.apple.com/apsl/ and read it before using this | |
13 | * file. | |
14 | * | |
15 | * The Original Code and all software distributed under the License are | |
16 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
1c79356b A |
17 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, |
18 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
43866e37 A |
19 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. |
20 | * Please see the License for the specific language governing rights and | |
21 | * limitations under the License. | |
1c79356b A |
22 | * |
23 | * @APPLE_LICENSE_HEADER_END@ | |
24 | */ | |
25 | /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */ | |
26 | /* | |
27 | * Copyright (c) 1982, 1986, 1989, 1990, 1991, 1993 | |
28 | * The Regents of the University of California. All rights reserved. | |
29 | * (c) UNIX System Laboratories, Inc. | |
30 | * All or some portions of this file are derived from material licensed | |
31 | * to the University of California by American Telephone and Telegraph | |
32 | * Co. or Unix System Laboratories, Inc. and are reproduced herein with | |
33 | * the permission of UNIX System Laboratories, Inc. | |
34 | * | |
35 | * Redistribution and use in source and binary forms, with or without | |
36 | * modification, are permitted provided that the following conditions | |
37 | * are met: | |
38 | * 1. Redistributions of source code must retain the above copyright | |
39 | * notice, this list of conditions and the following disclaimer. | |
40 | * 2. Redistributions in binary form must reproduce the above copyright | |
41 | * notice, this list of conditions and the following disclaimer in the | |
42 | * documentation and/or other materials provided with the distribution. | |
43 | * 3. All advertising materials mentioning features or use of this software | |
44 | * must display the following acknowledgement: | |
45 | * This product includes software developed by the University of | |
46 | * California, Berkeley and its contributors. | |
47 | * 4. Neither the name of the University nor the names of its contributors | |
48 | * may be used to endorse or promote products derived from this software | |
49 | * without specific prior written permission. | |
50 | * | |
51 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | |
52 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
53 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
54 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
55 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
56 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
57 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
58 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
59 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
60 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
61 | * SUCH DAMAGE. | |
62 | * | |
63 | * @(#)kern_prot.c 8.9 (Berkeley) 2/14/95 | |
64 | */ | |
65 | ||
66 | /* | |
67 | * System calls related to processes and protection | |
68 | */ | |
69 | ||
70 | #include <sys/param.h> | |
71 | #include <sys/acct.h> | |
72 | #include <sys/systm.h> | |
73 | #include <sys/ucred.h> | |
74 | #include <sys/proc.h> | |
75 | #include <sys/timeb.h> | |
76 | #include <sys/times.h> | |
77 | #include <sys/malloc.h> | |
55e303ae | 78 | #include <sys/kern_audit.h> |
1c79356b A |
79 | |
80 | #include <sys/mount.h> | |
81 | #include <mach/message.h> | |
9bccf70c A |
82 | #include <mach/host_security.h> |
83 | ||
1c79356b A |
84 | #include <kern/host.h> |
85 | ||
86 | /* | |
87 | * setprivexec: (dis)allow this process to hold | |
88 | * task, thread, or execption ports of processes about to exec. | |
89 | */ | |
90 | struct setprivexec_args { | |
91 | int flag; | |
92 | }; | |
93 | int | |
94 | setprivexec(p, uap, retval) | |
95 | struct proc *p; | |
96 | register struct setprivexec_args *uap; | |
97 | register_t *retval; | |
98 | { | |
99 | *retval = p->p_debugger; | |
100 | p->p_debugger = (uap->flag != 0); | |
101 | return(0); | |
102 | } | |
103 | ||
104 | /* ARGSUSED */ | |
105 | getpid(p, uap, retval) | |
106 | struct proc *p; | |
107 | void *uap; | |
108 | register_t *retval; | |
109 | { | |
110 | ||
111 | *retval = p->p_pid; | |
112 | #if COMPAT_43 | |
113 | retval[1] = p->p_pptr->p_pid; | |
114 | #endif | |
115 | return (0); | |
116 | } | |
117 | ||
118 | /* ARGSUSED */ | |
119 | getppid(p, uap, retval) | |
120 | struct proc *p; | |
121 | void *uap; | |
122 | register_t *retval; | |
123 | { | |
124 | ||
125 | *retval = p->p_pptr->p_pid; | |
126 | return (0); | |
127 | } | |
128 | ||
129 | /* Get process group ID; note that POSIX getpgrp takes no parameter */ | |
130 | getpgrp(p, uap, retval) | |
131 | struct proc *p; | |
132 | void *uap; | |
133 | register_t *retval; | |
134 | { | |
135 | ||
136 | *retval = p->p_pgrp->pg_id; | |
137 | return (0); | |
138 | } | |
139 | ||
9bccf70c A |
140 | /* Get an arbitary pid's process group id */ |
141 | struct getpgid_args { | |
142 | pid_t pid; | |
143 | }; | |
144 | ||
145 | int | |
146 | getpgid(p, uap, retval) | |
147 | struct proc *p; | |
148 | struct getpgid_args *uap; | |
149 | register_t *retval; | |
150 | { | |
151 | struct proc *pt; | |
152 | ||
153 | pt = p; | |
154 | if (uap->pid == 0) | |
155 | goto found; | |
156 | ||
157 | if ((pt = pfind(uap->pid)) == 0) | |
158 | return (ESRCH); | |
159 | found: | |
160 | *retval = pt->p_pgrp->pg_id; | |
161 | return (0); | |
162 | } | |
163 | ||
164 | /* | |
165 | * Get an arbitary pid's session id. | |
166 | */ | |
167 | struct getsid_args { | |
168 | pid_t pid; | |
169 | }; | |
170 | ||
171 | int | |
172 | getsid(p, uap, retval) | |
173 | struct proc *p; | |
174 | struct getsid_args *uap; | |
175 | register_t *retval; | |
176 | { | |
177 | struct proc *pt; | |
178 | ||
179 | pt = p; | |
180 | if (uap->pid == 0) | |
181 | goto found; | |
182 | ||
183 | if ((pt = pfind(uap->pid)) == 0) | |
184 | return (ESRCH); | |
185 | found: | |
186 | *retval = pt->p_session->s_sid; | |
187 | return (0); | |
188 | } | |
189 | ||
1c79356b A |
190 | /* ARGSUSED */ |
191 | getuid(p, uap, retval) | |
192 | struct proc *p; | |
193 | void *uap; | |
194 | register_t *retval; | |
195 | { | |
196 | ||
197 | *retval = p->p_cred->p_ruid; | |
198 | #if COMPAT_43 | |
199 | retval[1] = p->p_ucred->cr_uid; | |
200 | #endif | |
201 | return (0); | |
202 | } | |
203 | ||
204 | /* ARGSUSED */ | |
205 | geteuid(p, uap, retval) | |
206 | struct proc *p; | |
207 | void *uap; | |
208 | register_t *retval; | |
209 | { | |
210 | ||
211 | *retval = p->p_ucred->cr_uid; | |
212 | return (0); | |
213 | } | |
214 | ||
215 | /* ARGSUSED */ | |
216 | getgid(p, uap, retval) | |
217 | struct proc *p; | |
218 | void *uap; | |
219 | register_t *retval; | |
220 | { | |
221 | ||
222 | *retval = p->p_cred->p_rgid; | |
223 | #if COMPAT_43 | |
224 | retval[1] = p->p_ucred->cr_groups[0]; | |
225 | #endif | |
226 | return (0); | |
227 | } | |
228 | ||
229 | /* | |
230 | * Get effective group ID. The "egid" is groups[0], and could be obtained | |
231 | * via getgroups. This syscall exists because it is somewhat painful to do | |
232 | * correctly in a library function. | |
233 | */ | |
234 | /* ARGSUSED */ | |
235 | getegid(p, uap, retval) | |
236 | struct proc *p; | |
237 | void *uap; | |
238 | register_t *retval; | |
239 | { | |
240 | ||
241 | *retval = p->p_ucred->cr_groups[0]; | |
242 | return (0); | |
243 | } | |
244 | ||
245 | struct getgroups_args { | |
246 | u_int gidsetsize; | |
247 | gid_t *gidset; | |
248 | }; | |
249 | getgroups(p, uap, retval) | |
250 | struct proc *p; | |
251 | register struct getgroups_args *uap; | |
252 | register_t *retval; | |
253 | { | |
254 | register struct pcred *pc = p->p_cred; | |
255 | register u_int ngrp; | |
256 | int error; | |
257 | ||
258 | if ((ngrp = uap->gidsetsize) == 0) { | |
259 | *retval = pc->pc_ucred->cr_ngroups; | |
260 | return (0); | |
261 | } | |
262 | if (ngrp < pc->pc_ucred->cr_ngroups) | |
263 | return (EINVAL); | |
264 | pcred_readlock(p); | |
265 | ngrp = pc->pc_ucred->cr_ngroups; | |
266 | if (error = copyout((caddr_t)pc->pc_ucred->cr_groups, | |
267 | (caddr_t)uap->gidset, ngrp * sizeof(gid_t))) { | |
268 | pcred_unlock(p); | |
269 | return (error); | |
270 | } | |
271 | pcred_unlock(p); | |
272 | *retval = ngrp; | |
273 | return (0); | |
274 | } | |
275 | ||
276 | /* ARGSUSED */ | |
277 | setsid(p, uap, retval) | |
278 | register struct proc *p; | |
279 | void *uap; | |
280 | register_t *retval; | |
281 | { | |
282 | ||
55e303ae | 283 | if (p->p_pgid == p->p_pid || pgfind(p->p_pid) || p->p_flag & P_INVFORK) { |
1c79356b A |
284 | return (EPERM); |
285 | } else { | |
286 | (void)enterpgrp(p, p->p_pid, 1); | |
287 | *retval = p->p_pid; | |
288 | return (0); | |
289 | } | |
290 | } | |
291 | ||
292 | /* | |
293 | * set process group (setpgid/old setpgrp) | |
294 | * | |
295 | * caller does setpgid(targpid, targpgid) | |
296 | * | |
297 | * pid must be caller or child of caller (ESRCH) | |
298 | * if a child | |
299 | * pid must be in same session (EPERM) | |
300 | * pid can't have done an exec (EACCES) | |
301 | * if pgid != pid | |
302 | * there must exist some pid in same session having pgid (EPERM) | |
303 | * pid must not be session leader (EPERM) | |
304 | */ | |
305 | struct setpgid_args { | |
306 | int pid; | |
307 | int pgid; | |
308 | }; | |
309 | /* ARGSUSED */ | |
310 | setpgid(curp, uap, retval) | |
311 | struct proc *curp; | |
312 | register struct setpgid_args *uap; | |
313 | register_t *retval; | |
314 | { | |
315 | register struct proc *targp; /* target process */ | |
316 | register struct pgrp *pgrp; /* target pgrp */ | |
317 | ||
318 | if (uap->pid != 0 && uap->pid != curp->p_pid) { | |
319 | if ((targp = pfind(uap->pid)) == 0 || !inferior(targp)) | |
320 | return (ESRCH); | |
321 | if (targp->p_session != curp->p_session) | |
322 | return (EPERM); | |
323 | if (targp->p_flag & P_EXEC) | |
324 | return (EACCES); | |
325 | } else | |
326 | targp = curp; | |
327 | if (SESS_LEADER(targp)) | |
328 | return (EPERM); | |
329 | if (uap->pgid == 0) | |
330 | uap->pgid = targp->p_pid; | |
331 | else if (uap->pgid != targp->p_pid) | |
332 | if ((pgrp = pgfind(uap->pgid)) == 0 || | |
55e303ae | 333 | pgrp->pg_session != curp->p_session) |
1c79356b A |
334 | return (EPERM); |
335 | return (enterpgrp(targp, uap->pgid, 0)); | |
336 | } | |
337 | ||
0b4e3aa0 A |
338 | struct issetugid_args { |
339 | int dummy; | |
340 | }; | |
341 | issetugid(p, uap, retval) | |
342 | struct proc *p; | |
343 | struct issetugid_args *uap; | |
344 | register_t *retval; | |
345 | { | |
346 | /* | |
347 | * Note: OpenBSD sets a P_SUGIDEXEC flag set at execve() time, | |
348 | * we use P_SUGID because we consider changing the owners as | |
349 | * "tainting" as well. | |
350 | * This is significant for procs that start as root and "become" | |
351 | * a user without an exec - programs cannot know *everything* | |
352 | * that libc *might* have put in their data segment. | |
353 | */ | |
354 | ||
355 | *retval = (p->p_flag & P_SUGID) ? 1 : 0; | |
356 | return (0); | |
357 | } | |
358 | ||
1c79356b A |
359 | struct setuid_args { |
360 | uid_t uid; | |
361 | }; | |
362 | /* ARGSUSED */ | |
363 | setuid(p, uap, retval) | |
364 | struct proc *p; | |
365 | struct setuid_args *uap; | |
366 | register_t *retval; | |
367 | { | |
368 | register struct pcred *pc = p->p_cred; | |
369 | register uid_t uid; | |
370 | int error; | |
371 | ||
372 | uid = uap->uid; | |
55e303ae | 373 | AUDIT_ARG(uid, uid, 0, 0, 0); |
1c79356b A |
374 | if (uid != pc->p_ruid && |
375 | (error = suser(pc->pc_ucred, &p->p_acflag))) | |
376 | return (error); | |
377 | /* | |
378 | * Everything's okay, do it. | |
379 | * Transfer proc count to new user. | |
380 | * Copy credentials so other references do not see our changes. | |
381 | */ | |
9bccf70c A |
382 | |
383 | /* prepare app access profile files */ | |
384 | prepare_profile_database(uap->uid); | |
1c79356b A |
385 | pcred_writelock(p); |
386 | (void)chgproccnt(pc->p_ruid, -1); | |
387 | (void)chgproccnt(uid, 1); | |
388 | pc->pc_ucred = crcopy(pc->pc_ucred); | |
389 | pc->pc_ucred->cr_uid = uid; | |
390 | pc->p_ruid = uid; | |
391 | pc->p_svuid = uid; | |
392 | pcred_unlock(p); | |
393 | set_security_token(p); | |
394 | p->p_flag |= P_SUGID; | |
395 | return (0); | |
396 | } | |
397 | ||
398 | struct seteuid_args { | |
399 | uid_t euid; | |
400 | }; | |
401 | /* ARGSUSED */ | |
402 | seteuid(p, uap, retval) | |
403 | struct proc *p; | |
404 | struct seteuid_args *uap; | |
405 | register_t *retval; | |
406 | { | |
407 | register struct pcred *pc = p->p_cred; | |
408 | register uid_t euid; | |
409 | int error; | |
410 | ||
411 | euid = uap->euid; | |
55e303ae | 412 | AUDIT_ARG(uid, 0, euid, 0, 0); |
1c79356b A |
413 | if (euid != pc->p_ruid && euid != pc->p_svuid && |
414 | (error = suser(pc->pc_ucred, &p->p_acflag))) | |
415 | return (error); | |
416 | /* | |
417 | * Everything's okay, do it. Copy credentials so other references do | |
418 | * not see our changes. | |
419 | */ | |
420 | pcred_writelock(p); | |
421 | pc->pc_ucred = crcopy(pc->pc_ucred); | |
422 | pc->pc_ucred->cr_uid = euid; | |
423 | pcred_unlock(p); | |
424 | set_security_token(p); | |
425 | p->p_flag |= P_SUGID; | |
426 | return (0); | |
427 | } | |
428 | ||
429 | struct setgid_args { | |
430 | gid_t gid; | |
431 | }; | |
432 | /* ARGSUSED */ | |
433 | setgid(p, uap, retval) | |
434 | struct proc *p; | |
435 | struct setgid_args *uap; | |
436 | register_t *retval; | |
437 | { | |
438 | register struct pcred *pc = p->p_cred; | |
439 | register gid_t gid; | |
440 | int error; | |
441 | ||
442 | gid = uap->gid; | |
55e303ae | 443 | AUDIT_ARG(gid, gid, 0, 0, 0); |
1c79356b A |
444 | if (gid != pc->p_rgid && (error = suser(pc->pc_ucred, &p->p_acflag))) |
445 | return (error); | |
446 | pcred_writelock(p); | |
447 | pc->pc_ucred = crcopy(pc->pc_ucred); | |
448 | pc->pc_ucred->cr_groups[0] = gid; | |
449 | pc->p_rgid = gid; | |
450 | pc->p_svgid = gid; /* ??? */ | |
451 | pcred_unlock(p); | |
452 | set_security_token(p); | |
453 | p->p_flag |= P_SUGID; | |
454 | return (0); | |
455 | } | |
456 | ||
457 | struct setegid_args { | |
458 | gid_t egid; | |
459 | }; | |
460 | /* ARGSUSED */ | |
461 | setegid(p, uap, retval) | |
462 | struct proc *p; | |
463 | struct setegid_args *uap; | |
464 | register_t *retval; | |
465 | { | |
466 | register struct pcred *pc = p->p_cred; | |
467 | register gid_t egid; | |
468 | int error; | |
469 | ||
470 | egid = uap->egid; | |
55e303ae | 471 | AUDIT_ARG(gid, 0, egid, 0, 0); |
1c79356b A |
472 | if (egid != pc->p_rgid && egid != pc->p_svgid && |
473 | (error = suser(pc->pc_ucred, &p->p_acflag))) | |
474 | return (error); | |
475 | pcred_writelock(p); | |
476 | pc->pc_ucred = crcopy(pc->pc_ucred); | |
477 | pc->pc_ucred->cr_groups[0] = egid; | |
478 | pcred_unlock(p); | |
479 | set_security_token(p); | |
480 | p->p_flag |= P_SUGID; | |
481 | return (0); | |
482 | } | |
483 | ||
484 | struct setgroups_args{ | |
485 | u_int gidsetsize; | |
486 | gid_t *gidset; | |
487 | }; | |
488 | ||
489 | /* ARGSUSED */ | |
490 | setgroups(p, uap, retval) | |
491 | struct proc *p; | |
492 | struct setgroups_args *uap; | |
493 | register_t *retval; | |
494 | { | |
495 | register struct pcred *pc = p->p_cred; | |
496 | struct ucred *new, *old; | |
497 | register u_int ngrp; | |
498 | int error; | |
499 | ||
500 | if (error = suser(pc->pc_ucred, &p->p_acflag)) | |
501 | return (error); | |
502 | ngrp = uap->gidsetsize; | |
55e303ae | 503 | if (ngrp > NGROUPS) |
1c79356b A |
504 | return (EINVAL); |
505 | new = crget(); | |
55e303ae A |
506 | |
507 | if ( ngrp < 1 ) { | |
508 | ngrp = 1; | |
509 | } | |
510 | else { | |
511 | error = copyin((caddr_t)uap->gidset, | |
512 | (caddr_t)new->cr_groups, ngrp * sizeof(gid_t)); | |
513 | if (error) { | |
514 | crfree(new); | |
515 | return (error); | |
516 | } | |
1c79356b A |
517 | } |
518 | new->cr_ngroups = ngrp; | |
55e303ae | 519 | AUDIT_ARG(groupset, new->cr_groups, ngrp); |
1c79356b A |
520 | pcred_writelock(p); |
521 | old = pc->pc_ucred; | |
522 | new->cr_uid = old->cr_uid; | |
523 | pc->pc_ucred = new; | |
524 | pcred_unlock(p); | |
525 | set_security_token(p); | |
526 | p->p_flag |= P_SUGID; | |
527 | if (old != NOCRED) | |
528 | crfree(old); | |
529 | return (0); | |
530 | } | |
531 | ||
532 | #if COMPAT_43 | |
533 | struct osetreuid_args{ | |
534 | int ruid; | |
535 | int euid; | |
536 | }; | |
537 | /* ARGSUSED */ | |
538 | osetreuid(p, uap, retval) | |
539 | register struct proc *p; | |
540 | struct osetreuid_args *uap; | |
541 | register_t *retval; | |
542 | { | |
543 | struct seteuid_args seuidargs; | |
544 | struct setuid_args suidargs; | |
545 | ||
546 | /* | |
547 | * There are five cases, and we attempt to emulate them in | |
548 | * the following fashion: | |
549 | * -1, -1: return 0. This is correct emulation. | |
550 | * -1, N: call seteuid(N). This is correct emulation. | |
551 | * N, -1: if we called setuid(N), our euid would be changed | |
552 | * to N as well. the theory is that we don't want to | |
553 | * revoke root access yet, so we call seteuid(N) | |
554 | * instead. This is incorrect emulation, but often | |
555 | * suffices enough for binary compatibility. | |
556 | * N, N: call setuid(N). This is correct emulation. | |
557 | * N, M: call setuid(N). This is close to correct emulation. | |
558 | */ | |
559 | if (uap->ruid == (uid_t)-1) { | |
560 | if (uap->euid == (uid_t)-1) | |
561 | return (0); /* -1, -1 */ | |
562 | seuidargs.euid = uap->euid; /* -1, N */ | |
563 | return (seteuid(p, &seuidargs, retval)); | |
564 | } | |
565 | if (uap->euid == (uid_t)-1) { | |
566 | seuidargs.euid = uap->ruid; /* N, -1 */ | |
567 | return (seteuid(p, &seuidargs, retval)); | |
568 | } | |
569 | suidargs.uid = uap->ruid; /* N, N and N, M */ | |
570 | return (setuid(p, &suidargs, retval)); | |
571 | } | |
572 | ||
573 | struct osetregid_args { | |
574 | int rgid; | |
575 | int egid; | |
576 | }; | |
577 | /* ARGSUSED */ | |
578 | osetregid(p, uap, retval) | |
579 | register struct proc *p; | |
580 | struct osetregid_args *uap; | |
581 | register_t *retval; | |
582 | { | |
583 | struct setegid_args segidargs; | |
584 | struct setgid_args sgidargs; | |
585 | ||
586 | /* | |
587 | * There are five cases, described above in osetreuid() | |
588 | */ | |
589 | if (uap->rgid == (gid_t)-1) { | |
590 | if (uap->egid == (gid_t)-1) | |
591 | return (0); /* -1, -1 */ | |
592 | segidargs.egid = uap->egid; /* -1, N */ | |
593 | return (setegid(p, &segidargs, retval)); | |
594 | } | |
595 | if (uap->egid == (gid_t)-1) { | |
596 | segidargs.egid = uap->rgid; /* N, -1 */ | |
597 | return (setegid(p, &segidargs, retval)); | |
598 | } | |
599 | sgidargs.gid = uap->rgid; /* N, N and N, M */ | |
600 | return (setgid(p, &sgidargs, retval)); | |
601 | } | |
602 | #endif /* COMPAT_43 */ | |
603 | ||
604 | /* | |
605 | * Check if gid is a member of the group set. | |
606 | */ | |
607 | groupmember(gid, cred) | |
608 | gid_t gid; | |
609 | register struct ucred *cred; | |
610 | { | |
611 | register gid_t *gp; | |
612 | gid_t *egp; | |
613 | ||
614 | egp = &(cred->cr_groups[cred->cr_ngroups]); | |
615 | for (gp = cred->cr_groups; gp < egp; gp++) | |
616 | if (*gp == gid) | |
617 | return (1); | |
618 | return (0); | |
619 | } | |
620 | ||
621 | /* | |
622 | * Test whether the specified credentials imply "super-user" | |
623 | * privilege; if so, and we have accounting info, set the flag | |
624 | * indicating use of super-powers. | |
625 | * Returns 0 or error. | |
626 | */ | |
627 | suser(cred, acflag) | |
628 | struct ucred *cred; | |
629 | u_short *acflag; | |
630 | { | |
631 | #if DIAGNOSTIC | |
632 | if (cred == NOCRED || cred == FSCRED) | |
633 | panic("suser"); | |
634 | #endif | |
635 | if (cred->cr_uid == 0) { | |
636 | if (acflag) | |
637 | *acflag |= ASU; | |
638 | return (0); | |
639 | } | |
640 | return (EPERM); | |
641 | } | |
642 | ||
643 | int | |
644 | is_suser(void) | |
645 | { | |
646 | struct proc *p = current_proc(); | |
647 | ||
648 | if (!p) | |
649 | return (0); | |
650 | ||
651 | return (suser(p->p_ucred, &p->p_acflag) == 0); | |
652 | } | |
653 | ||
654 | int | |
655 | is_suser1(void) | |
656 | { | |
657 | struct proc *p = current_proc(); | |
658 | ||
659 | if (!p) | |
660 | return (0); | |
661 | ||
662 | return (suser(p->p_ucred, &p->p_acflag) == 0 || | |
663 | p->p_cred->p_ruid == 0 || p->p_cred->p_svuid == 0); | |
664 | } | |
665 | ||
666 | /* | |
667 | * Allocate a zeroed cred structure. | |
668 | */ | |
669 | struct ucred * | |
670 | crget() | |
671 | { | |
672 | register struct ucred *cr; | |
673 | ||
674 | MALLOC_ZONE(cr, struct ucred *, sizeof(*cr), M_CRED, M_WAITOK); | |
675 | bzero((caddr_t)cr, sizeof(*cr)); | |
676 | cr->cr_ref = 1; | |
677 | return (cr); | |
678 | } | |
679 | ||
680 | /* | |
681 | * Free a cred structure. | |
682 | * Throws away space when ref count gets to 0. | |
683 | */ | |
684 | void | |
685 | crfree(cr) | |
686 | struct ucred *cr; | |
687 | { | |
688 | #if DIAGNOSTIC | |
689 | if (cr == NOCRED || cr == FSCRED) | |
690 | panic("crfree"); | |
691 | #endif | |
692 | if (--cr->cr_ref == 0) | |
693 | FREE_ZONE((caddr_t)cr, sizeof *cr, M_CRED); | |
694 | } | |
695 | ||
696 | /* | |
697 | * Copy cred structure to a new one and free the old one. | |
698 | */ | |
699 | struct ucred * | |
700 | crcopy(cr) | |
701 | struct ucred *cr; | |
702 | { | |
703 | struct ucred *newcr; | |
704 | ||
705 | #if DIAGNOSTIC | |
706 | if (cr == NOCRED || cr == FSCRED) | |
707 | panic("crcopy"); | |
708 | #endif | |
709 | if (cr->cr_ref == 1) | |
710 | return (cr); | |
711 | newcr = crget(); | |
712 | *newcr = *cr; | |
713 | crfree(cr); | |
714 | newcr->cr_ref = 1; | |
715 | return (newcr); | |
716 | } | |
717 | ||
718 | /* | |
719 | * Dup cred struct to a new held one. | |
720 | */ | |
721 | struct ucred * | |
722 | crdup(cr) | |
723 | struct ucred *cr; | |
724 | { | |
725 | struct ucred *newcr; | |
726 | ||
727 | #if DIAGNOSTIC | |
728 | if (cr == NOCRED || cr == FSCRED) | |
729 | panic("crdup"); | |
730 | #endif | |
731 | newcr = crget(); | |
732 | *newcr = *cr; | |
733 | newcr->cr_ref = 1; | |
734 | return (newcr); | |
735 | } | |
736 | ||
55e303ae A |
737 | /* |
738 | * compare two cred structs | |
739 | */ | |
740 | int | |
741 | crcmp(cr1, cr2) | |
742 | struct ucred *cr1; | |
743 | struct ucred *cr2; | |
744 | { | |
745 | int i; | |
746 | ||
747 | if (cr1 == cr2) | |
748 | return 0; | |
749 | if (cr1 == NOCRED || cr1 == FSCRED || | |
750 | cr2 == NOCRED || cr2 == FSCRED) | |
751 | return 1; | |
752 | if (cr1->cr_uid != cr2->cr_uid) | |
753 | return 1; | |
754 | if (cr1->cr_ngroups != cr2->cr_ngroups) | |
755 | return 1; | |
756 | // XXX assumes groups will always be listed in some order | |
757 | for (i=0; i < cr1->cr_ngroups; i++) | |
758 | if (cr1->cr_groups[i] != cr2->cr_groups[i]) | |
759 | return 1; | |
760 | return (0); | |
761 | } | |
762 | ||
1c79356b A |
763 | /* |
764 | * Get login name, if available. | |
765 | */ | |
766 | struct getlogin_args { | |
767 | char *namebuf; | |
768 | u_int namelen; | |
769 | }; | |
770 | /* ARGSUSED */ | |
771 | getlogin(p, uap, retval) | |
772 | struct proc *p; | |
773 | struct getlogin_args *uap; | |
774 | register_t *retval; | |
775 | { | |
776 | ||
777 | if (uap->namelen > sizeof (p->p_pgrp->pg_session->s_login)) | |
778 | uap->namelen = sizeof (p->p_pgrp->pg_session->s_login); | |
779 | return (copyout((caddr_t) p->p_pgrp->pg_session->s_login, | |
780 | (caddr_t)uap->namebuf, uap->namelen)); | |
781 | } | |
782 | ||
783 | /* | |
784 | * Set login name. | |
785 | */ | |
786 | struct setlogin_args { | |
787 | char *namebuf; | |
788 | }; | |
789 | /* ARGSUSED */ | |
790 | setlogin(p, uap, retval) | |
791 | struct proc *p; | |
792 | struct setlogin_args *uap; | |
793 | register_t *retval; | |
794 | { | |
795 | int error; | |
796 | int dummy=0; | |
797 | ||
798 | if (error = suser(p->p_ucred, &p->p_acflag)) | |
799 | return (error); | |
800 | ||
801 | error = copyinstr((caddr_t) uap->namebuf, | |
802 | (caddr_t) p->p_pgrp->pg_session->s_login, | |
803 | sizeof (p->p_pgrp->pg_session->s_login) - 1, (size_t *)&dummy); | |
804 | if (error == ENAMETOOLONG) | |
805 | error = EINVAL; | |
806 | return (error); | |
807 | } | |
808 | ||
809 | ||
810 | /* Set the secrity token of the task with current euid and eguid */ | |
9bccf70c | 811 | kern_return_t |
1c79356b A |
812 | set_security_token(struct proc * p) |
813 | { | |
814 | security_token_t sec_token; | |
55e303ae | 815 | audit_token_t audit_token; |
1c79356b A |
816 | |
817 | sec_token.val[0] = p->p_ucred->cr_uid; | |
818 | sec_token.val[1] = p->p_ucred->cr_gid; | |
55e303ae A |
819 | audit_token.val[0] = p->p_au->ai_auid; |
820 | audit_token.val[1] = p->p_au->ai_asid; | |
821 | /* use au_tid for now, until au_tid_addr is put to use */ | |
822 | audit_token.val[2] = p->p_au->ai_termid.port; | |
823 | audit_token.val[3] = p->p_au->ai_termid.machine; | |
824 | audit_token.val[4] = 0; | |
825 | audit_token.val[5] = 0; | |
826 | audit_token.val[6] = 0; | |
827 | audit_token.val[7] = 0; | |
9bccf70c | 828 | return host_security_set_task_token(host_security_self(), |
1c79356b A |
829 | p->task, |
830 | sec_token, | |
55e303ae | 831 | audit_token, |
1c79356b | 832 | (sec_token.val[0]) ? |
55e303ae | 833 | HOST_PRIV_NULL : |
1c79356b A |
834 | host_priv_self()); |
835 | } | |
55e303ae A |
836 | |
837 | ||
838 | /* | |
839 | * Fill in a struct xucred based on a struct ucred. | |
840 | */ | |
841 | __private_extern__ | |
842 | void | |
843 | cru2x(struct ucred *cr, struct xucred *xcr) | |
844 | { | |
845 | ||
846 | bzero(xcr, sizeof(*xcr)); | |
847 | xcr->cr_version = XUCRED_VERSION; | |
848 | xcr->cr_uid = cr->cr_uid; | |
849 | xcr->cr_ngroups = cr->cr_ngroups; | |
850 | bcopy(cr->cr_groups, xcr->cr_groups, sizeof(xcr->cr_groups)); | |
851 | } |