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