xref: /csrg-svn/sys/kern/kern_prot.c (revision 37578)
123372Smckusick /*
2*37578Smckusick  * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
3*37578Smckusick  * All rights reserved.
423372Smckusick  *
5*37578Smckusick  * Redistribution and use in source and binary forms are permitted
6*37578Smckusick  * provided that the above copyright notice and this paragraph are
7*37578Smckusick  * duplicated in all such forms and that any documentation,
8*37578Smckusick  * advertising materials, and other materials related to such
9*37578Smckusick  * distribution and use acknowledge that the software was developed
10*37578Smckusick  * by the University of California, Berkeley.  The name of the
11*37578Smckusick  * University may not be used to endorse or promote products derived
12*37578Smckusick  * from this software without specific prior written permission.
13*37578Smckusick  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14*37578Smckusick  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15*37578Smckusick  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16*37578Smckusick  *
17*37578Smckusick  *	@(#)kern_prot.c	7.1.1.1 (Berkeley) 05/01/89
1823372Smckusick  */
197420Sroot 
207420Sroot /*
217498Sroot  * System calls related to processes and protection
227420Sroot  */
237420Sroot 
24*37578Smckusick #include "machine/reg.h"
25*37578Smckusick 
2617092Sbloom #include "param.h"
27*37578Smckusick #include "acct.h"
2817092Sbloom #include "systm.h"
2917092Sbloom #include "user.h"
3017092Sbloom #include "proc.h"
3117092Sbloom #include "timeb.h"
3217092Sbloom #include "times.h"
3317092Sbloom #include "reboot.h"
34*37578Smckusick #include "mount.h"
3517092Sbloom #include "buf.h"
36*37578Smckusick #include "../ufs/quota.h"
37*37578Smckusick #include "malloc.h"
38*37578Smckusick #define GRPSTART 0
397420Sroot 
407498Sroot getpid()
417498Sroot {
427498Sroot 
437498Sroot 	u.u_r.r_val1 = u.u_procp->p_pid;
447498Sroot 	u.u_r.r_val2 = u.u_procp->p_ppid;
457498Sroot }
467498Sroot 
477498Sroot getpgrp()
487498Sroot {
497498Sroot 	register struct a {
507498Sroot 		int	pid;
517498Sroot 	} *uap = (struct a *)u.u_ap;
527498Sroot 	register struct proc *p;
537498Sroot 
547498Sroot 	if (uap->pid == 0)
55*37578Smckusick 		uap->pid = u.u_procp->p_pid;
56*37578Smckusick 	p = pfind(uap->pid);
57*37578Smckusick 	if (p == 0) {
587498Sroot 		u.u_error = ESRCH;
597498Sroot 		return;
607498Sroot 	}
61*37578Smckusick 	u.u_r.r_val1 = p->p_pgrp;
627498Sroot }
637498Sroot 
647420Sroot getuid()
657420Sroot {
667420Sroot 
677420Sroot 	u.u_r.r_val1 = u.u_ruid;
687420Sroot 	u.u_r.r_val2 = u.u_uid;
697420Sroot }
707420Sroot 
717498Sroot getgid()
727498Sroot {
737498Sroot 
747498Sroot 	u.u_r.r_val1 = u.u_rgid;
757498Sroot 	u.u_r.r_val2 = u.u_gid;
767498Sroot }
777498Sroot 
787866Sroot getgroups()
797498Sroot {
807498Sroot 	register struct	a {
818624Sroot 		u_int	gidsetsize;
827498Sroot 		int	*gidset;
837498Sroot 	} *uap = (struct a *)u.u_ap;
8418362Skarels 	register gid_t *gp;
8518362Skarels 	register int *lp;
8618362Skarels 	int groups[NGROUPS];
877498Sroot 
88*37578Smckusick 	if (uap->gidsetsize == 0) {
89*37578Smckusick 		u.u_r.r_val1 = u.u_ngroups - GRPSTART;
90*37578Smckusick 		return;
91*37578Smckusick 	}
92*37578Smckusick 	if (uap->gidsetsize < u.u_ngroups - GRPSTART) {
937866Sroot 		u.u_error = EINVAL;
947866Sroot 		return;
957866Sroot 	}
96*37578Smckusick 	uap->gidsetsize = u.u_ngroups - GRPSTART;
97*37578Smckusick 	gp = &u.u_groups[GRPSTART];
98*37578Smckusick 	for (lp = groups; lp < &groups[uap->gidsetsize]; )
9918362Skarels 		*lp++ = *gp++;
10018362Skarels 	u.u_error = copyout((caddr_t)groups, (caddr_t)uap->gidset,
10118362Skarels 	    uap->gidsetsize * sizeof (groups[0]));
1029997Ssam 	if (u.u_error)
1037498Sroot 		return;
1047866Sroot 	u.u_r.r_val1 = uap->gidsetsize;
1057498Sroot }
1067498Sroot 
1077498Sroot setpgrp()
1087498Sroot {
109*37578Smckusick 	register struct proc *p;
1107498Sroot 	register struct a {
1117498Sroot 		int	pid;
112*37578Smckusick 		int	pgrp;
1137498Sroot 	} *uap = (struct a *)u.u_ap;
1147498Sroot 
1157498Sroot 	if (uap->pid == 0)
116*37578Smckusick 		uap->pid = u.u_procp->p_pid;
117*37578Smckusick 	p = pfind(uap->pid);
118*37578Smckusick 	if (p == 0) {
1197498Sroot 		u.u_error = ESRCH;
1207498Sroot 		return;
1217498Sroot 	}
122*37578Smckusick /* need better control mechanisms for process groups */
123*37578Smckusick 	if (p->p_uid != u.u_uid && u.u_uid && !inferior(p)) {
1247498Sroot 		u.u_error = EPERM;
1257498Sroot 		return;
1267498Sroot 	}
127*37578Smckusick 	p->p_pgrp = uap->pgrp;
1287498Sroot }
1297498Sroot 
1309160Ssam setreuid()
1317420Sroot {
1329160Ssam 	struct a {
1339160Ssam 		int	ruid;
1349160Ssam 		int	euid;
1359160Ssam 	} *uap;
1369160Ssam 	register int ruid, euid;
1379160Ssam 
1389160Ssam 	uap = (struct a *)u.u_ap;
1399160Ssam 	ruid = uap->ruid;
1409160Ssam 	if (ruid == -1)
1419160Ssam 		ruid = u.u_ruid;
14237553Smckusick 	if (u.u_ruid != ruid && u.u_uid != ruid &&
14337553Smckusick 	    (u.u_error = suser(u.u_cred, &u.u_acflag)))
1449160Ssam 		return;
1459160Ssam 	euid = uap->euid;
1469160Ssam 	if (euid == -1)
1479160Ssam 		euid = u.u_uid;
14837553Smckusick 	if (u.u_ruid != euid && u.u_uid != euid &&
14937553Smckusick 	    (u.u_error = suser(u.u_cred, &u.u_acflag)))
1509160Ssam 		return;
1519160Ssam 	/*
1529160Ssam 	 * Everything's okay, do it.
153*37578Smckusick 	 * Copy credentials so other references do not
154*37578Smckusick 	 * see our changes.
1559160Ssam 	 */
1569160Ssam #ifdef QUOTA
1579320Ssam 	if (u.u_quota->q_uid != ruid) {
1589320Ssam 		qclean();
15926354Skarels 		qstart(getquota((uid_t)ruid, 0, 0));
1609320Ssam 	}
1619160Ssam #endif
162*37578Smckusick 	if (u.u_cred->cr_ref > 1)
163*37578Smckusick 		u.u_cred = crcopy(u.u_cred);
16425627Skarels 	u.u_procp->p_uid = euid;
1659320Ssam 	u.u_ruid = ruid;
1669160Ssam 	u.u_uid = euid;
1679160Ssam }
1689160Ssam 
1699160Ssam setregid()
1707420Sroot {
1719160Ssam 	register struct a {
1729160Ssam 		int	rgid;
1739160Ssam 		int	egid;
1749160Ssam 	} *uap;
1759160Ssam 	register int rgid, egid;
1769160Ssam 
1779160Ssam 	uap = (struct a *)u.u_ap;
1789160Ssam 	rgid = uap->rgid;
1799160Ssam 	if (rgid == -1)
1809160Ssam 		rgid = u.u_rgid;
18137553Smckusick 	if (u.u_rgid != rgid && u.u_gid != rgid &&
18237553Smckusick 	    (u.u_error = suser(u.u_cred, &u.u_acflag)))
1839160Ssam 		return;
1849160Ssam 	egid = uap->egid;
1859160Ssam 	if (egid == -1)
1869160Ssam 		egid = u.u_gid;
18737553Smckusick 	if (u.u_rgid != egid && u.u_gid != egid &&
18837553Smckusick 	    (u.u_error = suser(u.u_cred, &u.u_acflag)))
1899160Ssam 		return;
190*37578Smckusick 	if (u.u_cred->cr_ref > 1)
191*37578Smckusick 		u.u_cred = crcopy(u.u_cred);
192*37578Smckusick 	u.u_rgid = rgid;
19311164Ssam 	u.u_gid = egid;
1949160Ssam }
1959160Ssam 
1967866Sroot setgroups()
1977498Sroot {
1987498Sroot 	register struct	a {
1998624Sroot 		u_int	gidsetsize;
2007498Sroot 		int	*gidset;
2017498Sroot 	} *uap = (struct a *)u.u_ap;
20218362Skarels 	register gid_t *gp;
20318362Skarels 	register int *lp;
204*37578Smckusick 	int ngrp, groups[NGROUPS];
2057498Sroot 
20637553Smckusick 	if (u.u_error = suser(u.u_cred, &u.u_acflag))
2077498Sroot 		return;
208*37578Smckusick 	ngrp = uap->gidsetsize + GRPSTART;
209*37578Smckusick 	if (ngrp > sizeof (u.u_groups) / sizeof (u.u_groups[0])) {
2107866Sroot 		u.u_error = EINVAL;
2117498Sroot 		return;
2127498Sroot 	}
21318362Skarels 	u.u_error = copyin((caddr_t)uap->gidset, (caddr_t)groups,
21418362Skarels 	    uap->gidsetsize * sizeof (groups[0]));
2159997Ssam 	if (u.u_error)
2167498Sroot 		return;
217*37578Smckusick 	gp = &u.u_groups[GRPSTART];
218*37578Smckusick 	for (lp = groups; lp < &groups[uap->gidsetsize]; )
21918362Skarels 		*gp++ = *lp++;
220*37578Smckusick 	u.u_ngroups = ngrp;
2217498Sroot }
2227498Sroot 
2237498Sroot /*
224*37578Smckusick  * Check if gid is a member of the group set.
22511810Ssam  */
226*37578Smckusick groupmember(gid, cred)
22726275Skarels 	gid_t gid;
228*37578Smckusick 	register struct ucred *cred;
2297866Sroot {
23018362Skarels 	register gid_t *gp;
231*37578Smckusick 	gid_t *egp;
2327866Sroot 
233*37578Smckusick 	egp = &(cred->cr_groups[cred->cr_ngroups]);
234*37578Smckusick 	for (gp = cred->cr_groups; gp < egp; gp++)
2357866Sroot 		if (*gp == gid)
236*37578Smckusick 			return (1);
237*37578Smckusick 	return (0);
2387866Sroot }
2397866Sroot 
24011810Ssam /*
241*37578Smckusick  * Test if the current user is the super user.
24211810Ssam  */
243*37578Smckusick suser(cred, acflag)
244*37578Smckusick 	struct ucred *cred;
245*37578Smckusick 	short *acflag;
2467866Sroot {
2477866Sroot 
248*37578Smckusick 	if (cred->cr_uid == 0) {
249*37578Smckusick 		if (acflag)
250*37578Smckusick 			*acflag |= ASU;
251*37578Smckusick 		return (0);
25218362Skarels 	}
253*37578Smckusick 	return (EPERM);
2547866Sroot }
25511810Ssam 
25611810Ssam /*
257*37578Smckusick  * Allocate a zeroed cred structure.
25811810Ssam  */
259*37578Smckusick struct ucred *
260*37578Smckusick crget()
26111810Ssam {
262*37578Smckusick 	register struct ucred *cr;
26311810Ssam 
264*37578Smckusick 	MALLOC(cr, struct ucred *, sizeof(*cr), M_CRED, M_WAITOK);
265*37578Smckusick 	bzero((caddr_t)cr, sizeof(*cr));
266*37578Smckusick 	cr->cr_ref = 1;
267*37578Smckusick 	return(cr);
26811810Ssam }
26937085Skfall 
27037085Skfall /*
271*37578Smckusick  * Free a cred structure.
272*37578Smckusick  * Throws away space when ref count gets to 0.
27337085Skfall  */
274*37578Smckusick crfree(cr)
275*37578Smckusick 	struct ucred *cr;
276*37578Smckusick {
277*37578Smckusick 	int	s = splimp();
27837085Skfall 
279*37578Smckusick 	if (--cr->cr_ref != 0) {
280*37578Smckusick 		(void) splx(s);
281*37578Smckusick 		return;
282*37578Smckusick 	}
283*37578Smckusick 	FREE((caddr_t)cr, M_CRED);
284*37578Smckusick 	(void) splx(s);
285*37578Smckusick }
286*37578Smckusick 
287*37578Smckusick /*
288*37578Smckusick  * Copy cred structure to a new one and free the old one.
289*37578Smckusick  */
290*37578Smckusick struct ucred *
291*37578Smckusick crcopy(cr)
292*37578Smckusick 	struct ucred *cr;
29337085Skfall {
294*37578Smckusick 	struct ucred *newcr;
29537085Skfall 
296*37578Smckusick 	newcr = crget();
297*37578Smckusick 	*newcr = *cr;
298*37578Smckusick 	crfree(cr);
299*37578Smckusick 	newcr->cr_ref = 1;
300*37578Smckusick 	return(newcr);
30137085Skfall }
30237085Skfall 
30337085Skfall /*
304*37578Smckusick  * Dup cred struct to a new held one.
30537085Skfall  */
306*37578Smckusick struct ucred *
307*37578Smckusick crdup(cr)
308*37578Smckusick 	struct ucred *cr;
30937085Skfall {
310*37578Smckusick 	struct ucred *newcr;
31137085Skfall 
312*37578Smckusick 	newcr = crget();
313*37578Smckusick 	*newcr = *cr;
314*37578Smckusick 	newcr->cr_ref = 1;
315*37578Smckusick 	return(newcr);
31637085Skfall }
317