xref: /csrg-svn/sys/kern/kern_resource.c (revision 54345)
149594Sbostic /*-
249594Sbostic  * Copyright (c) 1982, 1986, 1991 The Regents of the University of California.
349594Sbostic  * All rights reserved.
423373Smckusick  *
549594Sbostic  * %sccs.include.redist.c%
649594Sbostic  *
7*54345Smckusick  *	@(#)kern_resource.c	7.18 (Berkeley) 06/23/92
823373Smckusick  */
97Sbill 
1017092Sbloom #include "param.h"
1147541Skarels #include "resourcevar.h"
1247541Skarels #include "malloc.h"
1317092Sbloom #include "proc.h"
147Sbill 
1549282Shibler #include "vm/vm.h"
1649282Shibler 
178176Sroot /*
188176Sroot  * Resource controls and accounting.
198176Sroot  */
208176Sroot 
2143365Smckusick getpriority(curp, uap, retval)
2243365Smckusick 	struct proc *curp;
2343365Smckusick 	register struct args {
248031Sroot 		int	which;
258031Sroot 		int	who;
2643365Smckusick 	} *uap;
2743365Smckusick 	int *retval;
2843365Smckusick {
298031Sroot 	register struct proc *p;
3035810Smarc 	register int low = PRIO_MAX + 1;
318031Sroot 
328031Sroot 	switch (uap->which) {
338031Sroot 
348031Sroot 	case PRIO_PROCESS:
358031Sroot 		if (uap->who == 0)
3643365Smckusick 			p = curp;
378031Sroot 		else
388031Sroot 			p = pfind(uap->who);
398031Sroot 		if (p == 0)
4028149Skarels 			break;
4117400Skarels 		low = p->p_nice;
428031Sroot 		break;
438031Sroot 
4435810Smarc 	case PRIO_PGRP: {
4535810Smarc 		register struct pgrp *pg;
4635810Smarc 
478031Sroot 		if (uap->who == 0)
4843365Smckusick 			pg = curp->p_pgrp;
4935810Smarc 		else if ((pg = pgfind(uap->who)) == NULL)
5035810Smarc 			break;
5135810Smarc 		for (p = pg->pg_mem; p != NULL; p = p->p_pgrpnxt) {
5235810Smarc 			if (p->p_nice < low)
5317400Skarels 				low = p->p_nice;
548176Sroot 		}
558031Sroot 		break;
5635810Smarc 	}
578031Sroot 
588176Sroot 	case PRIO_USER:
598176Sroot 		if (uap->who == 0)
6047541Skarels 			uap->who = curp->p_ucred->cr_uid;
6116530Skarels 		for (p = allproc; p != NULL; p = p->p_nxt) {
6247541Skarels 			if (p->p_ucred->cr_uid == uap->who &&
6317400Skarels 			    p->p_nice < low)
6417400Skarels 				low = p->p_nice;
658176Sroot 		}
668176Sroot 		break;
678176Sroot 
688031Sroot 	default:
6944405Skarels 		return (EINVAL);
708031Sroot 	}
7143365Smckusick 	if (low == PRIO_MAX + 1)
7244405Skarels 		return (ESRCH);
7343365Smckusick 	*retval = low;
7444405Skarels 	return (0);
758031Sroot }
768031Sroot 
7743365Smckusick /* ARGSUSED */
7843365Smckusick setpriority(curp, uap, retval)
7943365Smckusick 	struct proc *curp;
8043365Smckusick 	register struct args {
818031Sroot 		int	which;
828031Sroot 		int	who;
838031Sroot 		int	prio;
8443365Smckusick 	} *uap;
8543365Smckusick 	int *retval;
8643365Smckusick {
878031Sroot 	register struct proc *p;
8843365Smckusick 	int found = 0, error = 0;
898031Sroot 
908031Sroot 	switch (uap->which) {
918031Sroot 
928031Sroot 	case PRIO_PROCESS:
938176Sroot 		if (uap->who == 0)
9443365Smckusick 			p = curp;
958176Sroot 		else
968176Sroot 			p = pfind(uap->who);
978031Sroot 		if (p == 0)
9828149Skarels 			break;
9943365Smckusick 		error = donice(curp, p, uap->prio);
10017400Skarels 		found++;
1018031Sroot 		break;
1028031Sroot 
10335810Smarc 	case PRIO_PGRP: {
10435810Smarc 		register struct pgrp *pg;
10535810Smarc 
1068176Sroot 		if (uap->who == 0)
10743365Smckusick 			pg = curp->p_pgrp;
10835810Smarc 		else if ((pg = pgfind(uap->who)) == NULL)
10935810Smarc 			break;
11035810Smarc 		for (p = pg->pg_mem; p != NULL; p = p->p_pgrpnxt) {
11143365Smckusick 			error = donice(curp, p, uap->prio);
11235810Smarc 			found++;
11335810Smarc 		}
1148031Sroot 		break;
11535810Smarc 	}
1168031Sroot 
1178176Sroot 	case PRIO_USER:
1188176Sroot 		if (uap->who == 0)
11947541Skarels 			uap->who = curp->p_ucred->cr_uid;
12016530Skarels 		for (p = allproc; p != NULL; p = p->p_nxt)
12147541Skarels 			if (p->p_ucred->cr_uid == uap->who) {
12243365Smckusick 				error = donice(curp, p, uap->prio);
12317400Skarels 				found++;
12417400Skarels 			}
1258176Sroot 		break;
1268176Sroot 
1278031Sroot 	default:
12844405Skarels 		return (EINVAL);
1298031Sroot 	}
13017400Skarels 	if (found == 0)
13144405Skarels 		return (ESRCH);
13244405Skarels 	return (0);
1338031Sroot }
1348031Sroot 
13543365Smckusick donice(curp, chgp, n)
13643365Smckusick 	register struct proc *curp, *chgp;
1378031Sroot 	register int n;
1388031Sroot {
13947541Skarels 	register struct pcred *pcred = curp->p_cred;
1408031Sroot 
14147541Skarels 	if (pcred->pc_ucred->cr_uid && pcred->p_ruid &&
14247541Skarels 	    pcred->pc_ucred->cr_uid != chgp->p_ucred->cr_uid &&
14347541Skarels 	    pcred->p_ruid != chgp->p_ucred->cr_uid)
14443365Smckusick 		return (EPERM);
14517400Skarels 	if (n > PRIO_MAX)
14617400Skarels 		n = PRIO_MAX;
14717400Skarels 	if (n < PRIO_MIN)
14817400Skarels 		n = PRIO_MIN;
14947541Skarels 	if (n < chgp->p_nice && suser(pcred->pc_ucred, &curp->p_acflag))
15043365Smckusick 		return (EACCES);
15143365Smckusick 	chgp->p_nice = n;
15243365Smckusick 	(void) setpri(chgp);
15343365Smckusick 	return (0);
1548031Sroot }
1558031Sroot 
156*54345Smckusick #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
15743365Smckusick /* ARGSUSED */
15843365Smckusick setrlimit(p, uap, retval)
15943365Smckusick 	struct proc *p;
16043365Smckusick 	register struct args {
1618031Sroot 		u_int	which;
16253761Smckusick 		struct	orlimit *lim;
16353761Smckusick 	} *uap;
16453761Smckusick 	int *retval;
16553761Smckusick {
16653761Smckusick 	struct orlimit olim;
16753761Smckusick 	struct rlimit lim;
16853761Smckusick 	int error;
16953761Smckusick 
17053761Smckusick 	if (error =
17153761Smckusick 	    copyin((caddr_t)uap->lim, (caddr_t)&olim, sizeof (struct orlimit)))
17253761Smckusick 		return (error);
17353761Smckusick 	lim.rlim_cur = olim.rlim_cur;
17453761Smckusick 	lim.rlim_max = olim.rlim_max;
17553761Smckusick 	return (dosetrlimit(p, uap->which, &lim));
17653761Smckusick }
17753761Smckusick 
17853761Smckusick /* ARGSUSED */
17953761Smckusick getrlimit(p, uap, retval)
18053761Smckusick 	struct proc *p;
18153761Smckusick 	register struct args {
18253761Smckusick 		u_int	which;
18353761Smckusick 		struct	orlimit *rlp;
18453761Smckusick 	} *uap;
18553761Smckusick 	int *retval;
18653761Smckusick {
18753761Smckusick 	struct orlimit olim;
18853761Smckusick 
18953761Smckusick 	if (uap->which >= RLIM_NLIMITS)
19053761Smckusick 		return (EINVAL);
19153761Smckusick 	olim.rlim_cur = p->p_rlimit[uap->which].rlim_cur;
19253761Smckusick 	if (olim.rlim_cur == -1)
19353761Smckusick 		olim.rlim_cur = 0x7fffffff;
19453761Smckusick 	olim.rlim_max = p->p_rlimit[uap->which].rlim_max;
19553761Smckusick 	if (olim.rlim_max == -1)
19653761Smckusick 		olim.rlim_max = 0x7fffffff;
19753761Smckusick 	return (copyout((caddr_t)&olim, (caddr_t)uap->rlp, sizeof(olim)));
19853761Smckusick }
199*54345Smckusick #endif /* COMPAT_43 || COMPAT_SUNOS */
20053761Smckusick 
20153761Smckusick /* ARGSUSED */
20253761Smckusick __setrlimit(p, uap, retval)
20353761Smckusick 	struct proc *p;
20453761Smckusick 	register struct args {
20553761Smckusick 		u_int	which;
2068031Sroot 		struct	rlimit *lim;
20743365Smckusick 	} *uap;
20843365Smckusick 	int *retval;
20943365Smckusick {
2108031Sroot 	struct rlimit alim;
21153761Smckusick 	int error;
21253761Smckusick 
21353761Smckusick 	if (error =
21453761Smckusick 	    copyin((caddr_t)uap->lim, (caddr_t)&alim, sizeof (struct rlimit)))
21553761Smckusick 		return (error);
21653761Smckusick 	return (dosetrlimit(p, uap->which, &alim));
21753761Smckusick }
21853761Smckusick 
21953761Smckusick dosetrlimit(p, which, limp)
22053761Smckusick 	struct proc *p;
22153761Smckusick 	u_int which;
22253761Smckusick 	struct rlimit *limp;
22353761Smckusick {
2248031Sroot 	register struct rlimit *alimp;
22525257Skarels 	extern unsigned maxdmap;
22643365Smckusick 	int error;
2278031Sroot 
22853761Smckusick 	if (which >= RLIM_NLIMITS)
22944405Skarels 		return (EINVAL);
23053761Smckusick 	alimp = &p->p_rlimit[which];
23153761Smckusick 	if (limp->rlim_cur > alimp->rlim_max ||
23253761Smckusick 	    limp->rlim_max > alimp->rlim_max)
23347541Skarels 		if (error = suser(p->p_ucred, &p->p_acflag))
23444405Skarels 			return (error);
23553761Smckusick 	if (limp->rlim_cur > limp->rlim_max)
23653761Smckusick 		limp->rlim_cur = limp->rlim_max;
23747541Skarels 	if (p->p_limit->p_refcnt > 1 &&
23847541Skarels 	    (p->p_limit->p_lflags & PL_SHAREMOD) == 0) {
23947541Skarels 		p->p_limit->p_refcnt--;
24047541Skarels 		p->p_limit = limcopy(p->p_limit);
24153761Smckusick 		alimp = &p->p_rlimit[which];
24247541Skarels 	}
24347541Skarels 
24453761Smckusick 	switch (which) {
2458031Sroot 
2468031Sroot 	case RLIMIT_DATA:
24753761Smckusick 		if (limp->rlim_cur > maxdmap)
24853761Smckusick 			limp->rlim_cur = maxdmap;
24953761Smckusick 		if (limp->rlim_max > maxdmap)
25053761Smckusick 			limp->rlim_max = maxdmap;
2518031Sroot 		break;
2528031Sroot 
2538031Sroot 	case RLIMIT_STACK:
25453761Smckusick 		if (limp->rlim_cur > maxdmap)
25553761Smckusick 			limp->rlim_cur = maxdmap;
25653761Smckusick 		if (limp->rlim_max > maxdmap)
25753761Smckusick 			limp->rlim_max = maxdmap;
25849282Shibler 		/*
25949282Shibler 		 * Stack is allocated to the max at exec time with only
26049282Shibler 		 * "rlim_cur" bytes accessible.  If stack limit is going
26149282Shibler 		 * up make more accessible, if going down make inaccessible.
26249282Shibler 		 */
26353761Smckusick 		if (limp->rlim_cur != alimp->rlim_cur) {
26449282Shibler 			vm_offset_t addr;
26549282Shibler 			vm_size_t size;
26649282Shibler 			vm_prot_t prot;
26749282Shibler 
26853761Smckusick 			if (limp->rlim_cur > alimp->rlim_cur) {
26949282Shibler 				prot = VM_PROT_ALL;
27053761Smckusick 				size = limp->rlim_cur - alimp->rlim_cur;
27153761Smckusick 				addr = USRSTACK - limp->rlim_cur;
27249282Shibler 			} else {
27349282Shibler 				prot = VM_PROT_NONE;
27453761Smckusick 				size = alimp->rlim_cur - limp->rlim_cur;
27549282Shibler 				addr = USRSTACK - alimp->rlim_cur;
27649282Shibler 			}
27749282Shibler 			addr = trunc_page(addr);
27849282Shibler 			size = round_page(size);
27949282Shibler 			(void) vm_map_protect(&p->p_vmspace->vm_map,
28049282Shibler 					      addr, addr+size, prot, FALSE);
28149282Shibler 		}
2828031Sroot 		break;
2838031Sroot 	}
28453761Smckusick 	*alimp = *limp;
28544405Skarels 	return (0);
2868031Sroot }
2878031Sroot 
28843365Smckusick /* ARGSUSED */
28953761Smckusick __getrlimit(p, uap, retval)
29043365Smckusick 	struct proc *p;
29143365Smckusick 	register struct args {
2928031Sroot 		u_int	which;
2938031Sroot 		struct	rlimit *rlp;
29443365Smckusick 	} *uap;
29543365Smckusick 	int *retval;
29643365Smckusick {
2978031Sroot 
29843365Smckusick 	if (uap->which >= RLIM_NLIMITS)
29944405Skarels 		return (EINVAL);
30047541Skarels 	return (copyout((caddr_t)&p->p_rlimit[uap->which], (caddr_t)uap->rlp,
30143365Smckusick 	    sizeof (struct rlimit)));
3028031Sroot }
3038031Sroot 
30443365Smckusick /* ARGSUSED */
30543365Smckusick getrusage(p, uap, retval)
30643365Smckusick 	register struct proc *p;
30743365Smckusick 	register struct args {
3088031Sroot 		int	who;
3098031Sroot 		struct	rusage *rusage;
31043365Smckusick 	} *uap;
31143365Smckusick 	int *retval;
31243365Smckusick {
3138031Sroot 	register struct rusage *rup;
3148031Sroot 
3158031Sroot 	switch (uap->who) {
3168031Sroot 
31740705Skarels 	case RUSAGE_SELF: {
31840705Skarels 		int s;
31940705Skarels 
32047541Skarels 		rup = &p->p_stats->p_ru;
32140705Skarels 		s = splclock();
32240705Skarels 		rup->ru_stime = p->p_stime;
32340705Skarels 		rup->ru_utime = p->p_utime;
32440705Skarels 		splx(s);
3258031Sroot 		break;
32640705Skarels 	}
3278031Sroot 
3288031Sroot 	case RUSAGE_CHILDREN:
32947541Skarels 		rup = &p->p_stats->p_cru;
3308031Sroot 		break;
3318031Sroot 
3328031Sroot 	default:
33344405Skarels 		return (EINVAL);
3348031Sroot 	}
33544405Skarels 	return (copyout((caddr_t)rup, (caddr_t)uap->rusage,
33643365Smckusick 	    sizeof (struct rusage)));
3378031Sroot }
3388031Sroot 
3398031Sroot ruadd(ru, ru2)
3408031Sroot 	register struct rusage *ru, *ru2;
3418031Sroot {
3428666Sroot 	register long *ip, *ip2;
3438031Sroot 	register int i;
3448031Sroot 
3458031Sroot 	timevaladd(&ru->ru_utime, &ru2->ru_utime);
3468031Sroot 	timevaladd(&ru->ru_stime, &ru2->ru_stime);
3478031Sroot 	if (ru->ru_maxrss < ru2->ru_maxrss)
3488031Sroot 		ru->ru_maxrss = ru2->ru_maxrss;
3498031Sroot 	ip = &ru->ru_first; ip2 = &ru2->ru_first;
35053644Sbostic 	for (i = &ru->ru_last - &ru->ru_first; i >= 0; i--)
3518031Sroot 		*ip++ += *ip2++;
3528031Sroot }
35347541Skarels 
35447541Skarels /*
35547541Skarels  * Make a copy of the plimit structure.
35647541Skarels  * We share these structures copy-on-write after fork,
35747541Skarels  * and copy when a limit is changed.
35847541Skarels  */
35947541Skarels struct plimit *
36047541Skarels limcopy(lim)
36147541Skarels 	struct plimit *lim;
36247541Skarels {
36347541Skarels 	register struct plimit *copy;
36447541Skarels 
36547541Skarels 	MALLOC(copy, struct plimit *, sizeof(struct plimit),
36647541Skarels 	    M_SUBPROC, M_WAITOK);
36747541Skarels 	bcopy(lim->pl_rlimit, copy->pl_rlimit,
36847541Skarels 	    sizeof(struct rlimit) * RLIM_NLIMITS);
36947541Skarels 	copy->p_lflags = 0;
37047541Skarels 	copy->p_refcnt = 1;
37147541Skarels 	return (copy);
37247541Skarels }
373