|
|
1.1 root 1: /*
2: * Copyright (c) 1982, 1986, 1989, 1990, 1991 Regents of the University
3: * of California. All rights reserved.
4: *
5: * Redistribution and use in source and binary forms, with or without
6: * modification, are permitted provided that the following conditions
7: * are met:
8: * 1. Redistributions of source code must retain the above copyright
9: * notice, this list of conditions and the following disclaimer.
10: * 2. Redistributions in binary form must reproduce the above copyright
11: * notice, this list of conditions and the following disclaimer in the
12: * documentation and/or other materials provided with the distribution.
13: * 3. All advertising materials mentioning features or use of this software
14: * must display the following acknowledgement:
15: * This product includes software developed by the University of
16: * California, Berkeley and its contributors.
17: * 4. Neither the name of the University nor the names of its contributors
18: * may be used to endorse or promote products derived from this software
19: * without specific prior written permission.
20: *
21: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31: * SUCH DAMAGE.
32: *
33: * @(#)kern_prot.c 7.21 (Berkeley) 5/3/91
34: */
35:
36: /*
37: * System calls related to processes and protection
38: */
39:
40: #include "param.h"
41: #include "acct.h"
42: #include "systm.h"
43: #include "ucred.h"
44: #include "proc.h"
45: #include "timeb.h"
46: #include "times.h"
47: #include "malloc.h"
48:
49: /* ARGSUSED */
50: getpid(p, uap, retval)
51: struct proc *p;
52: void *uap;
53: int *retval;
54: {
55:
56: *retval = p->p_pid;
57: #ifdef COMPAT_43
58: retval[1] = p->p_pptr->p_pid;
59: #endif
60: return (0);
61: }
62:
63: /* ARGSUSED */
64: getppid(p, uap, retval)
65: struct proc *p;
66: void *uap;
67: int *retval;
68: {
69:
70: *retval = p->p_pptr->p_pid;
71: return (0);
72: }
73:
74: /* Get process group ID; note that POSIX getpgrp takes no parameter */
75: getpgrp(p, uap, retval)
76: struct proc *p;
77: void *uap;
78: int *retval;
79: {
80:
81: *retval = p->p_pgrp->pg_id;
82: return (0);
83: }
84:
85: /* ARGSUSED */
86: getuid(p, uap, retval)
87: struct proc *p;
88: void *uap;
89: int *retval;
90: {
91:
92: *retval = p->p_cred->p_ruid;
93: #ifdef COMPAT_43
94: retval[1] = p->p_ucred->cr_uid;
95: #endif
96: return (0);
97: }
98:
99: /* ARGSUSED */
100: geteuid(p, uap, retval)
101: struct proc *p;
102: void *uap;
103: int *retval;
104: {
105:
106: *retval = p->p_ucred->cr_uid;
107: return (0);
108: }
109:
110: /* ARGSUSED */
111: getgid(p, uap, retval)
112: struct proc *p;
113: void *uap;
114: int *retval;
115: {
116:
117: *retval = p->p_cred->p_rgid;
118: #ifdef COMPAT_43
119: retval[1] = p->p_ucred->cr_groups[0];
120: #endif
121: return (0);
122: }
123:
124: /*
125: * Get effective group ID. The "egid" is groups[0], and could be obtained
126: * via getgroups. This syscall exists because it is somewhat painful to do
127: * correctly in a library function.
128: */
129: /* ARGSUSED */
130: getegid(p, uap, retval)
131: struct proc *p;
132: void *uap;
133: int *retval;
134: {
135:
136: *retval = p->p_ucred->cr_groups[0];
137: return (0);
138: }
139:
140: getgroups(p, uap, retval)
141: struct proc *p;
142: register struct arg {
143: u_int gidsetsize;
144: int *gidset; /* XXX not yet POSIX */
145: } *uap;
146: int *retval;
147: {
148: register struct pcred *pc = p->p_cred;
149: register gid_t *gp;
150: register int *lp;
151: register u_int ngrp;
152: int groups[NGROUPS];
153: int error;
154:
155: if ((ngrp = uap->gidsetsize) == 0) {
156: *retval = pc->pc_ucred->cr_ngroups;
157: return (0);
158: }
159: if (ngrp < pc->pc_ucred->cr_ngroups)
160: return (EINVAL);
161: ngrp = pc->pc_ucred->cr_ngroups;
162: for (gp = pc->pc_ucred->cr_groups, lp = groups; lp < &groups[ngrp]; )
163: *lp++ = *gp++;
164: if (error = copyout((caddr_t)groups, (caddr_t)uap->gidset,
165: ngrp * sizeof (groups[0])))
166: return (error);
167: *retval = ngrp;
168: return (0);
169: }
170:
171: /* ARGSUSED */
172: setsid(p, uap, retval)
173: register struct proc *p;
174: void *uap;
175: int *retval;
176: {
177:
178: if (p->p_pgid == p->p_pid || pgfind(p->p_pid)) {
179: return (EPERM);
180: } else {
181: enterpgrp(p, p->p_pid, 1);
182: *retval = p->p_pid;
183: return (0);
184: }
185: }
186:
187: /*
188: * set process group (setpgid/old setpgrp)
189: *
190: * caller does setpgid(targpid, targpgid)
191: *
192: * pid must be caller or child of caller (ESRCH)
193: * if a child
194: * pid must be in same session (EPERM)
195: * pid can't have done an exec (EACCES)
196: * if pgid != pid
197: * there must exist some pid in same session having pgid (EPERM)
198: * pid must not be session leader (EPERM)
199: */
200: /* ARGSUSED */
201: setpgid(curp, uap, retval)
202: struct proc *curp;
203: register struct args {
204: int pid; /* target process id */
205: int pgid; /* target pgrp id */
206: } *uap;
207: int *retval;
208: {
209: register struct proc *targp; /* target process */
210: register struct pgrp *pgrp; /* target pgrp */
211:
212: if (uap->pid != 0 && uap->pid != curp->p_pid) {
213: if ((targp = pfind(uap->pid)) == 0 || !inferior(targp))
214: return (ESRCH);
215: if (targp->p_session != curp->p_session)
216: return (EPERM);
217: if (targp->p_flag&SEXEC)
218: return (EACCES);
219: } else
220: targp = curp;
221: if (SESS_LEADER(targp))
222: return (EPERM);
223: if (uap->pgid == 0)
224: uap->pgid = targp->p_pid;
225: else if (uap->pgid != targp->p_pid)
226: if ((pgrp = pgfind(uap->pgid)) == 0 ||
227: pgrp->pg_session != curp->p_session)
228: return (EPERM);
229: enterpgrp(targp, uap->pgid, 0);
230: return (0);
231: }
232:
233: /* ARGSUSED */
234: setuid(p, uap, retval)
235: struct proc *p;
236: struct args {
237: int uid;
238: } *uap;
239: int *retval;
240: {
241: register struct pcred *pc = p->p_cred;
242: register uid_t uid;
243: int error;
244:
245: uid = uap->uid;
246: if (uid != pc->p_ruid &&
247: (error = suser(pc->pc_ucred, &p->p_acflag)))
248: return (error);
249: /*
250: * Everything's okay, do it. Copy credentials so other references do
251: * not see our changes.
252: */
253: pc->pc_ucred = crcopy(pc->pc_ucred);
254: pc->pc_ucred->cr_uid = uid;
255: pc->p_ruid = uid;
256: pc->p_svuid = uid;
257: return (0);
258: }
259:
260: /* ARGSUSED */
261: seteuid(p, uap, retval)
262: struct proc *p;
263: struct args {
264: int euid;
265: } *uap;
266: int *retval;
267: {
268: register struct pcred *pc = p->p_cred;
269: register uid_t euid;
270: int error;
271:
272: euid = uap->euid;
273: if (euid != pc->p_ruid && euid != pc->p_svuid &&
274: (error = suser(pc->pc_ucred, &p->p_acflag)))
275: return (error);
276: /*
277: * Everything's okay, do it. Copy credentials so other references do
278: * not see our changes.
279: */
280: pc->pc_ucred = crcopy(pc->pc_ucred);
281: pc->pc_ucred->cr_uid = euid;
282: return (0);
283: }
284:
285: /* ARGSUSED */
286: setgid(p, uap, retval)
287: struct proc *p;
288: struct args {
289: int gid;
290: } *uap;
291: int *retval;
292: {
293: register struct pcred *pc = p->p_cred;
294: register gid_t gid;
295: int error;
296:
297: gid = uap->gid;
298: if (gid != pc->p_rgid && (error = suser(pc->pc_ucred, &p->p_acflag)))
299: return (error);
300: pc->pc_ucred = crcopy(pc->pc_ucred);
301: pc->pc_ucred->cr_groups[0] = gid;
302: pc->p_rgid = gid;
303: pc->p_svgid = gid; /* ??? */
304: return (0);
305: }
306:
307: /* ARGSUSED */
308: setegid(p, uap, retval)
309: struct proc *p;
310: struct args {
311: int egid;
312: } *uap;
313: int *retval;
314: {
315: register struct pcred *pc = p->p_cred;
316: register gid_t egid;
317: int error;
318:
319: egid = uap->egid;
320: if (egid != pc->p_rgid && egid != pc->p_svgid &&
321: (error = suser(pc->pc_ucred, &p->p_acflag)))
322: return (error);
323: pc->pc_ucred = crcopy(pc->pc_ucred);
324: pc->pc_ucred->cr_groups[0] = egid;
325: return (0);
326: }
327:
328: #ifdef COMPAT_43
329: /* ARGSUSED */
330: osetreuid(p, uap, retval)
331: register struct proc *p;
332: struct args {
333: int ruid;
334: int euid;
335: } *uap;
336: int *retval;
337: {
338: register struct pcred *pc = p->p_cred;
339: register uid_t ruid, euid;
340: int error;
341:
342: if (uap->ruid == -1)
343: ruid = pc->p_ruid;
344: else
345: ruid = uap->ruid;
346: /*
347: * Allow setting real uid to previous effective, for swapping real and
348: * effective. This should be:
349: *
350: * if (ruid != pc->p_ruid &&
351: * (error = suser(pc->pc_ucred, &p->p_acflag)))
352: */
353: if (ruid != pc->p_ruid && ruid != pc->pc_ucred->cr_uid /* XXX */ &&
354: (error = suser(pc->pc_ucred, &p->p_acflag)))
355: return (error);
356: if (uap->euid == -1)
357: euid = pc->pc_ucred->cr_uid;
358: else
359: euid = uap->euid;
360: if (euid != pc->pc_ucred->cr_uid && euid != pc->p_ruid &&
361: euid != pc->p_svuid && (error = suser(pc->pc_ucred, &p->p_acflag)))
362: return (error);
363: /*
364: * Everything's okay, do it. Copy credentials so other references do
365: * not see our changes.
366: */
367: pc->pc_ucred = crcopy(pc->pc_ucred);
368: pc->pc_ucred->cr_uid = euid;
369: pc->p_ruid = ruid;
370: return (0);
371: }
372:
373: /* ARGSUSED */
374: osetregid(p, uap, retval)
375: register struct proc *p;
376: struct args {
377: int rgid;
378: int egid;
379: } *uap;
380: int *retval;
381: {
382: register struct pcred *pc = p->p_cred;
383: register gid_t rgid, egid;
384: int error;
385:
386: if (uap->rgid == -1)
387: rgid = pc->p_rgid;
388: else
389: rgid = uap->rgid;
390: /*
391: * Allow setting real gid to previous effective, for swapping real and
392: * effective. This didn't really work correctly in 4.[23], but is
393: * preserved so old stuff doesn't fail. This should be:
394: *
395: * if (rgid != pc->p_rgid &&
396: * (error = suser(pc->pc_ucred, &p->p_acflag)))
397: */
398: if (rgid != pc->p_rgid && rgid != pc->pc_ucred->cr_groups[0] /* XXX */ &&
399: (error = suser(pc->pc_ucred, &p->p_acflag)))
400: return (error);
401: if (uap->egid == -1)
402: egid = pc->pc_ucred->cr_groups[0];
403: else
404: egid = uap->egid;
405: if (egid != pc->pc_ucred->cr_groups[0] && egid != pc->p_rgid &&
406: egid != pc->p_svgid && (error = suser(pc->pc_ucred, &p->p_acflag)))
407: return (error);
408: pc->pc_ucred = crcopy(pc->pc_ucred);
409: pc->pc_ucred->cr_groups[0] = egid;
410: pc->p_rgid = rgid;
411: return (0);
412: }
413: #endif
414:
415: /* ARGSUSED */
416: setgroups(p, uap, retval)
417: struct proc *p;
418: struct args {
419: u_int gidsetsize;
420: int *gidset;
421: } *uap;
422: int *retval;
423: {
424: register struct pcred *pc = p->p_cred;
425: register gid_t *gp;
426: register u_int ngrp;
427: register int *lp;
428: int error, groups[NGROUPS];
429:
430: if (error = suser(pc->pc_ucred, &p->p_acflag))
431: return (error);
432: if ((ngrp = uap->gidsetsize) > NGROUPS)
433: return (EINVAL);
434: if (error = copyin((caddr_t)uap->gidset, (caddr_t)groups,
435: ngrp * sizeof (groups[0])))
436: return (error);
437: pc->pc_ucred = crcopy(pc->pc_ucred);
438: pc->pc_ucred->cr_ngroups = ngrp;
439: /* convert from int's to gid_t's */
440: for (gp = pc->pc_ucred->cr_groups, lp = groups; ngrp--; )
441: *gp++ = *lp++;
442: return (0);
443: }
444:
445: /*
446: * Check if gid is a member of the group set.
447: */
448: groupmember(gid, cred)
449: gid_t gid;
450: register struct ucred *cred;
451: {
452: register gid_t *gp;
453: gid_t *egp;
454:
455: egp = &(cred->cr_groups[cred->cr_ngroups]);
456: for (gp = cred->cr_groups; gp < egp; gp++)
457: if (*gp == gid)
458: return (1);
459: return (0);
460: }
461:
462: /*
463: * Test whether the specified credentials imply "super-user"
464: * privilege; if so, and we have accounting info, set the flag
465: * indicating use of super-powers.
466: * Returns 0 or error.
467: */
468: suser(cred, acflag)
469: struct ucred *cred;
1.1.1.2 ! root 470: u_short *acflag;
1.1 root 471: {
472: if (cred->cr_uid == 0) {
473: if (acflag)
474: *acflag |= ASU;
475: return (0);
476: }
477: return (EPERM);
478: }
479:
480: /*
481: * Allocate a zeroed cred structure.
482: */
483: struct ucred *
484: crget()
485: {
486: register struct ucred *cr;
487:
488: MALLOC(cr, struct ucred *, sizeof(*cr), M_CRED, M_WAITOK);
489: bzero((caddr_t)cr, sizeof(*cr));
490: cr->cr_ref = 1;
491: return (cr);
492: }
493:
494: /*
495: * Free a cred structure.
496: * Throws away space when ref count gets to 0.
497: */
498: crfree(cr)
499: struct ucred *cr;
500: {
501: int s = splimp(); /* ??? */
502:
503: if (--cr->cr_ref != 0) {
504: (void) splx(s);
505: return;
506: }
507: FREE((caddr_t)cr, M_CRED);
508: (void) splx(s);
509: }
510:
511: /*
512: * Copy cred structure to a new one and free the old one.
513: */
514: struct ucred *
515: crcopy(cr)
516: struct ucred *cr;
517: {
518: struct ucred *newcr;
519:
520: if (cr->cr_ref == 1)
521: return (cr);
522: newcr = crget();
523: *newcr = *cr;
524: crfree(cr);
525: newcr->cr_ref = 1;
526: return (newcr);
527: }
528:
529: /*
530: * Dup cred struct to a new held one.
531: */
532: struct ucred *
533: crdup(cr)
534: struct ucred *cr;
535: {
536: struct ucred *newcr;
537:
538: newcr = crget();
539: *newcr = *cr;
540: newcr->cr_ref = 1;
541: return (newcr);
542: }
543:
544: /*
545: * Get login name, if available.
546: */
547: /* ARGSUSED */
548: getlogin(p, uap, retval)
549: struct proc *p;
550: struct args {
551: char *namebuf;
552: u_int namelen;
553: } *uap;
554: int *retval;
555: {
556:
557: if (uap->namelen > sizeof (p->p_pgrp->pg_session->s_login))
558: uap->namelen = sizeof (p->p_pgrp->pg_session->s_login);
559: return (copyout((caddr_t) p->p_pgrp->pg_session->s_login,
560: (caddr_t) uap->namebuf, uap->namelen));
561: }
562:
563: /*
564: * Set login name.
565: */
566: /* ARGSUSED */
567: setlogin(p, uap, retval)
568: struct proc *p;
569: struct args {
570: char *namebuf;
571: } *uap;
572: int *retval;
573: {
574: int error;
575:
576: if (error = suser(p->p_ucred, &p->p_acflag))
577: return (error);
578: error = copyinstr((caddr_t) uap->namebuf,
579: (caddr_t) p->p_pgrp->pg_session->s_login,
580: sizeof (p->p_pgrp->pg_session->s_login) - 1, (u_int *)0);
581: if (error == ENAMETOOLONG)
582: error = EINVAL;
583: return (error);
584: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.