xref: /original-bsd/sys/kern/kern_prot.c (revision 9a77813a)
1 /*
2  * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
3  * All rights reserved.
4  *
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  *
17  *	@(#)kern_prot.c	7.6 (Berkeley) 05/01/89
18  */
19 
20 /*
21  * System calls related to processes and protection
22  */
23 
24 #include "param.h"
25 #include "acct.h"
26 #include "systm.h"
27 #include "user.h"
28 #include "proc.h"
29 #include "timeb.h"
30 #include "times.h"
31 #include "reboot.h"
32 #include "mount.h"
33 #include "buf.h"
34 #include "../ufs/quota.h"
35 #include "malloc.h"
36 #define GRPSTART 0
37 
38 #include "machine/reg.h"
39 
40 getpid()
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 
47 getpgrp()
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)
55 		p = u.u_procp;
56 	else if ((p = pfind(uap->pid)) == 0) {
57 		u.u_error = ESRCH;
58 		return;
59 	}
60 	u.u_r.r_val1 = p->p_pgrp->pg_id;
61 }
62 
63 getuid()
64 {
65 
66 	u.u_r.r_val1 = u.u_ruid;
67 	u.u_r.r_val2 = u.u_uid;
68 }
69 
70 getgid()
71 {
72 
73 	u.u_r.r_val1 = u.u_rgid;
74 	u.u_r.r_val2 = u.u_gid;
75 }
76 
77 getgroups()
78 {
79 	register struct	a {
80 		u_int	gidsetsize;
81 		int	*gidset;
82 	} *uap = (struct a *)u.u_ap;
83 	register gid_t *gp;
84 	register int *lp;
85 	int groups[NGROUPS];
86 
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) {
92 		u.u_error = EINVAL;
93 		return;
94 	}
95 	uap->gidsetsize = u.u_ngroups - GRPSTART;
96 	gp = &u.u_groups[GRPSTART];
97 	for (lp = groups; lp < &groups[uap->gidsetsize]; )
98 		*lp++ = *gp++;
99 	u.u_error = copyout((caddr_t)groups, (caddr_t)uap->gidset,
100 	    uap->gidsetsize * sizeof (groups[0]));
101 	if (u.u_error)
102 		return;
103 	u.u_r.r_val1 = uap->gidsetsize;
104 }
105 
106 setsid()
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  */
129 setpgrp()
130 {
131 	register struct a {
132 		int	pid;
133 		int	pgid;
134 	} *uap = (struct a *)u.u_ap;
135 	register struct proc *p;
136 	register struct pgrp *pgrp;
137 
138 	if (uap->pid == 0)
139 		p = u.u_procp;
140 	else if ((p = pfind(uap->pid)) == 0 || !inferior(p)) {
141 		u.u_error = ESRCH;
142 		return;
143 	}
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)) {
164 		u.u_error = EPERM;
165 		return;
166 	}
167 	/*
168 	 * done checking, now doit
169 	 */
170 	pgmv(p, uap->pgid, 0);
171 }
172 
173 setreuid()
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;
185 	if (u.u_ruid != ruid && u.u_uid != ruid &&
186 	    (u.u_error = suser(u.u_cred, &u.u_acflag)))
187 		return;
188 	euid = uap->euid;
189 	if (euid == -1)
190 		euid = u.u_uid;
191 	if (u.u_ruid != euid && u.u_uid != euid &&
192 	    (u.u_error = suser(u.u_cred, &u.u_acflag)))
193 		return;
194 	/*
195 	 * Everything's okay, do it.
196 	 * Copy credentials so other references do not
197 	 * see our changes.
198 	 */
199 #ifdef QUOTA
200 	if (u.u_quota->q_uid != ruid) {
201 		qclean();
202 		qstart(getquota((uid_t)ruid, 0, 0));
203 	}
204 #endif
205 	if (u.u_cred->cr_ref > 1)
206 		u.u_cred = crcopy(u.u_cred);
207 	u.u_procp->p_uid = euid;
208 	u.u_ruid = ruid;
209 	u.u_uid = euid;
210 }
211 
212 setregid()
213 {
214 	register struct a {
215 		int	rgid;
216 		int	egid;
217 	} *uap;
218 	register int rgid, egid;
219 
220 	uap = (struct a *)u.u_ap;
221 	rgid = uap->rgid;
222 	if (rgid == -1)
223 		rgid = u.u_rgid;
224 	if (u.u_rgid != rgid && u.u_gid != rgid &&
225 	    (u.u_error = suser(u.u_cred, &u.u_acflag)))
226 		return;
227 	egid = uap->egid;
228 	if (egid == -1)
229 		egid = u.u_gid;
230 	if (u.u_rgid != egid && u.u_gid != egid &&
231 	    (u.u_error = suser(u.u_cred, &u.u_acflag)))
232 		return;
233 	if (u.u_cred->cr_ref > 1)
234 		u.u_cred = crcopy(u.u_cred);
235 	u.u_rgid = rgid;
236 	u.u_gid = egid;
237 }
238 
239 setgroups()
240 {
241 	register struct	a {
242 		u_int	gidsetsize;
243 		int	*gidset;
244 	} *uap = (struct a *)u.u_ap;
245 	register gid_t *gp;
246 	register int *lp;
247 	int ngrp, groups[NGROUPS];
248 
249 	if (u.u_error = suser(u.u_cred, &u.u_acflag))
250 		return;
251 	ngrp = uap->gidsetsize + GRPSTART;
252 	if (ngrp > sizeof (u.u_groups) / sizeof (u.u_groups[0])) {
253 		u.u_error = EINVAL;
254 		return;
255 	}
256 	u.u_error = copyin((caddr_t)uap->gidset, (caddr_t)groups,
257 	    uap->gidsetsize * sizeof (groups[0]));
258 	if (u.u_error)
259 		return;
260 	gp = &u.u_groups[GRPSTART];
261 	for (lp = groups; lp < &groups[uap->gidsetsize]; )
262 		*gp++ = *lp++;
263 	u.u_ngroups = ngrp;
264 }
265 
266 /*
267  * Check if gid is a member of the group set.
268  */
269 groupmember(gid, cred)
270 	gid_t gid;
271 	register struct ucred *cred;
272 {
273 	register gid_t *gp;
274 	gid_t *egp;
275 
276 	egp = &(cred->cr_groups[cred->cr_ngroups]);
277 	for (gp = cred->cr_groups; gp < egp; gp++)
278 		if (*gp == gid)
279 			return (1);
280 	return (0);
281 }
282 
283 /*
284  * Test if the current user is the super user.
285  */
286 suser(cred, acflag)
287 	struct ucred *cred;
288 	short *acflag;
289 {
290 
291 	if (cred->cr_uid == 0) {
292 		if (acflag)
293 			*acflag |= ASU;
294 		return (0);
295 	}
296 	return (EPERM);
297 }
298 
299 /*
300  * Allocate a zeroed cred structure.
301  */
302 struct ucred *
303 crget()
304 {
305 	register struct ucred *cr;
306 
307 	MALLOC(cr, struct ucred *, sizeof(*cr), M_CRED, M_WAITOK);
308 	bzero((caddr_t)cr, sizeof(*cr));
309 	cr->cr_ref = 1;
310 	return(cr);
311 }
312 
313 /*
314  * Free a cred structure.
315  * Throws away space when ref count gets to 0.
316  */
317 crfree(cr)
318 	struct ucred *cr;
319 {
320 	int	s = splimp();
321 
322 	if (--cr->cr_ref != 0) {
323 		(void) splx(s);
324 		return;
325 	}
326 	FREE((caddr_t)cr, M_CRED);
327 	(void) splx(s);
328 }
329 
330 /*
331  * Copy cred structure to a new one and free the old one.
332  */
333 struct ucred *
334 crcopy(cr)
335 	struct ucred *cr;
336 {
337 	struct ucred *newcr;
338 
339 	newcr = crget();
340 	*newcr = *cr;
341 	crfree(cr);
342 	newcr->cr_ref = 1;
343 	return(newcr);
344 }
345 
346 /*
347  * Dup cred struct to a new held one.
348  */
349 struct ucred *
350 crdup(cr)
351 	struct ucred *cr;
352 {
353 	struct ucred *newcr;
354 
355 	newcr = crget();
356 	*newcr = *cr;
357 	newcr->cr_ref = 1;
358 	return(newcr);
359 }
360 
361 /*
362  * Get login name of process owner, if available
363  */
364 
365 getlogname()
366 {
367 	struct a {
368 		char	*namebuf;
369 		u_int	namelen;
370 	} *uap = (struct a *)u.u_ap;
371 
372 	if (uap->namelen > sizeof (u.u_logname))
373 		uap->namelen = sizeof (u.u_logname);
374 	u.u_error = copyout((caddr_t)u.u_logname, (caddr_t)uap->namebuf,
375 		uap->namelen);
376 }
377 
378 /*
379  * Set login name of process owner
380  */
381 
382 setlogname()
383 {
384 	struct a {
385 		char	*namebuf;
386 		u_int	namelen;
387 	} *uap = (struct a *)u.u_ap;
388 
389 	if (u.u_error = suser(u.u_cred, &u.u_acflag))
390 		return;
391 	if (uap->namelen > sizeof (u.u_logname) - 1)
392 		u.u_error = EINVAL;
393 	else
394 		u.u_error = copyin((caddr_t)uap->namebuf,
395 			(caddr_t)u.u_logname, uap->namelen);
396 }
397