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