reorganization to move ufsmount ops to be vnode ops;
[unix-history] / usr / src / sys / kern / kern_prot.c
CommitLineData
da7c5cc6 1/*
8429d022
MK
2 * Copyright (c) 1982, 1986, 1989, 1990, 1991 Regents of the University
3 * of California. All rights reserved.
da7c5cc6 4 *
dbf0c423 5 * %sccs.include.redist.c%
88a39492 6 *
ff63251b 7 * @(#)kern_prot.c 7.21 (Berkeley) %G%
da7c5cc6 8 */
a05af100
BJ
9
10/*
4147b3f6 11 * System calls related to processes and protection
a05af100
BJ
12 */
13
94368568 14#include "param.h"
88a39492 15#include "acct.h"
94368568 16#include "systm.h"
8429d022 17#include "ucred.h"
94368568
JB
18#include "proc.h"
19#include "timeb.h"
20#include "times.h"
88a39492 21#include "malloc.h"
a05af100 22
d5dc47bf
MK
23/* ARGSUSED */
24getpid(p, uap, retval)
25 struct proc *p;
26 void *uap;
27 int *retval;
4147b3f6
BJ
28{
29
d5dc47bf
MK
30 *retval = p->p_pid;
31#ifdef COMPAT_43
8429d022 32 retval[1] = p->p_pptr->p_pid;
d5dc47bf 33#endif
d9c2f47f 34 return (0);
4147b3f6
BJ
35}
36
d5dc47bf
MK
37/* ARGSUSED */
38getppid(p, uap, retval)
39 struct proc *p;
40 void *uap;
41 int *retval;
4147b3f6 42{
d5dc47bf 43
8429d022 44 *retval = p->p_pptr->p_pid;
d9c2f47f 45 return (0);
d5dc47bf
MK
46}
47
8429d022 48/* Get process group ID; note that POSIX getpgrp takes no parameter */
d5dc47bf
MK
49getpgrp(p, uap, retval)
50 struct proc *p;
8429d022 51 void *uap;
d5dc47bf
MK
52 int *retval;
53{
4147b3f6 54
d5dc47bf 55 *retval = p->p_pgrp->pg_id;
d9c2f47f 56 return (0);
4147b3f6
BJ
57}
58
d5dc47bf
MK
59/* ARGSUSED */
60getuid(p, uap, retval)
61 struct proc *p;
62 void *uap;
63 int *retval;
a05af100
BJ
64{
65
8429d022 66 *retval = p->p_cred->p_ruid;
d5dc47bf 67#ifdef COMPAT_43
8429d022 68 retval[1] = p->p_ucred->cr_uid;
d5dc47bf 69#endif
d9c2f47f 70 return (0);
a05af100
BJ
71}
72
d5dc47bf
MK
73/* ARGSUSED */
74geteuid(p, uap, retval)
75 struct proc *p;
76 void *uap;
77 int *retval;
4147b3f6
BJ
78{
79
8429d022 80 *retval = p->p_ucred->cr_uid;
d9c2f47f 81 return (0);
4147b3f6
BJ
82}
83
d5dc47bf
MK
84/* ARGSUSED */
85getgid(p, uap, retval)
86 struct proc *p;
87 void *uap;
88 int *retval;
89{
90
8429d022 91 *retval = p->p_cred->p_rgid;
d5dc47bf 92#ifdef COMPAT_43
8429d022 93 retval[1] = p->p_ucred->cr_groups[0];
d5dc47bf 94#endif
d9c2f47f 95 return (0);
d5dc47bf
MK
96}
97
98/*
0712db82
KB
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.
d5dc47bf
MK
102 */
103/* ARGSUSED */
104getegid(p, uap, retval)
105 struct proc *p;
106 void *uap;
107 int *retval;
4147b3f6 108{
8429d022
MK
109
110 *retval = p->p_ucred->cr_groups[0];
d9c2f47f 111 return (0);
d5dc47bf
MK
112}
113
114getgroups(p, uap, retval)
115 struct proc *p;
116 register struct arg {
b32450f4 117 u_int gidsetsize;
d5dc47bf
MK
118 int *gidset; /* XXX not yet POSIX */
119 } *uap;
120 int *retval;
121{
8429d022 122 register struct pcred *pc = p->p_cred;
38b6104c
MK
123 register gid_t *gp;
124 register int *lp;
fca91c15 125 register u_int ngrp;
38b6104c 126 int groups[NGROUPS];
d5dc47bf 127 int error;
4147b3f6 128
fca91c15 129 if ((ngrp = uap->gidsetsize) == 0) {
8429d022 130 *retval = pc->pc_ucred->cr_ngroups;
d9c2f47f 131 return (0);
197da11b 132 }
8429d022 133 if (ngrp < pc->pc_ucred->cr_ngroups)
d9c2f47f 134 return (EINVAL);
8429d022
MK
135 ngrp = pc->pc_ucred->cr_ngroups;
136 for (gp = pc->pc_ucred->cr_groups, lp = groups; lp < &groups[ngrp]; )
38b6104c 137 *lp++ = *gp++;
d5dc47bf 138 if (error = copyout((caddr_t)groups, (caddr_t)uap->gidset,
fca91c15 139 ngrp * sizeof (groups[0])))
d9c2f47f 140 return (error);
fca91c15 141 *retval = ngrp;
d9c2f47f 142 return (0);
4147b3f6
BJ
143}
144
d5dc47bf
MK
145/* ARGSUSED */
146setsid(p, uap, retval)
8429d022 147 register struct proc *p;
d5dc47bf
MK
148 void *uap;
149 int *retval;
8fe87cbb 150{
8fe87cbb 151
d5dc47bf 152 if (p->p_pgid == p->p_pid || pgfind(p->p_pid)) {
d9c2f47f 153 return (EPERM);
d5dc47bf 154 } else {
8429d022 155 enterpgrp(p, p->p_pid, 1);
d5dc47bf 156 *retval = p->p_pid;
d9c2f47f 157 return (0);
8fe87cbb 158 }
8fe87cbb
MT
159}
160
161/*
8429d022 162 * set process group (setpgid/old setpgrp)
8fe87cbb 163 *
049b1521 164 * caller does setpgid(targpid, targpgid)
164c0f54
MK
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)
8fe87cbb 173 */
d5dc47bf 174/* ARGSUSED */
049b1521
MT
175setpgid(curp, uap, retval)
176 struct proc *curp;
d5dc47bf 177 register struct args {
ff63251b
MK
178 int pid; /* target process id */
179 int pgid; /* target pgrp id */
d5dc47bf
MK
180 } *uap;
181 int *retval;
182{
049b1521 183 register struct proc *targp; /* target process */
ff63251b 184 register struct pgrp *pgrp; /* target pgrp */
4147b3f6 185
ff63251b
MK
186 if (uap->pid != 0 && uap->pid != curp->p_pid) {
187 if ((targp = pfind(uap->pid)) == 0 || !inferior(targp))
d9c2f47f 188 return (ESRCH);
049b1521 189 if (targp->p_session != curp->p_session)
d9c2f47f 190 return (EPERM);
049b1521 191 if (targp->p_flag&SEXEC)
d9c2f47f 192 return (EACCES);
d5dc47bf 193 } else
049b1521
MT
194 targp = curp;
195 if (SESS_LEADER(targp))
d9c2f47f 196 return (EPERM);
ff63251b
MK
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)
0712db82 202 return (EPERM);
ff63251b 203 enterpgrp(targp, uap->pgid, 0);
d9c2f47f 204 return (0);
4147b3f6
BJ
205}
206
d5dc47bf
MK
207/* ARGSUSED */
208setuid(p, uap, retval)
8429d022 209 struct proc *p;
d5dc47bf
MK
210 struct args {
211 int uid;
212 } *uap;
213 int *retval;
4f083fd7 214{
8429d022 215 register struct pcred *pc = p->p_cred;
d5dc47bf
MK
216 register uid_t uid;
217 int error;
218
219 uid = uap->uid;
8429d022
MK
220 if (uid != pc->p_ruid &&
221 (error = suser(pc->pc_ucred, &p->p_acflag)))
d9c2f47f 222 return (error);
d5dc47bf 223 /*
0712db82
KB
224 * Everything's okay, do it. Copy credentials so other references do
225 * not see our changes.
d5dc47bf 226 */
8429d022
MK
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;
d9c2f47f 231 return (0);
d5dc47bf
MK
232}
233
234/* ARGSUSED */
235seteuid(p, uap, retval)
8429d022 236 struct proc *p;
d5dc47bf 237 struct args {
4f083fd7
SL
238 int euid;
239 } *uap;
d5dc47bf
MK
240 int *retval;
241{
8429d022 242 register struct pcred *pc = p->p_cred;
d5dc47bf
MK
243 register uid_t euid;
244 int error;
4f083fd7 245
4f083fd7 246 euid = uap->euid;
8429d022
MK
247 if (euid != pc->p_ruid && euid != pc->p_svuid &&
248 (error = suser(pc->pc_ucred, &p->p_acflag)))
d9c2f47f 249 return (error);
4f083fd7 250 /*
0712db82
KB
251 * Everything's okay, do it. Copy credentials so other references do
252 * not see our changes.
4f083fd7 253 */
8429d022
MK
254 pc->pc_ucred = crcopy(pc->pc_ucred);
255 pc->pc_ucred->cr_uid = euid;
d9c2f47f 256 return (0);
4f083fd7
SL
257}
258
d5dc47bf
MK
259/* ARGSUSED */
260setgid(p, uap, retval)
261 struct proc *p;
262 struct args {
263 int gid;
264 } *uap;
265 int *retval;
4f083fd7 266{
8429d022 267 register struct pcred *pc = p->p_cred;
d5dc47bf
MK
268 register gid_t gid;
269 int error;
270
271 gid = uap->gid;
8429d022 272 if (gid != pc->p_rgid && (error = suser(pc->pc_ucred, &p->p_acflag)))
d9c2f47f 273 return (error);
8429d022
MK
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; /* ??? */
d9c2f47f 278 return (0);
d5dc47bf
MK
279}
280
281/* ARGSUSED */
282setegid(p, uap, retval)
283 struct proc *p;
284 struct args {
4f083fd7
SL
285 int egid;
286 } *uap;
d5dc47bf
MK
287 int *retval;
288{
8429d022 289 register struct pcred *pc = p->p_cred;
d5dc47bf
MK
290 register gid_t egid;
291 int error;
4f083fd7 292
4f083fd7 293 egid = uap->egid;
8429d022
MK
294 if (egid != pc->p_rgid && egid != pc->p_svgid &&
295 (error = suser(pc->pc_ucred, &p->p_acflag)))
d9c2f47f 296 return (error);
8429d022
MK
297 pc->pc_ucred = crcopy(pc->pc_ucred);
298 pc->pc_ucred->cr_groups[0] = egid;
d9c2f47f 299 return (0);
d5dc47bf
MK
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{
8429d022 312 register struct pcred *pc = p->p_cred;
d5dc47bf
MK
313 register uid_t ruid, euid;
314 int error;
315
316 if (uap->ruid == -1)
8429d022
MK
317 if (ruid != pc->p_ruid && ruid != pc->pc_ucred->cr_uid /* XXX */ &&
318 (error = suser(pc->pc_ucred, &p->p_acflag)))
d9c2f47f 319 return (error);
d5dc47bf 320 if (uap->euid == -1)
8429d022
MK
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)))
d9c2f47f 323 return (error);
d5dc47bf 324 /*
0712db82
KB
325 * Everything's okay, do it. Copy credentials so other references do
326 * not see our changes.
d5dc47bf 327 */
8429d022
MK
328 pc->pc_ucred = crcopy(pc->pc_ucred);
329 pc->pc_ucred->cr_uid = euid;
330 pc->p_ruid = ruid;
d9c2f47f 331 return (0);
4f083fd7 332}
a05af100 333
d5dc47bf
MK
334/* ARGSUSED */
335osetregid(p, uap, retval)
8429d022 336 register struct proc *p;
d5dc47bf
MK
337 struct args {
338 int rgid;
339 int egid;
340 } *uap;
341 int *retval;
4147b3f6 342{
8429d022 343 register struct pcred *pc = p->p_cred;
d5dc47bf
MK
344 register gid_t rgid, egid;
345 int error;
346
347 if (uap->rgid == -1)
8429d022
MK
348 if (rgid != pc->p_rgid && rgid != pc->pc_ucred->cr_groups[0] /* XXX */ &&
349 (error = suser(pc->pc_ucred, &p->p_acflag)))
d9c2f47f 350 return (error);
d5dc47bf 351 if (uap->egid == -1)
8429d022
MK
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)))
d9c2f47f 354 return (error);
8429d022
MK
355 pc->pc_ucred = crcopy(pc->pc_ucred);
356 pc->pc_ucred->cr_groups[0] = egid;
357 pc->p_rgid = rgid;
d9c2f47f 358 return (0);
d5dc47bf
MK
359}
360#endif
361
362/* ARGSUSED */
363setgroups(p, uap, retval)
364 struct proc *p;
365 struct args {
b32450f4 366 u_int gidsetsize;
4147b3f6 367 int *gidset;
d5dc47bf
MK
368 } *uap;
369 int *retval;
370{
8429d022 371 register struct pcred *pc = p->p_cred;
38b6104c 372 register gid_t *gp;
fca91c15 373 register u_int ngrp;
38b6104c 374 register int *lp;
446a921a 375 int error, groups[NGROUPS];
4147b3f6 376
8429d022 377 if (error = suser(pc->pc_ucred, &p->p_acflag))
d9c2f47f 378 return (error);
fca91c15 379 if ((ngrp = uap->gidsetsize) > NGROUPS)
d9c2f47f 380 return (EINVAL);
446a921a 381 if (error = copyin((caddr_t)uap->gidset, (caddr_t)groups,
fca91c15 382 ngrp * sizeof (groups[0])))
d9c2f47f 383 return (error);
8429d022
MK
384 pc->pc_ucred = crcopy(pc->pc_ucred);
385 pc->pc_ucred->cr_ngroups = ngrp;
446a921a 386 /* convert from int's to gid_t's */
8429d022 387 for (gp = pc->pc_ucred->cr_groups, lp = groups; ngrp--; )
fca91c15 388 *gp++ = *lp++;
d9c2f47f 389 return (0);
4147b3f6
BJ
390}
391
f926daf9 392/*
88a39492 393 * Check if gid is a member of the group set.
f926daf9 394 */
88a39492 395groupmember(gid, cred)
90731a34 396 gid_t gid;
88a39492 397 register struct ucred *cred;
197da11b 398{
38b6104c 399 register gid_t *gp;
88a39492 400 gid_t *egp;
197da11b 401
88a39492
KM
402 egp = &(cred->cr_groups[cred->cr_ngroups]);
403 for (gp = cred->cr_groups; gp < egp; gp++)
197da11b 404 if (*gp == gid)
88a39492
KM
405 return (1);
406 return (0);
197da11b
BJ
407}
408
f926daf9 409/*
f242743a
MK
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.
f926daf9 414 */
88a39492
KM
415suser(cred, acflag)
416 struct ucred *cred;
417 short *acflag;
197da11b 418{
88a39492
KM
419 if (cred->cr_uid == 0) {
420 if (acflag)
421 *acflag |= ASU;
422 return (0);
38b6104c 423 }
88a39492 424 return (EPERM);
197da11b 425}
f926daf9
SL
426
427/*
88a39492 428 * Allocate a zeroed cred structure.
f926daf9 429 */
88a39492
KM
430struct ucred *
431crget()
f926daf9 432{
88a39492 433 register struct ucred *cr;
f926daf9 434
88a39492
KM
435 MALLOC(cr, struct ucred *, sizeof(*cr), M_CRED, M_WAITOK);
436 bzero((caddr_t)cr, sizeof(*cr));
437 cr->cr_ref = 1;
d5dc47bf 438 return (cr);
88a39492
KM
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{
8429d022 448 int s = splimp(); /* ??? */
88a39492
KM
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
0712db82
KB
467 if (cr->cr_ref == 1)
468 return (cr);
88a39492
KM
469 newcr = crget();
470 *newcr = *cr;
471 crfree(cr);
472 newcr->cr_ref = 1;
d5dc47bf 473 return (newcr);
88a39492
KM
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;
d5dc47bf 488 return (newcr);
f926daf9 489}
5b6ee178
KF
490
491/*
164c0f54 492 * Get login name, if available.
5b6ee178 493 */
d5dc47bf
MK
494/* ARGSUSED */
495getlogin(p, uap, retval)
496 struct proc *p;
497 struct args {
5b6ee178
KF
498 char *namebuf;
499 u_int namelen;
d5dc47bf
MK
500 } *uap;
501 int *retval;
502{
5b6ee178 503
8429d022
MK
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));
5b6ee178
KF
508}
509
510/*
164c0f54 511 * Set login name.
5b6ee178 512 */
d5dc47bf
MK
513/* ARGSUSED */
514setlogin(p, uap, retval)
515 struct proc *p;
516 struct args {
5b6ee178 517 char *namebuf;
d5dc47bf
MK
518 } *uap;
519 int *retval;
520{
164c0f54 521 int error;
5b6ee178 522
8429d022 523 if (error = suser(p->p_ucred, &p->p_acflag))
d9c2f47f 524 return (error);
8429d022
MK
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)
164c0f54 529 error = EINVAL;
d9c2f47f 530 return (error);
5b6ee178 531}