xref: /csrg-svn/sys/kern/kern_resource.c (revision 49282)
123373Smckusick /*
229093Smckusick  * Copyright (c) 1982, 1986 Regents of the University of California.
323373Smckusick  * All rights reserved.  The Berkeley software License Agreement
423373Smckusick  * specifies the terms and conditions for redistribution.
523373Smckusick  *
6*49282Shibler  *	@(#)kern_resource.c	7.12 (Berkeley) 05/07/91
723373Smckusick  */
87Sbill 
917092Sbloom #include "param.h"
1047541Skarels #include "resourcevar.h"
1147541Skarels #include "malloc.h"
1217092Sbloom #include "proc.h"
137Sbill 
14*49282Shibler #include "vm/vm.h"
15*49282Shibler 
168176Sroot /*
178176Sroot  * Resource controls and accounting.
188176Sroot  */
198176Sroot 
2043365Smckusick getpriority(curp, uap, retval)
2143365Smckusick 	struct proc *curp;
2243365Smckusick 	register struct args {
238031Sroot 		int	which;
248031Sroot 		int	who;
2543365Smckusick 	} *uap;
2643365Smckusick 	int *retval;
2743365Smckusick {
288031Sroot 	register struct proc *p;
2935810Smarc 	register int low = PRIO_MAX + 1;
308031Sroot 
318031Sroot 	switch (uap->which) {
328031Sroot 
338031Sroot 	case PRIO_PROCESS:
348031Sroot 		if (uap->who == 0)
3543365Smckusick 			p = curp;
368031Sroot 		else
378031Sroot 			p = pfind(uap->who);
388031Sroot 		if (p == 0)
3928149Skarels 			break;
4017400Skarels 		low = p->p_nice;
418031Sroot 		break;
428031Sroot 
4335810Smarc 	case PRIO_PGRP: {
4435810Smarc 		register struct pgrp *pg;
4535810Smarc 
468031Sroot 		if (uap->who == 0)
4743365Smckusick 			pg = curp->p_pgrp;
4835810Smarc 		else if ((pg = pgfind(uap->who)) == NULL)
4935810Smarc 			break;
5035810Smarc 		for (p = pg->pg_mem; p != NULL; p = p->p_pgrpnxt) {
5135810Smarc 			if (p->p_nice < low)
5217400Skarels 				low = p->p_nice;
538176Sroot 		}
548031Sroot 		break;
5535810Smarc 	}
568031Sroot 
578176Sroot 	case PRIO_USER:
588176Sroot 		if (uap->who == 0)
5947541Skarels 			uap->who = curp->p_ucred->cr_uid;
6016530Skarels 		for (p = allproc; p != NULL; p = p->p_nxt) {
6147541Skarels 			if (p->p_ucred->cr_uid == uap->who &&
6217400Skarels 			    p->p_nice < low)
6317400Skarels 				low = p->p_nice;
648176Sroot 		}
658176Sroot 		break;
668176Sroot 
678031Sroot 	default:
6844405Skarels 		return (EINVAL);
698031Sroot 	}
7043365Smckusick 	if (low == PRIO_MAX + 1)
7144405Skarels 		return (ESRCH);
7243365Smckusick 	*retval = low;
7344405Skarels 	return (0);
748031Sroot }
758031Sroot 
7643365Smckusick /* ARGSUSED */
7743365Smckusick setpriority(curp, uap, retval)
7843365Smckusick 	struct proc *curp;
7943365Smckusick 	register struct args {
808031Sroot 		int	which;
818031Sroot 		int	who;
828031Sroot 		int	prio;
8343365Smckusick 	} *uap;
8443365Smckusick 	int *retval;
8543365Smckusick {
868031Sroot 	register struct proc *p;
8743365Smckusick 	int found = 0, error = 0;
888031Sroot 
898031Sroot 	switch (uap->which) {
908031Sroot 
918031Sroot 	case PRIO_PROCESS:
928176Sroot 		if (uap->who == 0)
9343365Smckusick 			p = curp;
948176Sroot 		else
958176Sroot 			p = pfind(uap->who);
968031Sroot 		if (p == 0)
9728149Skarels 			break;
9843365Smckusick 		error = donice(curp, p, uap->prio);
9917400Skarels 		found++;
1008031Sroot 		break;
1018031Sroot 
10235810Smarc 	case PRIO_PGRP: {
10335810Smarc 		register struct pgrp *pg;
10435810Smarc 
1058176Sroot 		if (uap->who == 0)
10643365Smckusick 			pg = curp->p_pgrp;
10735810Smarc 		else if ((pg = pgfind(uap->who)) == NULL)
10835810Smarc 			break;
10935810Smarc 		for (p = pg->pg_mem; p != NULL; p = p->p_pgrpnxt) {
11043365Smckusick 			error = donice(curp, p, uap->prio);
11135810Smarc 			found++;
11235810Smarc 		}
1138031Sroot 		break;
11435810Smarc 	}
1158031Sroot 
1168176Sroot 	case PRIO_USER:
1178176Sroot 		if (uap->who == 0)
11847541Skarels 			uap->who = curp->p_ucred->cr_uid;
11916530Skarels 		for (p = allproc; p != NULL; p = p->p_nxt)
12047541Skarels 			if (p->p_ucred->cr_uid == uap->who) {
12143365Smckusick 				error = donice(curp, p, uap->prio);
12217400Skarels 				found++;
12317400Skarels 			}
1248176Sroot 		break;
1258176Sroot 
1268031Sroot 	default:
12744405Skarels 		return (EINVAL);
1288031Sroot 	}
12917400Skarels 	if (found == 0)
13044405Skarels 		return (ESRCH);
13144405Skarels 	return (0);
1328031Sroot }
1338031Sroot 
13443365Smckusick donice(curp, chgp, n)
13543365Smckusick 	register struct proc *curp, *chgp;
1368031Sroot 	register int n;
1378031Sroot {
13847541Skarels 	register struct pcred *pcred = curp->p_cred;
1398031Sroot 
14047541Skarels 	if (pcred->pc_ucred->cr_uid && pcred->p_ruid &&
14147541Skarels 	    pcred->pc_ucred->cr_uid != chgp->p_ucred->cr_uid &&
14247541Skarels 	    pcred->p_ruid != chgp->p_ucred->cr_uid)
14343365Smckusick 		return (EPERM);
14417400Skarels 	if (n > PRIO_MAX)
14517400Skarels 		n = PRIO_MAX;
14617400Skarels 	if (n < PRIO_MIN)
14717400Skarels 		n = PRIO_MIN;
14847541Skarels 	if (n < chgp->p_nice && suser(pcred->pc_ucred, &curp->p_acflag))
14943365Smckusick 		return (EACCES);
15043365Smckusick 	chgp->p_nice = n;
15143365Smckusick 	(void) setpri(chgp);
15243365Smckusick 	return (0);
1538031Sroot }
1548031Sroot 
15543365Smckusick /* ARGSUSED */
15643365Smckusick setrlimit(p, uap, retval)
15743365Smckusick 	struct proc *p;
15843365Smckusick 	register struct args {
1598031Sroot 		u_int	which;
1608031Sroot 		struct	rlimit *lim;
16143365Smckusick 	} *uap;
16243365Smckusick 	int *retval;
16343365Smckusick {
1648031Sroot 	struct rlimit alim;
1658031Sroot 	register struct rlimit *alimp;
16625257Skarels 	extern unsigned maxdmap;
16743365Smckusick 	int error;
1688031Sroot 
16943365Smckusick 	if (uap->which >= RLIM_NLIMITS)
17044405Skarels 		return (EINVAL);
17147541Skarels 	alimp = &p->p_rlimit[uap->which];
17243365Smckusick 	if (error =
17343365Smckusick 	    copyin((caddr_t)uap->lim, (caddr_t)&alim, sizeof (struct rlimit)))
17444405Skarels 		return (error);
1758031Sroot 	if (alim.rlim_cur > alimp->rlim_max || alim.rlim_max > alimp->rlim_max)
17647541Skarels 		if (error = suser(p->p_ucred, &p->p_acflag))
17744405Skarels 			return (error);
17847541Skarels 	if (p->p_limit->p_refcnt > 1 &&
17947541Skarels 	    (p->p_limit->p_lflags & PL_SHAREMOD) == 0) {
18047541Skarels 		p->p_limit->p_refcnt--;
18147541Skarels 		p->p_limit = limcopy(p->p_limit);
18247541Skarels 	}
18347541Skarels 
1848031Sroot 	switch (uap->which) {
1858031Sroot 
1868031Sroot 	case RLIMIT_DATA:
18718279Smckusick 		if (alim.rlim_cur > maxdmap)
18818279Smckusick 			alim.rlim_cur = maxdmap;
18918279Smckusick 		if (alim.rlim_max > maxdmap)
19018279Smckusick 			alim.rlim_max = maxdmap;
1918031Sroot 		break;
1928031Sroot 
1938031Sroot 	case RLIMIT_STACK:
19418279Smckusick 		if (alim.rlim_cur > maxdmap)
19518279Smckusick 			alim.rlim_cur = maxdmap;
19618279Smckusick 		if (alim.rlim_max > maxdmap)
19718279Smckusick 			alim.rlim_max = maxdmap;
198*49282Shibler 		/*
199*49282Shibler 		 * Stack is allocated to the max at exec time with only
200*49282Shibler 		 * "rlim_cur" bytes accessible.  If stack limit is going
201*49282Shibler 		 * up make more accessible, if going down make inaccessible.
202*49282Shibler 		 */
203*49282Shibler 		if (alim.rlim_cur != alimp->rlim_cur) {
204*49282Shibler 			vm_offset_t addr;
205*49282Shibler 			vm_size_t size;
206*49282Shibler 			vm_prot_t prot;
207*49282Shibler 
208*49282Shibler 			if (alim.rlim_cur > alimp->rlim_cur) {
209*49282Shibler 				prot = VM_PROT_ALL;
210*49282Shibler 				size = alim.rlim_cur - alimp->rlim_cur;
211*49282Shibler 				addr = USRSTACK - alim.rlim_cur;
212*49282Shibler 			} else {
213*49282Shibler 				prot = VM_PROT_NONE;
214*49282Shibler 				size = alimp->rlim_cur - alim.rlim_cur;
215*49282Shibler 				addr = USRSTACK - alimp->rlim_cur;
216*49282Shibler 			}
217*49282Shibler 			addr = trunc_page(addr);
218*49282Shibler 			size = round_page(size);
219*49282Shibler 			(void) vm_map_protect(&p->p_vmspace->vm_map,
220*49282Shibler 					      addr, addr+size, prot, FALSE);
221*49282Shibler 		}
2228031Sroot 		break;
2238031Sroot 	}
22448419Skarels 	p->p_rlimit[uap->which] = alim;
22544405Skarels 	return (0);
2268031Sroot }
2278031Sroot 
22843365Smckusick /* ARGSUSED */
22943365Smckusick getrlimit(p, uap, retval)
23043365Smckusick 	struct proc *p;
23143365Smckusick 	register struct args {
2328031Sroot 		u_int	which;
2338031Sroot 		struct	rlimit *rlp;
23443365Smckusick 	} *uap;
23543365Smckusick 	int *retval;
23643365Smckusick {
2378031Sroot 
23843365Smckusick 	if (uap->which >= RLIM_NLIMITS)
23944405Skarels 		return (EINVAL);
24047541Skarels 	return (copyout((caddr_t)&p->p_rlimit[uap->which], (caddr_t)uap->rlp,
24143365Smckusick 	    sizeof (struct rlimit)));
2428031Sroot }
2438031Sroot 
24443365Smckusick /* ARGSUSED */
24543365Smckusick getrusage(p, uap, retval)
24643365Smckusick 	register struct proc *p;
24743365Smckusick 	register struct args {
2488031Sroot 		int	who;
2498031Sroot 		struct	rusage *rusage;
25043365Smckusick 	} *uap;
25143365Smckusick 	int *retval;
25243365Smckusick {
2538031Sroot 	register struct rusage *rup;
2548031Sroot 
2558031Sroot 	switch (uap->who) {
2568031Sroot 
25740705Skarels 	case RUSAGE_SELF: {
25840705Skarels 		int s;
25940705Skarels 
26047541Skarels 		rup = &p->p_stats->p_ru;
26140705Skarels 		s = splclock();
26240705Skarels 		rup->ru_stime = p->p_stime;
26340705Skarels 		rup->ru_utime = p->p_utime;
26440705Skarels 		splx(s);
2658031Sroot 		break;
26640705Skarels 	}
2678031Sroot 
2688031Sroot 	case RUSAGE_CHILDREN:
26947541Skarels 		rup = &p->p_stats->p_cru;
2708031Sroot 		break;
2718031Sroot 
2728031Sroot 	default:
27344405Skarels 		return (EINVAL);
2748031Sroot 	}
27544405Skarels 	return (copyout((caddr_t)rup, (caddr_t)uap->rusage,
27643365Smckusick 	    sizeof (struct rusage)));
2778031Sroot }
2788031Sroot 
2798031Sroot ruadd(ru, ru2)
2808031Sroot 	register struct rusage *ru, *ru2;
2818031Sroot {
2828666Sroot 	register long *ip, *ip2;
2838031Sroot 	register int i;
2848031Sroot 
2858031Sroot 	timevaladd(&ru->ru_utime, &ru2->ru_utime);
2868031Sroot 	timevaladd(&ru->ru_stime, &ru2->ru_stime);
2878031Sroot 	if (ru->ru_maxrss < ru2->ru_maxrss)
2888031Sroot 		ru->ru_maxrss = ru2->ru_maxrss;
2898031Sroot 	ip = &ru->ru_first; ip2 = &ru2->ru_first;
2908031Sroot 	for (i = &ru->ru_last - &ru->ru_first; i > 0; i--)
2918031Sroot 		*ip++ += *ip2++;
2928031Sroot }
29347541Skarels 
29447541Skarels /*
29547541Skarels  * Make a copy of the plimit structure.
29647541Skarels  * We share these structures copy-on-write after fork,
29747541Skarels  * and copy when a limit is changed.
29847541Skarels  */
29947541Skarels struct plimit *
30047541Skarels limcopy(lim)
30147541Skarels 	struct plimit *lim;
30247541Skarels {
30347541Skarels 	register struct plimit *copy;
30447541Skarels 
30547541Skarels 	MALLOC(copy, struct plimit *, sizeof(struct plimit),
30647541Skarels 	    M_SUBPROC, M_WAITOK);
30747541Skarels 	bcopy(lim->pl_rlimit, copy->pl_rlimit,
30847541Skarels 	    sizeof(struct rlimit) * RLIM_NLIMITS);
30947541Skarels 	copy->p_lflags = 0;
31047541Skarels 	copy->p_refcnt = 1;
31147541Skarels 	return (copy);
31247541Skarels }
313