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