reorganization to move ufsmount ops to be vnode ops;
[unix-history] / usr / src / sys / kern / kern_prot.c
... / ...
CommitLineData
1/*
2 * Copyright (c) 1982, 1986, 1989, 1990, 1991 Regents of the University
3 * of California. All rights reserved.
4 *
5 * %sccs.include.redist.c%
6 *
7 * @(#)kern_prot.c 7.21 (Berkeley) %G%
8 */
9
10/*
11 * System calls related to processes and protection
12 */
13
14#include "param.h"
15#include "acct.h"
16#include "systm.h"
17#include "ucred.h"
18#include "proc.h"
19#include "timeb.h"
20#include "times.h"
21#include "malloc.h"
22
23/* ARGSUSED */
24getpid(p, uap, retval)
25 struct proc *p;
26 void *uap;
27 int *retval;
28{
29
30 *retval = p->p_pid;
31#ifdef COMPAT_43
32 retval[1] = p->p_pptr->p_pid;
33#endif
34 return (0);
35}
36
37/* ARGSUSED */
38getppid(p, uap, retval)
39 struct proc *p;
40 void *uap;
41 int *retval;
42{
43
44 *retval = p->p_pptr->p_pid;
45 return (0);
46}
47
48/* Get process group ID; note that POSIX getpgrp takes no parameter */
49getpgrp(p, uap, retval)
50 struct proc *p;
51 void *uap;
52 int *retval;
53{
54
55 *retval = p->p_pgrp->pg_id;
56 return (0);
57}
58
59/* ARGSUSED */
60getuid(p, uap, retval)
61 struct proc *p;
62 void *uap;
63 int *retval;
64{
65
66 *retval = p->p_cred->p_ruid;
67#ifdef COMPAT_43
68 retval[1] = p->p_ucred->cr_uid;
69#endif
70 return (0);
71}
72
73/* ARGSUSED */
74geteuid(p, uap, retval)
75 struct proc *p;
76 void *uap;
77 int *retval;
78{
79
80 *retval = p->p_ucred->cr_uid;
81 return (0);
82}
83
84/* ARGSUSED */
85getgid(p, uap, retval)
86 struct proc *p;
87 void *uap;
88 int *retval;
89{
90
91 *retval = p->p_cred->p_rgid;
92#ifdef COMPAT_43
93 retval[1] = p->p_ucred->cr_groups[0];
94#endif
95 return (0);
96}
97
98/*
99 * Get effective group ID. The "egid" is groups[0], and could be obtained
100 * via getgroups. This syscall exists because it is somewhat painful to do
101 * correctly in a library function.
102 */
103/* ARGSUSED */
104getegid(p, uap, retval)
105 struct proc *p;
106 void *uap;
107 int *retval;
108{
109
110 *retval = p->p_ucred->cr_groups[0];
111 return (0);
112}
113
114getgroups(p, uap, retval)
115 struct proc *p;
116 register struct arg {
117 u_int gidsetsize;
118 int *gidset; /* XXX not yet POSIX */
119 } *uap;
120 int *retval;
121{
122 register struct pcred *pc = p->p_cred;
123 register gid_t *gp;
124 register int *lp;
125 register u_int ngrp;
126 int groups[NGROUPS];
127 int error;
128
129 if ((ngrp = uap->gidsetsize) == 0) {
130 *retval = pc->pc_ucred->cr_ngroups;
131 return (0);
132 }
133 if (ngrp < pc->pc_ucred->cr_ngroups)
134 return (EINVAL);
135 ngrp = pc->pc_ucred->cr_ngroups;
136 for (gp = pc->pc_ucred->cr_groups, lp = groups; lp < &groups[ngrp]; )
137 *lp++ = *gp++;
138 if (error = copyout((caddr_t)groups, (caddr_t)uap->gidset,
139 ngrp * sizeof (groups[0])))
140 return (error);
141 *retval = ngrp;
142 return (0);
143}
144
145/* ARGSUSED */
146setsid(p, uap, retval)
147 register struct proc *p;
148 void *uap;
149 int *retval;
150{
151
152 if (p->p_pgid == p->p_pid || pgfind(p->p_pid)) {
153 return (EPERM);
154 } else {
155 enterpgrp(p, p->p_pid, 1);
156 *retval = p->p_pid;
157 return (0);
158 }
159}
160
161/*
162 * set process group (setpgid/old setpgrp)
163 *
164 * caller does setpgid(targpid, targpgid)
165 *
166 * pid must be caller or child of caller (ESRCH)
167 * if a child
168 * pid must be in same session (EPERM)
169 * pid can't have done an exec (EACCES)
170 * if pgid != pid
171 * there must exist some pid in same session having pgid (EPERM)
172 * pid must not be session leader (EPERM)
173 */
174/* ARGSUSED */
175setpgid(curp, uap, retval)
176 struct proc *curp;
177 register struct args {
178 int pid; /* target process id */
179 int pgid; /* target pgrp id */
180 } *uap;
181 int *retval;
182{
183 register struct proc *targp; /* target process */
184 register struct pgrp *pgrp; /* target pgrp */
185
186 if (uap->pid != 0 && uap->pid != curp->p_pid) {
187 if ((targp = pfind(uap->pid)) == 0 || !inferior(targp))
188 return (ESRCH);
189 if (targp->p_session != curp->p_session)
190 return (EPERM);
191 if (targp->p_flag&SEXEC)
192 return (EACCES);
193 } else
194 targp = curp;
195 if (SESS_LEADER(targp))
196 return (EPERM);
197 if (uap->pgid == 0)
198 uap->pgid = targp->p_pid;
199 else if (uap->pgid != targp->p_pid)
200 if ((pgrp = pgfind(uap->pgid)) == 0 ||
201 pgrp->pg_session != curp->p_session)
202 return (EPERM);
203 enterpgrp(targp, uap->pgid, 0);
204 return (0);
205}
206
207/* ARGSUSED */
208setuid(p, uap, retval)
209 struct proc *p;
210 struct args {
211 int uid;
212 } *uap;
213 int *retval;
214{
215 register struct pcred *pc = p->p_cred;
216 register uid_t uid;
217 int error;
218
219 uid = uap->uid;
220 if (uid != pc->p_ruid &&
221 (error = suser(pc->pc_ucred, &p->p_acflag)))
222 return (error);
223 /*
224 * Everything's okay, do it. Copy credentials so other references do
225 * not see our changes.
226 */
227 pc->pc_ucred = crcopy(pc->pc_ucred);
228 pc->pc_ucred->cr_uid = uid;
229 pc->p_ruid = uid;
230 pc->p_svuid = uid;
231 return (0);
232}
233
234/* ARGSUSED */
235seteuid(p, uap, retval)
236 struct proc *p;
237 struct args {
238 int euid;
239 } *uap;
240 int *retval;
241{
242 register struct pcred *pc = p->p_cred;
243 register uid_t euid;
244 int error;
245
246 euid = uap->euid;
247 if (euid != pc->p_ruid && euid != pc->p_svuid &&
248 (error = suser(pc->pc_ucred, &p->p_acflag)))
249 return (error);
250 /*
251 * Everything's okay, do it. Copy credentials so other references do
252 * not see our changes.
253 */
254 pc->pc_ucred = crcopy(pc->pc_ucred);
255 pc->pc_ucred->cr_uid = euid;
256 return (0);
257}
258
259/* ARGSUSED */
260setgid(p, uap, retval)
261 struct proc *p;
262 struct args {
263 int gid;
264 } *uap;
265 int *retval;
266{
267 register struct pcred *pc = p->p_cred;
268 register gid_t gid;
269 int error;
270
271 gid = uap->gid;
272 if (gid != pc->p_rgid && (error = suser(pc->pc_ucred, &p->p_acflag)))
273 return (error);
274 pc->pc_ucred = crcopy(pc->pc_ucred);
275 pc->pc_ucred->cr_groups[0] = gid;
276 pc->p_rgid = gid;
277 pc->p_svgid = gid; /* ??? */
278 return (0);
279}
280
281/* ARGSUSED */
282setegid(p, uap, retval)
283 struct proc *p;
284 struct args {
285 int egid;
286 } *uap;
287 int *retval;
288{
289 register struct pcred *pc = p->p_cred;
290 register gid_t egid;
291 int error;
292
293 egid = uap->egid;
294 if (egid != pc->p_rgid && egid != pc->p_svgid &&
295 (error = suser(pc->pc_ucred, &p->p_acflag)))
296 return (error);
297 pc->pc_ucred = crcopy(pc->pc_ucred);
298 pc->pc_ucred->cr_groups[0] = egid;
299 return (0);
300}
301
302#ifdef COMPAT_43
303/* ARGSUSED */
304osetreuid(p, uap, retval)
305 register struct proc *p;
306 struct args {
307 int ruid;
308 int euid;
309 } *uap;
310 int *retval;
311{
312 register struct pcred *pc = p->p_cred;
313 register uid_t ruid, euid;
314 int error;
315
316 if (uap->ruid == -1)
317 if (ruid != pc->p_ruid && ruid != pc->pc_ucred->cr_uid /* XXX */ &&
318 (error = suser(pc->pc_ucred, &p->p_acflag)))
319 return (error);
320 if (uap->euid == -1)
321 if (euid != pc->pc_ucred->cr_uid && euid != pc->p_ruid &&
322 euid != pc->p_svuid && (error = suser(pc->pc_ucred, &p->p_acflag)))
323 return (error);
324 /*
325 * Everything's okay, do it. Copy credentials so other references do
326 * not see our changes.
327 */
328 pc->pc_ucred = crcopy(pc->pc_ucred);
329 pc->pc_ucred->cr_uid = euid;
330 pc->p_ruid = ruid;
331 return (0);
332}
333
334/* ARGSUSED */
335osetregid(p, uap, retval)
336 register struct proc *p;
337 struct args {
338 int rgid;
339 int egid;
340 } *uap;
341 int *retval;
342{
343 register struct pcred *pc = p->p_cred;
344 register gid_t rgid, egid;
345 int error;
346
347 if (uap->rgid == -1)
348 if (rgid != pc->p_rgid && rgid != pc->pc_ucred->cr_groups[0] /* XXX */ &&
349 (error = suser(pc->pc_ucred, &p->p_acflag)))
350 return (error);
351 if (uap->egid == -1)
352 if (egid != pc->pc_ucred->cr_groups[0] && egid != pc->p_rgid &&
353 egid != pc->p_svgid && (error = suser(pc->pc_ucred, &p->p_acflag)))
354 return (error);
355 pc->pc_ucred = crcopy(pc->pc_ucred);
356 pc->pc_ucred->cr_groups[0] = egid;
357 pc->p_rgid = rgid;
358 return (0);
359}
360#endif
361
362/* ARGSUSED */
363setgroups(p, uap, retval)
364 struct proc *p;
365 struct args {
366 u_int gidsetsize;
367 int *gidset;
368 } *uap;
369 int *retval;
370{
371 register struct pcred *pc = p->p_cred;
372 register gid_t *gp;
373 register u_int ngrp;
374 register int *lp;
375 int error, groups[NGROUPS];
376
377 if (error = suser(pc->pc_ucred, &p->p_acflag))
378 return (error);
379 if ((ngrp = uap->gidsetsize) > NGROUPS)
380 return (EINVAL);
381 if (error = copyin((caddr_t)uap->gidset, (caddr_t)groups,
382 ngrp * sizeof (groups[0])))
383 return (error);
384 pc->pc_ucred = crcopy(pc->pc_ucred);
385 pc->pc_ucred->cr_ngroups = ngrp;
386 /* convert from int's to gid_t's */
387 for (gp = pc->pc_ucred->cr_groups, lp = groups; ngrp--; )
388 *gp++ = *lp++;
389 return (0);
390}
391
392/*
393 * Check if gid is a member of the group set.
394 */
395groupmember(gid, cred)
396 gid_t gid;
397 register struct ucred *cred;
398{
399 register gid_t *gp;
400 gid_t *egp;
401
402 egp = &(cred->cr_groups[cred->cr_ngroups]);
403 for (gp = cred->cr_groups; gp < egp; gp++)
404 if (*gp == gid)
405 return (1);
406 return (0);
407}
408
409/*
410 * Test whether the specified credentials imply "super-user"
411 * privilege; if so, and we have accounting info, set the flag
412 * indicating use of super-powers.
413 * Returns 0 or error.
414 */
415suser(cred, acflag)
416 struct ucred *cred;
417 short *acflag;
418{
419 if (cred->cr_uid == 0) {
420 if (acflag)
421 *acflag |= ASU;
422 return (0);
423 }
424 return (EPERM);
425}
426
427/*
428 * Allocate a zeroed cred structure.
429 */
430struct ucred *
431crget()
432{
433 register struct ucred *cr;
434
435 MALLOC(cr, struct ucred *, sizeof(*cr), M_CRED, M_WAITOK);
436 bzero((caddr_t)cr, sizeof(*cr));
437 cr->cr_ref = 1;
438 return (cr);
439}
440
441/*
442 * Free a cred structure.
443 * Throws away space when ref count gets to 0.
444 */
445crfree(cr)
446 struct ucred *cr;
447{
448 int s = splimp(); /* ??? */
449
450 if (--cr->cr_ref != 0) {
451 (void) splx(s);
452 return;
453 }
454 FREE((caddr_t)cr, M_CRED);
455 (void) splx(s);
456}
457
458/*
459 * Copy cred structure to a new one and free the old one.
460 */
461struct ucred *
462crcopy(cr)
463 struct ucred *cr;
464{
465 struct ucred *newcr;
466
467 if (cr->cr_ref == 1)
468 return (cr);
469 newcr = crget();
470 *newcr = *cr;
471 crfree(cr);
472 newcr->cr_ref = 1;
473 return (newcr);
474}
475
476/*
477 * Dup cred struct to a new held one.
478 */
479struct ucred *
480crdup(cr)
481 struct ucred *cr;
482{
483 struct ucred *newcr;
484
485 newcr = crget();
486 *newcr = *cr;
487 newcr->cr_ref = 1;
488 return (newcr);
489}
490
491/*
492 * Get login name, if available.
493 */
494/* ARGSUSED */
495getlogin(p, uap, retval)
496 struct proc *p;
497 struct args {
498 char *namebuf;
499 u_int namelen;
500 } *uap;
501 int *retval;
502{
503
504 if (uap->namelen > sizeof (p->p_pgrp->pg_session->s_login))
505 uap->namelen = sizeof (p->p_pgrp->pg_session->s_login);
506 return (copyout((caddr_t) p->p_pgrp->pg_session->s_login,
507 (caddr_t) uap->namebuf, uap->namelen));
508}
509
510/*
511 * Set login name.
512 */
513/* ARGSUSED */
514setlogin(p, uap, retval)
515 struct proc *p;
516 struct args {
517 char *namebuf;
518 } *uap;
519 int *retval;
520{
521 int error;
522
523 if (error = suser(p->p_ucred, &p->p_acflag))
524 return (error);
525 error = copyinstr((caddr_t) uap->namebuf,
526 (caddr_t) p->p_pgrp->pg_session->s_login,
527 sizeof (p->p_pgrp->pg_session->s_login) - 1, (u_int *)0);
528 if (error == ENAMETOOLONG)
529 error = EINVAL;
530 return (error);
531}