xref: /csrg-svn/sys/kern/kern_prot.c (revision 37578)
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.1.1.1 (Berkeley) 05/01/89
18  */
19 
20 /*
21  * System calls related to processes and protection
22  */
23 
24 #include "machine/reg.h"
25 
26 #include "param.h"
27 #include "acct.h"
28 #include "systm.h"
29 #include "user.h"
30 #include "proc.h"
31 #include "timeb.h"
32 #include "times.h"
33 #include "reboot.h"
34 #include "mount.h"
35 #include "buf.h"
36 #include "../ufs/quota.h"
37 #include "malloc.h"
38 #define GRPSTART 0
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 		uap->pid = u.u_procp->p_pid;
56 	p = pfind(uap->pid);
57 	if (p == 0) {
58 		u.u_error = ESRCH;
59 		return;
60 	}
61 	u.u_r.r_val1 = p->p_pgrp;
62 }
63 
64 getuid()
65 {
66 
67 	u.u_r.r_val1 = u.u_ruid;
68 	u.u_r.r_val2 = u.u_uid;
69 }
70 
71 getgid()
72 {
73 
74 	u.u_r.r_val1 = u.u_rgid;
75 	u.u_r.r_val2 = u.u_gid;
76 }
77 
78 getgroups()
79 {
80 	register struct	a {
81 		u_int	gidsetsize;
82 		int	*gidset;
83 	} *uap = (struct a *)u.u_ap;
84 	register gid_t *gp;
85 	register int *lp;
86 	int groups[NGROUPS];
87 
88 	if (uap->gidsetsize == 0) {
89 		u.u_r.r_val1 = u.u_ngroups - GRPSTART;
90 		return;
91 	}
92 	if (uap->gidsetsize < u.u_ngroups - GRPSTART) {
93 		u.u_error = EINVAL;
94 		return;
95 	}
96 	uap->gidsetsize = u.u_ngroups - GRPSTART;
97 	gp = &u.u_groups[GRPSTART];
98 	for (lp = groups; lp < &groups[uap->gidsetsize]; )
99 		*lp++ = *gp++;
100 	u.u_error = copyout((caddr_t)groups, (caddr_t)uap->gidset,
101 	    uap->gidsetsize * sizeof (groups[0]));
102 	if (u.u_error)
103 		return;
104 	u.u_r.r_val1 = uap->gidsetsize;
105 }
106 
107 setpgrp()
108 {
109 	register struct proc *p;
110 	register struct a {
111 		int	pid;
112 		int	pgrp;
113 	} *uap = (struct a *)u.u_ap;
114 
115 	if (uap->pid == 0)
116 		uap->pid = u.u_procp->p_pid;
117 	p = pfind(uap->pid);
118 	if (p == 0) {
119 		u.u_error = ESRCH;
120 		return;
121 	}
122 /* need better control mechanisms for process groups */
123 	if (p->p_uid != u.u_uid && u.u_uid && !inferior(p)) {
124 		u.u_error = EPERM;
125 		return;
126 	}
127 	p->p_pgrp = uap->pgrp;
128 }
129 
130 setreuid()
131 {
132 	struct a {
133 		int	ruid;
134 		int	euid;
135 	} *uap;
136 	register int ruid, euid;
137 
138 	uap = (struct a *)u.u_ap;
139 	ruid = uap->ruid;
140 	if (ruid == -1)
141 		ruid = u.u_ruid;
142 	if (u.u_ruid != ruid && u.u_uid != ruid &&
143 	    (u.u_error = suser(u.u_cred, &u.u_acflag)))
144 		return;
145 	euid = uap->euid;
146 	if (euid == -1)
147 		euid = u.u_uid;
148 	if (u.u_ruid != euid && u.u_uid != euid &&
149 	    (u.u_error = suser(u.u_cred, &u.u_acflag)))
150 		return;
151 	/*
152 	 * Everything's okay, do it.
153 	 * Copy credentials so other references do not
154 	 * see our changes.
155 	 */
156 #ifdef QUOTA
157 	if (u.u_quota->q_uid != ruid) {
158 		qclean();
159 		qstart(getquota((uid_t)ruid, 0, 0));
160 	}
161 #endif
162 	if (u.u_cred->cr_ref > 1)
163 		u.u_cred = crcopy(u.u_cred);
164 	u.u_procp->p_uid = euid;
165 	u.u_ruid = ruid;
166 	u.u_uid = euid;
167 }
168 
169 setregid()
170 {
171 	register struct a {
172 		int	rgid;
173 		int	egid;
174 	} *uap;
175 	register int rgid, egid;
176 
177 	uap = (struct a *)u.u_ap;
178 	rgid = uap->rgid;
179 	if (rgid == -1)
180 		rgid = u.u_rgid;
181 	if (u.u_rgid != rgid && u.u_gid != rgid &&
182 	    (u.u_error = suser(u.u_cred, &u.u_acflag)))
183 		return;
184 	egid = uap->egid;
185 	if (egid == -1)
186 		egid = u.u_gid;
187 	if (u.u_rgid != egid && u.u_gid != egid &&
188 	    (u.u_error = suser(u.u_cred, &u.u_acflag)))
189 		return;
190 	if (u.u_cred->cr_ref > 1)
191 		u.u_cred = crcopy(u.u_cred);
192 	u.u_rgid = rgid;
193 	u.u_gid = egid;
194 }
195 
196 setgroups()
197 {
198 	register struct	a {
199 		u_int	gidsetsize;
200 		int	*gidset;
201 	} *uap = (struct a *)u.u_ap;
202 	register gid_t *gp;
203 	register int *lp;
204 	int ngrp, groups[NGROUPS];
205 
206 	if (u.u_error = suser(u.u_cred, &u.u_acflag))
207 		return;
208 	ngrp = uap->gidsetsize + GRPSTART;
209 	if (ngrp > sizeof (u.u_groups) / sizeof (u.u_groups[0])) {
210 		u.u_error = EINVAL;
211 		return;
212 	}
213 	u.u_error = copyin((caddr_t)uap->gidset, (caddr_t)groups,
214 	    uap->gidsetsize * sizeof (groups[0]));
215 	if (u.u_error)
216 		return;
217 	gp = &u.u_groups[GRPSTART];
218 	for (lp = groups; lp < &groups[uap->gidsetsize]; )
219 		*gp++ = *lp++;
220 	u.u_ngroups = ngrp;
221 }
222 
223 /*
224  * Check if gid is a member of the group set.
225  */
226 groupmember(gid, cred)
227 	gid_t gid;
228 	register struct ucred *cred;
229 {
230 	register gid_t *gp;
231 	gid_t *egp;
232 
233 	egp = &(cred->cr_groups[cred->cr_ngroups]);
234 	for (gp = cred->cr_groups; gp < egp; gp++)
235 		if (*gp == gid)
236 			return (1);
237 	return (0);
238 }
239 
240 /*
241  * Test if the current user is the super user.
242  */
243 suser(cred, acflag)
244 	struct ucred *cred;
245 	short *acflag;
246 {
247 
248 	if (cred->cr_uid == 0) {
249 		if (acflag)
250 			*acflag |= ASU;
251 		return (0);
252 	}
253 	return (EPERM);
254 }
255 
256 /*
257  * Allocate a zeroed cred structure.
258  */
259 struct ucred *
260 crget()
261 {
262 	register struct ucred *cr;
263 
264 	MALLOC(cr, struct ucred *, sizeof(*cr), M_CRED, M_WAITOK);
265 	bzero((caddr_t)cr, sizeof(*cr));
266 	cr->cr_ref = 1;
267 	return(cr);
268 }
269 
270 /*
271  * Free a cred structure.
272  * Throws away space when ref count gets to 0.
273  */
274 crfree(cr)
275 	struct ucred *cr;
276 {
277 	int	s = splimp();
278 
279 	if (--cr->cr_ref != 0) {
280 		(void) splx(s);
281 		return;
282 	}
283 	FREE((caddr_t)cr, M_CRED);
284 	(void) splx(s);
285 }
286 
287 /*
288  * Copy cred structure to a new one and free the old one.
289  */
290 struct ucred *
291 crcopy(cr)
292 	struct ucred *cr;
293 {
294 	struct ucred *newcr;
295 
296 	newcr = crget();
297 	*newcr = *cr;
298 	crfree(cr);
299 	newcr->cr_ref = 1;
300 	return(newcr);
301 }
302 
303 /*
304  * Dup cred struct to a new held one.
305  */
306 struct ucred *
307 crdup(cr)
308 	struct ucred *cr;
309 {
310 	struct ucred *newcr;
311 
312 	newcr = crget();
313 	*newcr = *cr;
314 	newcr->cr_ref = 1;
315 	return(newcr);
316 }
317