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