xref: /csrg-svn/sys/kern/kern_prot.c (revision 37085)
123372Smckusick /*
229092Smckusick  * Copyright (c) 1982, 1986 Regents of the University of California.
323372Smckusick  * All rights reserved.  The Berkeley software License Agreement
423372Smckusick  * specifies the terms and conditions for redistribution.
523372Smckusick  *
6*37085Skfall  *	@(#)kern_prot.c	7.3 (Berkeley) 03/07/89
723372Smckusick  */
87420Sroot 
97420Sroot /*
107498Sroot  * System calls related to processes and protection
117420Sroot  */
127420Sroot 
139754Ssam #include "../machine/reg.h"
149754Ssam 
1517092Sbloom #include "param.h"
1617092Sbloom #include "systm.h"
1717092Sbloom #include "dir.h"
1817092Sbloom #include "user.h"
1917092Sbloom #include "inode.h"
2017092Sbloom #include "proc.h"
2117092Sbloom #include "timeb.h"
2217092Sbloom #include "times.h"
2317092Sbloom #include "reboot.h"
2417092Sbloom #include "fs.h"
2517092Sbloom #include "buf.h"
2617092Sbloom #include "mount.h"
2717092Sbloom #include "quota.h"
287420Sroot 
297498Sroot getpid()
307498Sroot {
317498Sroot 
327498Sroot 	u.u_r.r_val1 = u.u_procp->p_pid;
337498Sroot 	u.u_r.r_val2 = u.u_procp->p_ppid;
347498Sroot }
357498Sroot 
367498Sroot getpgrp()
377498Sroot {
387498Sroot 	register struct a {
397498Sroot 		int	pid;
407498Sroot 	} *uap = (struct a *)u.u_ap;
417498Sroot 	register struct proc *p;
427498Sroot 
437498Sroot 	if (uap->pid == 0)
4435810Smarc 		p = u.u_procp;
4535810Smarc 	else if ((p = pfind(uap->pid)) == 0) {
467498Sroot 		u.u_error = ESRCH;
477498Sroot 		return;
487498Sroot 	}
4935810Smarc 	u.u_r.r_val1 = p->p_pgrp->pg_id;
507498Sroot }
517498Sroot 
527420Sroot getuid()
537420Sroot {
547420Sroot 
557420Sroot 	u.u_r.r_val1 = u.u_ruid;
567420Sroot 	u.u_r.r_val2 = u.u_uid;
577420Sroot }
587420Sroot 
597498Sroot getgid()
607498Sroot {
617498Sroot 
627498Sroot 	u.u_r.r_val1 = u.u_rgid;
637498Sroot 	u.u_r.r_val2 = u.u_gid;
647498Sroot }
657498Sroot 
667866Sroot getgroups()
677498Sroot {
687498Sroot 	register struct	a {
698624Sroot 		u_int	gidsetsize;
707498Sroot 		int	*gidset;
717498Sroot 	} *uap = (struct a *)u.u_ap;
7218362Skarels 	register gid_t *gp;
7318362Skarels 	register int *lp;
7418362Skarels 	int groups[NGROUPS];
757498Sroot 
767866Sroot 	for (gp = &u.u_groups[NGROUPS]; gp > u.u_groups; gp--)
7718362Skarels 		if (gp[-1] != NOGROUP)
787866Sroot 			break;
797866Sroot 	if (uap->gidsetsize < gp - u.u_groups) {
807866Sroot 		u.u_error = EINVAL;
817866Sroot 		return;
827866Sroot 	}
837866Sroot 	uap->gidsetsize = gp - u.u_groups;
8418362Skarels 	for (lp = groups, gp = u.u_groups; lp < &groups[uap->gidsetsize]; )
8518362Skarels 		*lp++ = *gp++;
8618362Skarels 	u.u_error = copyout((caddr_t)groups, (caddr_t)uap->gidset,
8718362Skarels 	    uap->gidsetsize * sizeof (groups[0]));
889997Ssam 	if (u.u_error)
897498Sroot 		return;
907866Sroot 	u.u_r.r_val1 = uap->gidsetsize;
917498Sroot }
927498Sroot 
9335810Smarc setsid()
9435810Smarc {
9535810Smarc 	register struct proc *p = u.u_procp;
9635810Smarc 
9735810Smarc 	if ((p->p_pgid == p->p_pid) || pgfind(p->p_pid))
9835810Smarc 		u.u_error = EPERM;
9935810Smarc 	else {
10035810Smarc 		pgmv(p, p->p_pid, 1);
10135810Smarc 		u.u_r.r_val1 = p->p_pid;
10235810Smarc 	}
10335810Smarc 	return;
10435810Smarc }
10535810Smarc 
10635810Smarc /*
10735810Smarc  * set process group
10835810Smarc  *
10935810Smarc  * if target pid != caller's pid
11035810Smarc  *	pid must be an inferior
11135810Smarc  *	pid must be in same session
11235810Smarc  *	pid can't have done an exec
11335810Smarc  *	there must exist a pid with pgid in same session
11435810Smarc  * pid must not be session leader
11535810Smarc  */
1167498Sroot setpgrp()
1177498Sroot {
1187498Sroot 	register struct a {
1197498Sroot 		int	pid;
12035810Smarc 		int	pgid;
1217498Sroot 	} *uap = (struct a *)u.u_ap;
12235810Smarc 	register struct proc *p;
12335810Smarc 	register struct pgrp *pgrp;
1247498Sroot 
1257498Sroot 	if (uap->pid == 0)
12635810Smarc 		p = u.u_procp;
12735810Smarc 	else if ((p = pfind(uap->pid)) == 0 || !inferior(p)) {
1287498Sroot 		u.u_error = ESRCH;
1297498Sroot 		return;
1307498Sroot 	}
13135810Smarc 	else if (p != u.u_procp) {
13235810Smarc 		if (p->p_session != u.u_procp->p_session) {
13335810Smarc 			u.u_error = EPERM;
13435810Smarc 			return;
13535810Smarc 		}
13635810Smarc 		if (p->p_flag&SEXEC) {
13735810Smarc 			u.u_error = EACCES;
13835810Smarc 			return;
13935810Smarc 		}
14035810Smarc 	}
14135810Smarc 	if (SESS_LEADER(p)) {
1427498Sroot 		u.u_error = EPERM;
1437498Sroot 		return;
1447498Sroot 	}
14535810Smarc 	if (uap->pgid == 0)
14635810Smarc 		uap->pgid = p->p_pid;
14735810Smarc 	else if ((uap->pgid != p->p_pid) &&
14835810Smarc 		(((pgrp = pgfind(uap->pgid)) == 0) ||
14935810Smarc 		   pgrp->pg_mem == NULL ||
15035810Smarc 	           pgrp->pg_session != u.u_procp->p_session)) {
15135810Smarc 		u.u_error = EPERM;
15235810Smarc 		return;
15335810Smarc 	}
15435810Smarc 	/*
15535810Smarc 	 * done checking, now doit
15635810Smarc 	 */
15735810Smarc 	pgmv(p, uap->pgid, 0);
1587498Sroot }
1597498Sroot 
1609160Ssam setreuid()
1617420Sroot {
1629160Ssam 	struct a {
1639160Ssam 		int	ruid;
1649160Ssam 		int	euid;
1659160Ssam 	} *uap;
1669160Ssam 	register int ruid, euid;
1679160Ssam 
1689160Ssam 	uap = (struct a *)u.u_ap;
1699160Ssam 	ruid = uap->ruid;
1709160Ssam 	if (ruid == -1)
1719160Ssam 		ruid = u.u_ruid;
1729160Ssam 	if (u.u_ruid != ruid && u.u_uid != ruid && !suser())
1739160Ssam 		return;
1749160Ssam 	euid = uap->euid;
1759160Ssam 	if (euid == -1)
1769160Ssam 		euid = u.u_uid;
1779160Ssam 	if (u.u_ruid != euid && u.u_uid != euid && !suser())
1789160Ssam 		return;
1799160Ssam 	/*
1809160Ssam 	 * Everything's okay, do it.
1819160Ssam 	 */
1829160Ssam #ifdef QUOTA
1839320Ssam 	if (u.u_quota->q_uid != ruid) {
1849320Ssam 		qclean();
18526354Skarels 		qstart(getquota((uid_t)ruid, 0, 0));
1869320Ssam 	}
1879160Ssam #endif
18825627Skarels 	u.u_procp->p_uid = euid;
1899320Ssam 	u.u_ruid = ruid;
1909160Ssam 	u.u_uid = euid;
1919160Ssam }
1929160Ssam 
1939160Ssam setregid()
1947420Sroot {
1959160Ssam 	register struct a {
1969160Ssam 		int	rgid;
1979160Ssam 		int	egid;
1989160Ssam 	} *uap;
1999160Ssam 	register int rgid, egid;
2009160Ssam 
2019160Ssam 	uap = (struct a *)u.u_ap;
2029160Ssam 	rgid = uap->rgid;
2039160Ssam 	if (rgid == -1)
2049160Ssam 		rgid = u.u_rgid;
2059160Ssam 	if (u.u_rgid != rgid && u.u_gid != rgid && !suser())
2069160Ssam 		return;
2079160Ssam 	egid = uap->egid;
2089160Ssam 	if (egid == -1)
2099160Ssam 		egid = u.u_gid;
2109160Ssam 	if (u.u_rgid != egid && u.u_gid != egid && !suser())
2119160Ssam 		return;
2129160Ssam 	if (u.u_rgid != rgid) {
2139160Ssam 		leavegroup(u.u_rgid);
21426275Skarels 		(void) entergroup((gid_t)rgid);
2159160Ssam 		u.u_rgid = rgid;
2169160Ssam 	}
21711164Ssam 	u.u_gid = egid;
2189160Ssam }
2199160Ssam 
2207866Sroot setgroups()
2217498Sroot {
2227498Sroot 	register struct	a {
2238624Sroot 		u_int	gidsetsize;
2247498Sroot 		int	*gidset;
2257498Sroot 	} *uap = (struct a *)u.u_ap;
22618362Skarels 	register gid_t *gp;
22718362Skarels 	register int *lp;
22818362Skarels 	int groups[NGROUPS];
2297498Sroot 
2308100Sroot 	if (!suser())
2317498Sroot 		return;
2327866Sroot 	if (uap->gidsetsize > sizeof (u.u_groups) / sizeof (u.u_groups[0])) {
2337866Sroot 		u.u_error = EINVAL;
2347498Sroot 		return;
2357498Sroot 	}
23618362Skarels 	u.u_error = copyin((caddr_t)uap->gidset, (caddr_t)groups,
23718362Skarels 	    uap->gidsetsize * sizeof (groups[0]));
2389997Ssam 	if (u.u_error)
2397498Sroot 		return;
24018362Skarels 	for (lp = groups, gp = u.u_groups; lp < &groups[uap->gidsetsize]; )
24118362Skarels 		*gp++ = *lp++;
24218362Skarels 	for ( ; gp < &u.u_groups[NGROUPS]; gp++)
24311810Ssam 		*gp = NOGROUP;
2447498Sroot }
2457498Sroot 
2467498Sroot /*
24711810Ssam  * Group utility functions.
24811810Ssam  */
24911810Ssam 
25011810Ssam /*
25111810Ssam  * Delete gid from the group set.
25211810Ssam  */
2537866Sroot leavegroup(gid)
25426275Skarels 	gid_t gid;
2557866Sroot {
25618362Skarels 	register gid_t *gp;
2577866Sroot 
2587866Sroot 	for (gp = u.u_groups; gp < &u.u_groups[NGROUPS]; gp++)
2597866Sroot 		if (*gp == gid)
2607866Sroot 			goto found;
2617866Sroot 	return;
2627866Sroot found:
2637866Sroot 	for (; gp < &u.u_groups[NGROUPS-1]; gp++)
2647866Sroot 		*gp = *(gp+1);
26511810Ssam 	*gp = NOGROUP;
2667866Sroot }
2677866Sroot 
26811810Ssam /*
26911810Ssam  * Add gid to the group set.
27011810Ssam  */
2717866Sroot entergroup(gid)
27226275Skarels 	gid_t gid;
2737866Sroot {
27418362Skarels 	register gid_t *gp;
2757866Sroot 
27618362Skarels 	for (gp = u.u_groups; gp < &u.u_groups[NGROUPS]; gp++) {
2777866Sroot 		if (*gp == gid)
2787866Sroot 			return (0);
27918362Skarels 		if (*gp == NOGROUP) {
2807866Sroot 			*gp = gid;
2817866Sroot 			return (0);
2827866Sroot 		}
28318362Skarels 	}
2847866Sroot 	return (-1);
2857866Sroot }
28611810Ssam 
28711810Ssam /*
28811810Ssam  * Check if gid is a member of the group set.
28911810Ssam  */
29011810Ssam groupmember(gid)
29118362Skarels 	gid_t gid;
29211810Ssam {
29318362Skarels 	register gid_t *gp;
29411810Ssam 
29511810Ssam 	if (u.u_gid == gid)
29611810Ssam 		return (1);
29711810Ssam 	for (gp = u.u_groups; gp < &u.u_groups[NGROUPS] && *gp != NOGROUP; gp++)
29811810Ssam 		if (*gp == gid)
29911810Ssam 			return (1);
30011810Ssam 	return (0);
30111810Ssam }
302*37085Skfall 
303*37085Skfall /*
304*37085Skfall  * Get login name of process owner, if available
305*37085Skfall  */
306*37085Skfall 
307*37085Skfall getlogname()
308*37085Skfall {
309*37085Skfall 	struct a {
310*37085Skfall 		char	*namebuf;
311*37085Skfall 		u_int	namelen;
312*37085Skfall 	} *uap = (struct a *)u.u_ap;
313*37085Skfall 
314*37085Skfall 	if (uap->namelen > sizeof (u.u_logname))
315*37085Skfall 		uap->namelen = sizeof (u.u_logname);
316*37085Skfall 	u.u_error = copyout((caddr_t)u.u_logname, (caddr_t)uap->namebuf,
317*37085Skfall 		uap->namelen);
318*37085Skfall }
319*37085Skfall 
320*37085Skfall /*
321*37085Skfall  * Set login name of process owner
322*37085Skfall  */
323*37085Skfall 
324*37085Skfall setlogname()
325*37085Skfall {
326*37085Skfall 	struct a {
327*37085Skfall 		char	*namebuf;
328*37085Skfall 		u_int	namelen;
329*37085Skfall 	} *uap = (struct a *)u.u_ap;
330*37085Skfall 
331*37085Skfall 	if(suser()) {
332*37085Skfall 		if(uap->namelen > sizeof (u.u_logname) - 1)
333*37085Skfall 			u.u_error = EINVAL;
334*37085Skfall 		else
335*37085Skfall 			u.u_error = copyin((caddr_t)uap->namebuf,
336*37085Skfall 				(caddr_t)u.u_logname, uap->namelen);
337*37085Skfall 	}
338*37085Skfall }
339