setgroups check int > NGROUPS, so negative would fail; minor cleanup
[unix-history] / usr / src / sys / kern / kern_prot.c
CommitLineData
da7c5cc6 1/*
d5dc47bf 2 * Copyright (c) 1982, 1986, 1989, 1990 Regents of the University of California.
88a39492 3 * All rights reserved.
da7c5cc6 4 *
dbf0c423 5 * %sccs.include.redist.c%
88a39492 6 *
446a921a 7 * @(#)kern_prot.c 7.14 (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"
d9c2f47f 17#include "user.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
32 retval[1] = p->p_ppid;
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
MK
43
44 *retval = p->p_ppid;
d9c2f47f 45 return (0);
d5dc47bf
MK
46}
47
48getpgrp(p, uap, retval)
49 struct proc *p;
50 struct args {
4147b3f6 51 int pid;
d5dc47bf
MK
52 } *uap;
53 int *retval;
54{
4147b3f6 55
d5dc47bf 56 if (uap->pid != 0 && (p = pfind(uap->pid)) == 0)
d9c2f47f 57 return (ESRCH);
d5dc47bf 58 *retval = p->p_pgrp->pg_id;
d9c2f47f 59 return (0);
4147b3f6
BJ
60}
61
d5dc47bf
MK
62/* ARGSUSED */
63getuid(p, uap, retval)
64 struct proc *p;
65 void *uap;
66 int *retval;
a05af100
BJ
67{
68
d5dc47bf
MK
69 *retval = p->p_ruid;
70#ifdef COMPAT_43
71 retval[1] = u.u_cred->cr_uid;
72#endif
d9c2f47f 73 return (0);
a05af100
BJ
74}
75
d5dc47bf
MK
76/* ARGSUSED */
77geteuid(p, uap, retval)
78 struct proc *p;
79 void *uap;
80 int *retval;
4147b3f6
BJ
81{
82
d5dc47bf 83 *retval = u.u_cred->cr_uid;
d9c2f47f 84 return (0);
4147b3f6
BJ
85}
86
d5dc47bf
MK
87/* ARGSUSED */
88getgid(p, uap, retval)
89 struct proc *p;
90 void *uap;
91 int *retval;
92{
93
94 *retval = p->p_rgid;
95#ifdef COMPAT_43
96 retval[1] = u.u_cred->cr_groups[0];
97#endif
d9c2f47f 98 return (0);
d5dc47bf
MK
99}
100
101/*
102 * Get effective group ID.
103 * The "egid" is groups[0], and thus could be obtained via getgroups;
104 * this is somewhat painful to do correctly in a library function,
105 * this the existence of this syscall.
106 */
107/* ARGSUSED */
108getegid(p, uap, retval)
109 struct proc *p;
110 void *uap;
111 int *retval;
4147b3f6 112{
d5dc47bf
MK
113
114 *retval = u.u_cred->cr_groups[0];
d9c2f47f 115 return (0);
d5dc47bf
MK
116}
117
118getgroups(p, uap, retval)
119 struct proc *p;
120 register struct arg {
b32450f4 121 u_int gidsetsize;
d5dc47bf
MK
122 int *gidset; /* XXX not yet POSIX */
123 } *uap;
124 int *retval;
125{
38b6104c
MK
126 register gid_t *gp;
127 register int *lp;
128 int groups[NGROUPS];
d5dc47bf 129 int error;
4147b3f6 130
88a39492 131 if (uap->gidsetsize == 0) {
d5dc47bf 132 *retval = u.u_cred->cr_ngroups;
d9c2f47f 133 return (0);
197da11b 134 }
d5dc47bf 135 if (uap->gidsetsize < u.u_cred->cr_ngroups)
d9c2f47f 136 return (EINVAL);
164c0f54
MK
137 uap->gidsetsize = u.u_cred->cr_ngroups;
138 gp = u.u_cred->cr_groups;
88a39492 139 for (lp = groups; lp < &groups[uap->gidsetsize]; )
38b6104c 140 *lp++ = *gp++;
d5dc47bf
MK
141 if (error = copyout((caddr_t)groups, (caddr_t)uap->gidset,
142 uap->gidsetsize * sizeof (groups[0])))
d9c2f47f 143 return (error);
d5dc47bf 144 *retval = uap->gidsetsize;
d9c2f47f 145 return (0);
4147b3f6
BJ
146}
147
d5dc47bf
MK
148/* ARGSUSED */
149setsid(p, uap, retval)
150 struct proc *p;
151 void *uap;
152 int *retval;
8fe87cbb 153{
8fe87cbb 154
d5dc47bf 155 if (p->p_pgid == p->p_pid || pgfind(p->p_pid)) {
d9c2f47f 156 return (EPERM);
d5dc47bf 157 } else {
8fe87cbb 158 pgmv(p, p->p_pid, 1);
d5dc47bf 159 *retval = p->p_pid;
d9c2f47f 160 return (0);
8fe87cbb 161 }
8fe87cbb
MT
162}
163
164/*
d5dc47bf 165 * set process group (setpgrp/setpgid)
8fe87cbb 166 *
164c0f54
MK
167 * caller does setpgrp(pid, pgid)
168 *
169 * pid must be caller or child of caller (ESRCH)
170 * if a child
171 * pid must be in same session (EPERM)
172 * pid can't have done an exec (EACCES)
173 * if pgid != pid
174 * there must exist some pid in same session having pgid (EPERM)
175 * pid must not be session leader (EPERM)
8fe87cbb 176 */
d5dc47bf
MK
177/* ARGSUSED */
178setpgrp(cp, uap, retval)
179 struct proc *cp;
180 register struct args {
4147b3f6 181 int pid;
8fe87cbb 182 int pgid;
d5dc47bf
MK
183 } *uap;
184 int *retval;
185{
8fe87cbb
MT
186 register struct proc *p;
187 register struct pgrp *pgrp;
4147b3f6 188
d5dc47bf
MK
189 if (uap->pid != 0) {
190 if ((p = pfind(uap->pid)) == 0 || !inferior(p))
d9c2f47f 191 return (ESRCH);
d5dc47bf 192 if (p->p_session != cp->p_session)
d9c2f47f 193 return (EPERM);
d5dc47bf 194 if (p->p_flag&SEXEC)
d9c2f47f 195 return (EACCES);
d5dc47bf
MK
196 } else
197 p = cp;
198 if (SESS_LEADER(p))
d9c2f47f 199 return (EPERM);
8fe87cbb
MT
200 if (uap->pgid == 0)
201 uap->pgid = p->p_pid;
202 else if ((uap->pgid != p->p_pid) &&
203 (((pgrp = pgfind(uap->pgid)) == 0) ||
204 pgrp->pg_mem == NULL ||
d5dc47bf 205 pgrp->pg_session != u.u_procp->p_session))
d9c2f47f 206 return (EPERM);
8fe87cbb 207 /*
d5dc47bf 208 * done checking, now do it
8fe87cbb
MT
209 */
210 pgmv(p, uap->pgid, 0);
d9c2f47f 211 return (0);
4147b3f6
BJ
212}
213
d5dc47bf
MK
214/* ARGSUSED */
215setuid(p, uap, retval)
216 register struct proc *p;
217 struct args {
218 int uid;
219 } *uap;
220 int *retval;
4f083fd7 221{
d5dc47bf
MK
222 register uid_t uid;
223 int error;
224
225 uid = uap->uid;
226 if (uid != p->p_ruid && (error = suser(u.u_cred, &u.u_acflag)))
d9c2f47f 227 return (error);
d5dc47bf
MK
228 /*
229 * Everything's okay, do it.
230 * Copy credentials so other references do not
231 * see our changes.
232 */
233 if (u.u_cred->cr_ref > 1)
234 u.u_cred = crcopy(u.u_cred);
235 u.u_cred->cr_uid = uid;
236 p->p_uid = uid;
237 p->p_ruid = uid;
238 p->p_svuid = uid;
d9c2f47f 239 return (0);
d5dc47bf
MK
240}
241
242/* ARGSUSED */
243seteuid(p, uap, retval)
244 register struct proc *p;
245 struct args {
4f083fd7
SL
246 int euid;
247 } *uap;
d5dc47bf
MK
248 int *retval;
249{
250 register uid_t euid;
251 int error;
4f083fd7 252
4f083fd7 253 euid = uap->euid;
d5dc47bf
MK
254 if (euid != p->p_ruid && euid != p->p_svuid &&
255 (error = suser(u.u_cred, &u.u_acflag)))
d9c2f47f 256 return (error);
4f083fd7
SL
257 /*
258 * Everything's okay, do it.
88a39492
KM
259 * Copy credentials so other references do not
260 * see our changes.
4f083fd7 261 */
88a39492
KM
262 if (u.u_cred->cr_ref > 1)
263 u.u_cred = crcopy(u.u_cred);
164c0f54
MK
264 u.u_cred->cr_uid = euid;
265 p->p_uid = euid;
d9c2f47f 266 return (0);
4f083fd7
SL
267}
268
d5dc47bf
MK
269/* ARGSUSED */
270setgid(p, uap, retval)
271 struct proc *p;
272 struct args {
273 int gid;
274 } *uap;
275 int *retval;
4f083fd7 276{
d5dc47bf
MK
277 register gid_t gid;
278 int error;
279
280 gid = uap->gid;
281 if (gid != p->p_rgid && (error = suser(u.u_cred, &u.u_acflag)))
d9c2f47f 282 return (error);
d5dc47bf
MK
283 if (u.u_cred->cr_ref > 1)
284 u.u_cred = crcopy(u.u_cred);
285 p->p_rgid = gid;
286 u.u_cred->cr_groups[0] = gid;
287 p->p_svgid = gid; /* ??? */
d9c2f47f 288 return (0);
d5dc47bf
MK
289}
290
291/* ARGSUSED */
292setegid(p, uap, retval)
293 struct proc *p;
294 struct args {
4f083fd7
SL
295 int egid;
296 } *uap;
d5dc47bf
MK
297 int *retval;
298{
299 register gid_t egid;
300 int error;
4f083fd7 301
4f083fd7 302 egid = uap->egid;
d5dc47bf
MK
303 if (egid != p->p_rgid && egid != p->p_svgid &&
304 (error = suser(u.u_cred, &u.u_acflag)))
d9c2f47f 305 return (error);
88a39492
KM
306 if (u.u_cred->cr_ref > 1)
307 u.u_cred = crcopy(u.u_cred);
164c0f54 308 u.u_cred->cr_groups[0] = egid;
d9c2f47f 309 return (0);
d5dc47bf
MK
310}
311
312#ifdef COMPAT_43
313/* ARGSUSED */
314osetreuid(p, uap, retval)
315 register struct proc *p;
316 struct args {
317 int ruid;
318 int euid;
319 } *uap;
320 int *retval;
321{
322 register uid_t ruid, euid;
323 int error;
324
325 if (uap->ruid == -1)
326 (error = suser(u.u_cred, &u.u_acflag)))
d9c2f47f 327 return (error);
d5dc47bf
MK
328 if (uap->euid == -1)
329 euid != p->p_svuid && (error = suser(u.u_cred, &u.u_acflag)))
d9c2f47f 330 return (error);
d5dc47bf
MK
331 /*
332 * Everything's okay, do it.
333 * Copy credentials so other references do not
334 * see our changes.
335 */
336 if (u.u_cred->cr_ref > 1)
337 u.u_cred = crcopy(u.u_cred);
338 u.u_cred->cr_uid = euid;
339 p->p_uid = euid;
340 p->p_ruid = ruid;
d9c2f47f 341 return (0);
4f083fd7 342}
a05af100 343
d5dc47bf
MK
344/* ARGSUSED */
345osetregid(p, uap, retval)
346 struct proc *p;
347 struct args {
348 int rgid;
349 int egid;
350 } *uap;
351 int *retval;
4147b3f6 352{
d5dc47bf
MK
353 register gid_t rgid, egid;
354 int error;
355
356 if (uap->rgid == -1)
357 (error = suser(u.u_cred, &u.u_acflag)))
d9c2f47f 358 return (error);
d5dc47bf
MK
359 if (uap->egid == -1)
360 egid != p->p_svgid && (error = suser(u.u_cred, &u.u_acflag)))
d9c2f47f 361 return (error);
d5dc47bf
MK
362 if (u.u_cred->cr_ref > 1)
363 u.u_cred = crcopy(u.u_cred);
364 p->p_rgid = rgid;
365 u.u_cred->cr_groups[0] = egid;
d9c2f47f 366 return (0);
d5dc47bf
MK
367}
368#endif
369
370/* ARGSUSED */
371setgroups(p, uap, retval)
372 struct proc *p;
373 struct args {
b32450f4 374 u_int gidsetsize;
4147b3f6 375 int *gidset;
d5dc47bf
MK
376 } *uap;
377 int *retval;
378{
38b6104c 379 register gid_t *gp;
446a921a 380 register u_int ngrps;
38b6104c 381 register int *lp;
446a921a 382 int error, groups[NGROUPS];
4147b3f6 383
d5dc47bf 384 if (error = suser(u.u_cred, &u.u_acflag))
d9c2f47f 385 return (error);
446a921a 386 if ((ngrps = uap->gidsetsize) > NGROUPS)
d9c2f47f 387 return (EINVAL);
446a921a
KB
388 if (error = copyin((caddr_t)uap->gidset, (caddr_t)groups,
389 ngrps * sizeof (groups[0])))
d9c2f47f 390 return (error);
446a921a
KB
391 u.u_cred->cr_ngroups = ngrps;
392 /* convert from int's to gid_t's */
393 for (gp = u.u_cred->cr_groups, lp = groups; ngrps--; *gp++ = *lp++)
394 /* void */;
d9c2f47f 395 return (0);
4147b3f6
BJ
396}
397
f926daf9 398/*
88a39492 399 * Check if gid is a member of the group set.
f926daf9 400 */
88a39492 401groupmember(gid, cred)
90731a34 402 gid_t gid;
88a39492 403 register struct ucred *cred;
197da11b 404{
38b6104c 405 register gid_t *gp;
88a39492 406 gid_t *egp;
197da11b 407
88a39492
KM
408 egp = &(cred->cr_groups[cred->cr_ngroups]);
409 for (gp = cred->cr_groups; gp < egp; gp++)
197da11b 410 if (*gp == gid)
88a39492
KM
411 return (1);
412 return (0);
197da11b
BJ
413}
414
f926daf9 415/*
88a39492 416 * Test if the current user is the super user.
f926daf9 417 */
88a39492
KM
418suser(cred, acflag)
419 struct ucred *cred;
420 short *acflag;
197da11b 421{
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{
d5dc47bf 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
471 newcr = crget();
472 *newcr = *cr;
473 crfree(cr);
474 newcr->cr_ref = 1;
d5dc47bf 475 return (newcr);
88a39492
KM
476}
477
478/*
479 * Dup cred struct to a new held one.
480 */
481struct ucred *
482crdup(cr)
483 struct ucred *cr;
484{
485 struct ucred *newcr;
486
487 newcr = crget();
488 *newcr = *cr;
489 newcr->cr_ref = 1;
d5dc47bf 490 return (newcr);
f926daf9 491}
5b6ee178
KF
492
493/*
164c0f54 494 * Get login name, if available.
5b6ee178 495 */
d5dc47bf
MK
496/* ARGSUSED */
497getlogin(p, uap, retval)
498 struct proc *p;
499 struct args {
5b6ee178
KF
500 char *namebuf;
501 u_int namelen;
d5dc47bf
MK
502 } *uap;
503 int *retval;
504{
5b6ee178 505
d5dc47bf
MK
506 if (uap->namelen > sizeof (p->p_logname))
507 uap->namelen = sizeof (p->p_logname);
d9c2f47f 508 return (copyout((caddr_t)p->p_logname, (caddr_t)uap->namebuf,
d5dc47bf 509 uap->namelen));
5b6ee178
KF
510}
511
512/*
164c0f54 513 * Set login name.
5b6ee178 514 */
d5dc47bf
MK
515/* ARGSUSED */
516setlogin(p, uap, retval)
517 struct proc *p;
518 struct args {
5b6ee178 519 char *namebuf;
d5dc47bf
MK
520 } *uap;
521 int *retval;
522{
164c0f54 523 int error;
5b6ee178 524
d5dc47bf 525 if (error = suser(u.u_cred, &u.u_acflag))
d9c2f47f 526 return (error);
d5dc47bf
MK
527 error = copyinstr((caddr_t)uap->namebuf, (caddr_t)p->p_logname,
528 sizeof (p->p_logname) - 1, (int *) 0);
164c0f54
MK
529 if (error == ENOENT) /* name too long */
530 error = EINVAL;
d9c2f47f 531 return (error);
5b6ee178 532}