xref: /csrg-svn/sys/kern/kern_prot.c (revision 37553)
1 /*
2  * Copyright (c) 1982, 1986 Regents of the University of California.
3  * All rights reserved.  The Berkeley software License Agreement
4  * specifies the terms and conditions for redistribution.
5  *
6  *	@(#)kern_prot.c	7.5 (Berkeley) 04/26/89
7  */
8 
9 /*
10  * System calls related to processes and protection
11  */
12 
13 #include "param.h"
14 #include "systm.h"
15 #include "dir.h"
16 #include "user.h"
17 #include "inode.h"
18 #include "proc.h"
19 #include "timeb.h"
20 #include "times.h"
21 #include "reboot.h"
22 #include "fs.h"
23 #include "buf.h"
24 #include "mount.h"
25 #include "quota.h"
26 
27 #include "machine/reg.h"
28 
29 getpid()
30 {
31 
32 	u.u_r.r_val1 = u.u_procp->p_pid;
33 	u.u_r.r_val2 = u.u_procp->p_ppid;
34 }
35 
36 getpgrp()
37 {
38 	register struct a {
39 		int	pid;
40 	} *uap = (struct a *)u.u_ap;
41 	register struct proc *p;
42 
43 	if (uap->pid == 0)
44 		p = u.u_procp;
45 	else if ((p = pfind(uap->pid)) == 0) {
46 		u.u_error = ESRCH;
47 		return;
48 	}
49 	u.u_r.r_val1 = p->p_pgrp->pg_id;
50 }
51 
52 getuid()
53 {
54 
55 	u.u_r.r_val1 = u.u_ruid;
56 	u.u_r.r_val2 = u.u_uid;
57 }
58 
59 getgid()
60 {
61 
62 	u.u_r.r_val1 = u.u_rgid;
63 	u.u_r.r_val2 = u.u_gid;
64 }
65 
66 getgroups()
67 {
68 	register struct	a {
69 		u_int	gidsetsize;
70 		int	*gidset;
71 	} *uap = (struct a *)u.u_ap;
72 	register gid_t *gp;
73 	register int *lp;
74 	int groups[NGROUPS];
75 
76 	for (gp = &u.u_groups[NGROUPS]; gp > u.u_groups; gp--)
77 		if (gp[-1] != NOGROUP)
78 			break;
79 	if (uap->gidsetsize < gp - u.u_groups) {
80 		u.u_error = EINVAL;
81 		return;
82 	}
83 	uap->gidsetsize = gp - u.u_groups;
84 	for (lp = groups, gp = u.u_groups; lp < &groups[uap->gidsetsize]; )
85 		*lp++ = *gp++;
86 	u.u_error = copyout((caddr_t)groups, (caddr_t)uap->gidset,
87 	    uap->gidsetsize * sizeof (groups[0]));
88 	if (u.u_error)
89 		return;
90 	u.u_r.r_val1 = uap->gidsetsize;
91 }
92 
93 setsid()
94 {
95 	register struct proc *p = u.u_procp;
96 
97 	if ((p->p_pgid == p->p_pid) || pgfind(p->p_pid))
98 		u.u_error = EPERM;
99 	else {
100 		pgmv(p, p->p_pid, 1);
101 		u.u_r.r_val1 = p->p_pid;
102 	}
103 	return;
104 }
105 
106 /*
107  * set process group
108  *
109  * if target pid != caller's pid
110  *	pid must be an inferior
111  *	pid must be in same session
112  *	pid can't have done an exec
113  *	there must exist a pid with pgid in same session
114  * pid must not be session leader
115  */
116 setpgrp()
117 {
118 	register struct a {
119 		int	pid;
120 		int	pgid;
121 	} *uap = (struct a *)u.u_ap;
122 	register struct proc *p;
123 	register struct pgrp *pgrp;
124 
125 	if (uap->pid == 0)
126 		p = u.u_procp;
127 	else if ((p = pfind(uap->pid)) == 0 || !inferior(p)) {
128 		u.u_error = ESRCH;
129 		return;
130 	}
131 	else if (p != u.u_procp) {
132 		if (p->p_session != u.u_procp->p_session) {
133 			u.u_error = EPERM;
134 			return;
135 		}
136 		if (p->p_flag&SEXEC) {
137 			u.u_error = EACCES;
138 			return;
139 		}
140 	}
141 	if (SESS_LEADER(p)) {
142 		u.u_error = EPERM;
143 		return;
144 	}
145 	if (uap->pgid == 0)
146 		uap->pgid = p->p_pid;
147 	else if ((uap->pgid != p->p_pid) &&
148 		(((pgrp = pgfind(uap->pgid)) == 0) ||
149 		   pgrp->pg_mem == NULL ||
150 	           pgrp->pg_session != u.u_procp->p_session)) {
151 		u.u_error = EPERM;
152 		return;
153 	}
154 	/*
155 	 * done checking, now doit
156 	 */
157 	pgmv(p, uap->pgid, 0);
158 }
159 
160 setreuid()
161 {
162 	struct a {
163 		int	ruid;
164 		int	euid;
165 	} *uap;
166 	register int ruid, euid;
167 
168 	uap = (struct a *)u.u_ap;
169 	ruid = uap->ruid;
170 	if (ruid == -1)
171 		ruid = u.u_ruid;
172 	if (u.u_ruid != ruid && u.u_uid != ruid &&
173 	    (u.u_error = suser(u.u_cred, &u.u_acflag)))
174 		return;
175 	euid = uap->euid;
176 	if (euid == -1)
177 		euid = u.u_uid;
178 	if (u.u_ruid != euid && u.u_uid != euid &&
179 	    (u.u_error = suser(u.u_cred, &u.u_acflag)))
180 		return;
181 	/*
182 	 * Everything's okay, do it.
183 	 */
184 #ifdef QUOTA
185 	if (u.u_quota->q_uid != ruid) {
186 		qclean();
187 		qstart(getquota((uid_t)ruid, 0, 0));
188 	}
189 #endif
190 	u.u_procp->p_uid = euid;
191 	u.u_ruid = ruid;
192 	u.u_uid = euid;
193 }
194 
195 setregid()
196 {
197 	register struct a {
198 		int	rgid;
199 		int	egid;
200 	} *uap;
201 	register int rgid, egid;
202 
203 	uap = (struct a *)u.u_ap;
204 	rgid = uap->rgid;
205 	if (rgid == -1)
206 		rgid = u.u_rgid;
207 	if (u.u_rgid != rgid && u.u_gid != rgid &&
208 	    (u.u_error = suser(u.u_cred, &u.u_acflag)))
209 		return;
210 	egid = uap->egid;
211 	if (egid == -1)
212 		egid = u.u_gid;
213 	if (u.u_rgid != egid && u.u_gid != egid &&
214 	    (u.u_error = suser(u.u_cred, &u.u_acflag)))
215 		return;
216 	if (u.u_rgid != rgid) {
217 		leavegroup(u.u_rgid);
218 		(void) entergroup((gid_t)rgid);
219 		u.u_rgid = rgid;
220 	}
221 	u.u_gid = egid;
222 }
223 
224 setgroups()
225 {
226 	register struct	a {
227 		u_int	gidsetsize;
228 		int	*gidset;
229 	} *uap = (struct a *)u.u_ap;
230 	register gid_t *gp;
231 	register int *lp;
232 	int groups[NGROUPS];
233 
234 	if (u.u_error = suser(u.u_cred, &u.u_acflag))
235 		return;
236 	if (uap->gidsetsize > sizeof (u.u_groups) / sizeof (u.u_groups[0])) {
237 		u.u_error = EINVAL;
238 		return;
239 	}
240 	u.u_error = copyin((caddr_t)uap->gidset, (caddr_t)groups,
241 	    uap->gidsetsize * sizeof (groups[0]));
242 	if (u.u_error)
243 		return;
244 	for (lp = groups, gp = u.u_groups; lp < &groups[uap->gidsetsize]; )
245 		*gp++ = *lp++;
246 	for ( ; gp < &u.u_groups[NGROUPS]; gp++)
247 		*gp = NOGROUP;
248 }
249 
250 /*
251  * Group utility functions.
252  */
253 
254 /*
255  * Delete gid from the group set.
256  */
257 leavegroup(gid)
258 	gid_t gid;
259 {
260 	register gid_t *gp;
261 
262 	for (gp = u.u_groups; gp < &u.u_groups[NGROUPS]; gp++)
263 		if (*gp == gid)
264 			goto found;
265 	return;
266 found:
267 	for (; gp < &u.u_groups[NGROUPS-1]; gp++)
268 		*gp = *(gp+1);
269 	*gp = NOGROUP;
270 }
271 
272 /*
273  * Add gid to the group set.
274  */
275 entergroup(gid)
276 	gid_t gid;
277 {
278 	register gid_t *gp;
279 
280 	for (gp = u.u_groups; gp < &u.u_groups[NGROUPS]; gp++) {
281 		if (*gp == gid)
282 			return (0);
283 		if (*gp == NOGROUP) {
284 			*gp = gid;
285 			return (0);
286 		}
287 	}
288 	return (-1);
289 }
290 
291 /*
292  * Check if gid is a member of the group set.
293  */
294 groupmember(gid)
295 	gid_t gid;
296 {
297 	register gid_t *gp;
298 
299 	if (u.u_gid == gid)
300 		return (1);
301 	for (gp = u.u_groups; gp < &u.u_groups[NGROUPS] && *gp != NOGROUP; gp++)
302 		if (*gp == gid)
303 			return (1);
304 	return (0);
305 }
306 
307 /*
308  * Get login name of process owner, if available
309  */
310 
311 getlogname()
312 {
313 	struct a {
314 		char	*namebuf;
315 		u_int	namelen;
316 	} *uap = (struct a *)u.u_ap;
317 
318 	if (uap->namelen > sizeof (u.u_logname))
319 		uap->namelen = sizeof (u.u_logname);
320 	u.u_error = copyout((caddr_t)u.u_logname, (caddr_t)uap->namebuf,
321 		uap->namelen);
322 }
323 
324 /*
325  * Set login name of process owner
326  */
327 
328 setlogname()
329 {
330 	struct a {
331 		char	*namebuf;
332 		u_int	namelen;
333 	} *uap = (struct a *)u.u_ap;
334 
335 	if (u.u_error = suser(u.u_cred, &u.u_acflag))
336 		return;
337 	if (uap->namelen > sizeof (u.u_logname) - 1)
338 		u.u_error = EINVAL;
339 	else
340 		u.u_error = copyin((caddr_t)uap->namebuf,
341 			(caddr_t)u.u_logname, uap->namelen);
342 }
343