blkflush is no longer used;
[unix-history] / usr / src / sys / kern / kern_prot.c
CommitLineData
da7c5cc6 1/*
88a39492
KM
2 * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
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 *
25ecd183 17 * @(#)kern_prot.c 7.7 (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"
94368568 27#include "user.h"
94368568
JB
28#include "proc.h"
29#include "timeb.h"
30#include "times.h"
31#include "reboot.h"
94368568 32#include "mount.h"
88a39492
KM
33#include "buf.h"
34#include "../ufs/quota.h"
35#include "malloc.h"
36#define GRPSTART 0
a05af100 37
d301d150
KM
38#include "machine/reg.h"
39
4147b3f6
BJ
40getpid()
41{
42
43 u.u_r.r_val1 = u.u_procp->p_pid;
44 u.u_r.r_val2 = u.u_procp->p_ppid;
45}
46
47getpgrp()
48{
49 register struct a {
50 int pid;
51 } *uap = (struct a *)u.u_ap;
52 register struct proc *p;
53
54 if (uap->pid == 0)
8fe87cbb
MT
55 p = u.u_procp;
56 else if ((p = pfind(uap->pid)) == 0) {
4147b3f6
BJ
57 u.u_error = ESRCH;
58 return;
59 }
8fe87cbb 60 u.u_r.r_val1 = p->p_pgrp->pg_id;
4147b3f6
BJ
61}
62
a05af100
BJ
63getuid()
64{
65
66 u.u_r.r_val1 = u.u_ruid;
67 u.u_r.r_val2 = u.u_uid;
68}
69
4147b3f6
BJ
70getgid()
71{
72
73 u.u_r.r_val1 = u.u_rgid;
74 u.u_r.r_val2 = u.u_gid;
75}
76
197da11b 77getgroups()
4147b3f6
BJ
78{
79 register struct a {
b32450f4 80 u_int gidsetsize;
4147b3f6
BJ
81 int *gidset;
82 } *uap = (struct a *)u.u_ap;
38b6104c
MK
83 register gid_t *gp;
84 register int *lp;
85 int groups[NGROUPS];
4147b3f6 86
88a39492
KM
87 if (uap->gidsetsize == 0) {
88 u.u_r.r_val1 = u.u_ngroups - GRPSTART;
89 return;
90 }
91 if (uap->gidsetsize < u.u_ngroups - GRPSTART) {
197da11b
BJ
92 u.u_error = EINVAL;
93 return;
94 }
88a39492
KM
95 uap->gidsetsize = u.u_ngroups - GRPSTART;
96 gp = &u.u_groups[GRPSTART];
97 for (lp = groups; lp < &groups[uap->gidsetsize]; )
38b6104c
MK
98 *lp++ = *gp++;
99 u.u_error = copyout((caddr_t)groups, (caddr_t)uap->gidset,
100 uap->gidsetsize * sizeof (groups[0]));
127f7d76 101 if (u.u_error)
4147b3f6 102 return;
197da11b 103 u.u_r.r_val1 = uap->gidsetsize;
4147b3f6
BJ
104}
105
8fe87cbb
MT
106setsid()
107{
108 register struct proc *p = u.u_procp;
109
110 if ((p->p_pgid == p->p_pid) || pgfind(p->p_pid))
111 u.u_error = EPERM;
112 else {
113 pgmv(p, p->p_pid, 1);
114 u.u_r.r_val1 = p->p_pid;
115 }
116 return;
117}
118
119/*
120 * set process group
121 *
122 * if target pid != caller's pid
123 * pid must be an inferior
124 * pid must be in same session
125 * pid can't have done an exec
126 * there must exist a pid with pgid in same session
127 * pid must not be session leader
128 */
4147b3f6
BJ
129setpgrp()
130{
4147b3f6
BJ
131 register struct a {
132 int pid;
8fe87cbb 133 int pgid;
4147b3f6 134 } *uap = (struct a *)u.u_ap;
8fe87cbb
MT
135 register struct proc *p;
136 register struct pgrp *pgrp;
4147b3f6
BJ
137
138 if (uap->pid == 0)
8fe87cbb
MT
139 p = u.u_procp;
140 else if ((p = pfind(uap->pid)) == 0 || !inferior(p)) {
4147b3f6
BJ
141 u.u_error = ESRCH;
142 return;
143 }
8fe87cbb
MT
144 else if (p != u.u_procp) {
145 if (p->p_session != u.u_procp->p_session) {
146 u.u_error = EPERM;
147 return;
148 }
149 if (p->p_flag&SEXEC) {
150 u.u_error = EACCES;
151 return;
152 }
153 }
154 if (SESS_LEADER(p)) {
155 u.u_error = EPERM;
156 return;
157 }
158 if (uap->pgid == 0)
159 uap->pgid = p->p_pid;
160 else if ((uap->pgid != p->p_pid) &&
161 (((pgrp = pgfind(uap->pgid)) == 0) ||
162 pgrp->pg_mem == NULL ||
163 pgrp->pg_session != u.u_procp->p_session)) {
4147b3f6
BJ
164 u.u_error = EPERM;
165 return;
166 }
8fe87cbb
MT
167 /*
168 * done checking, now doit
169 */
170 pgmv(p, uap->pgid, 0);
4147b3f6
BJ
171}
172
4f083fd7
SL
173setreuid()
174{
175 struct a {
176 int ruid;
177 int euid;
178 } *uap;
179 register int ruid, euid;
180
181 uap = (struct a *)u.u_ap;
182 ruid = uap->ruid;
183 if (ruid == -1)
184 ruid = u.u_ruid;
4f083fd7
SL
185 return;
186 euid = uap->euid;
187 if (euid == -1)
188 euid = u.u_uid;
4f083fd7
SL
189 return;
190 /*
191 * Everything's okay, do it.
88a39492
KM
192 * Copy credentials so other references do not
193 * see our changes.
4f083fd7 194 */
4f083fd7 195#ifdef QUOTA
709593b8
SL
196 if (u.u_quota->q_uid != ruid) {
197 qclean();
8011f5df 198 qstart(getquota((uid_t)ruid, 0, 0));
4f083fd7 199 }
709593b8 200#endif
88a39492
KM
201 if (u.u_cred->cr_ref > 1)
202 u.u_cred = crcopy(u.u_cred);
d3e64b9b 203 u.u_procp->p_uid = euid;
709593b8 204 u.u_ruid = ruid;
4f083fd7
SL
205 u.u_uid = euid;
206}
207
4f083fd7
SL
208setregid()
209{
210 register struct a {
211 int rgid;
212 int egid;
213 } *uap;
214 register int rgid, egid;
215
216 uap = (struct a *)u.u_ap;
217 rgid = uap->rgid;
218 if (rgid == -1)
219 rgid = u.u_rgid;
4f083fd7
SL
220 return;
221 egid = uap->egid;
222 if (egid == -1)
223 egid = u.u_gid;
4f083fd7 224 return;
88a39492
KM
225 if (u.u_cred->cr_ref > 1)
226 u.u_cred = crcopy(u.u_cred);
227 u.u_rgid = rgid;
955b5346 228 u.u_gid = egid;
4f083fd7 229}
a05af100 230
197da11b 231setgroups()
4147b3f6
BJ
232{
233 register struct a {
b32450f4 234 u_int gidsetsize;
4147b3f6
BJ
235 int *gidset;
236 } *uap = (struct a *)u.u_ap;
38b6104c
MK
237 register gid_t *gp;
238 register int *lp;
88a39492 239 int ngrp, groups[NGROUPS];
4147b3f6 240
849cbd39 241 if (u.u_error = suser(u.u_cred, &u.u_acflag))
4147b3f6 242 return;
88a39492
KM
243 ngrp = uap->gidsetsize + GRPSTART;
244 if (ngrp > sizeof (u.u_groups) / sizeof (u.u_groups[0])) {
197da11b 245 u.u_error = EINVAL;
4147b3f6
BJ
246 return;
247 }
38b6104c
MK
248 u.u_error = copyin((caddr_t)uap->gidset, (caddr_t)groups,
249 uap->gidsetsize * sizeof (groups[0]));
127f7d76 250 if (u.u_error)
4147b3f6 251 return;
88a39492
KM
252 gp = &u.u_groups[GRPSTART];
253 for (lp = groups; lp < &groups[uap->gidsetsize]; )
38b6104c 254 *gp++ = *lp++;
88a39492 255 u.u_ngroups = ngrp;
4147b3f6
BJ
256}
257
f926daf9 258/*
88a39492 259 * Check if gid is a member of the group set.
f926daf9 260 */
88a39492 261groupmember(gid, cred)
90731a34 262 gid_t gid;
88a39492 263 register struct ucred *cred;
197da11b 264{
38b6104c 265 register gid_t *gp;
88a39492 266 gid_t *egp;
197da11b 267
88a39492
KM
268 egp = &(cred->cr_groups[cred->cr_ngroups]);
269 for (gp = cred->cr_groups; gp < egp; gp++)
197da11b 270 if (*gp == gid)
88a39492
KM
271 return (1);
272 return (0);
197da11b
BJ
273}
274
f926daf9 275/*
88a39492 276 * Test if the current user is the super user.
f926daf9 277 */
88a39492
KM
278suser(cred, acflag)
279 struct ucred *cred;
280 short *acflag;
197da11b 281{
197da11b 282
88a39492
KM
283 if (cred->cr_uid == 0) {
284 if (acflag)
285 *acflag |= ASU;
286 return (0);
38b6104c 287 }
88a39492 288 return (EPERM);
197da11b 289}
f926daf9
SL
290
291/*
88a39492 292 * Allocate a zeroed cred structure.
f926daf9 293 */
88a39492
KM
294struct ucred *
295crget()
f926daf9 296{
88a39492 297 register struct ucred *cr;
f926daf9 298
88a39492
KM
299 MALLOC(cr, struct ucred *, sizeof(*cr), M_CRED, M_WAITOK);
300 bzero((caddr_t)cr, sizeof(*cr));
301 cr->cr_ref = 1;
302 return(cr);
303}
304
305/*
306 * Free a cred structure.
307 * Throws away space when ref count gets to 0.
308 */
309crfree(cr)
310 struct ucred *cr;
311{
312 int s = splimp();
313
314 if (--cr->cr_ref != 0) {
315 (void) splx(s);
316 return;
317 }
318 FREE((caddr_t)cr, M_CRED);
319 (void) splx(s);
320}
321
322/*
323 * Copy cred structure to a new one and free the old one.
324 */
325struct ucred *
326crcopy(cr)
327 struct ucred *cr;
328{
329 struct ucred *newcr;
330
331 newcr = crget();
332 *newcr = *cr;
333 crfree(cr);
334 newcr->cr_ref = 1;
335 return(newcr);
336}
337
338/*
339 * Dup cred struct to a new held one.
340 */
341struct ucred *
342crdup(cr)
343 struct ucred *cr;
344{
345 struct ucred *newcr;
346
347 newcr = crget();
348 *newcr = *cr;
349 newcr->cr_ref = 1;
350 return(newcr);
f926daf9 351}
5b6ee178
KF
352
353/*
354 * Get login name of process owner, if available
355 */
356
357getlogname()
358{
359 struct a {
360 char *namebuf;
361 u_int namelen;
362 } *uap = (struct a *)u.u_ap;
363
364 if (uap->namelen > sizeof (u.u_logname))
365 uap->namelen = sizeof (u.u_logname);
366 u.u_error = copyout((caddr_t)u.u_logname, (caddr_t)uap->namebuf,
367 uap->namelen);
368}
369
370/*
371 * Set login name of process owner
372 */
373
374setlogname()
375{
376 struct a {
377 char *namebuf;
378 u_int namelen;
379 } *uap = (struct a *)u.u_ap;
380
849cbd39
KM
381 if (u.u_error = suser(u.u_cred, &u.u_acflag))
382 return;
383 if (uap->namelen > sizeof (u.u_logname) - 1)
384 u.u_error = EINVAL;
25ecd183
KF
385 else {
386 u.u_logname[uap->namelen] = NULL;
849cbd39
KM
387 u.u_error = copyin((caddr_t)uap->namebuf,
388 (caddr_t)u.u_logname, uap->namelen);
25ecd183 389 }
5b6ee178 390}