xref: /csrg-svn/sys/kern/kern_resource.c (revision 48419)
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*48419Skarels  *	@(#)kern_resource.c	7.11 (Berkeley) 04/20/91
723373Smckusick  */
87Sbill 
917092Sbloom #include "param.h"
1047541Skarels #include "resourcevar.h"
1147541Skarels #include "malloc.h"
1217092Sbloom #include "proc.h"
137Sbill 
148176Sroot /*
158176Sroot  * Resource controls and accounting.
168176Sroot  */
178176Sroot 
1843365Smckusick getpriority(curp, uap, retval)
1943365Smckusick 	struct proc *curp;
2043365Smckusick 	register struct args {
218031Sroot 		int	which;
228031Sroot 		int	who;
2343365Smckusick 	} *uap;
2443365Smckusick 	int *retval;
2543365Smckusick {
268031Sroot 	register struct proc *p;
2735810Smarc 	register int low = PRIO_MAX + 1;
288031Sroot 
298031Sroot 	switch (uap->which) {
308031Sroot 
318031Sroot 	case PRIO_PROCESS:
328031Sroot 		if (uap->who == 0)
3343365Smckusick 			p = curp;
348031Sroot 		else
358031Sroot 			p = pfind(uap->who);
368031Sroot 		if (p == 0)
3728149Skarels 			break;
3817400Skarels 		low = p->p_nice;
398031Sroot 		break;
408031Sroot 
4135810Smarc 	case PRIO_PGRP: {
4235810Smarc 		register struct pgrp *pg;
4335810Smarc 
448031Sroot 		if (uap->who == 0)
4543365Smckusick 			pg = curp->p_pgrp;
4635810Smarc 		else if ((pg = pgfind(uap->who)) == NULL)
4735810Smarc 			break;
4835810Smarc 		for (p = pg->pg_mem; p != NULL; p = p->p_pgrpnxt) {
4935810Smarc 			if (p->p_nice < low)
5017400Skarels 				low = p->p_nice;
518176Sroot 		}
528031Sroot 		break;
5335810Smarc 	}
548031Sroot 
558176Sroot 	case PRIO_USER:
568176Sroot 		if (uap->who == 0)
5747541Skarels 			uap->who = curp->p_ucred->cr_uid;
5816530Skarels 		for (p = allproc; p != NULL; p = p->p_nxt) {
5947541Skarels 			if (p->p_ucred->cr_uid == uap->who &&
6017400Skarels 			    p->p_nice < low)
6117400Skarels 				low = p->p_nice;
628176Sroot 		}
638176Sroot 		break;
648176Sroot 
658031Sroot 	default:
6644405Skarels 		return (EINVAL);
678031Sroot 	}
6843365Smckusick 	if (low == PRIO_MAX + 1)
6944405Skarels 		return (ESRCH);
7043365Smckusick 	*retval = low;
7144405Skarels 	return (0);
728031Sroot }
738031Sroot 
7443365Smckusick /* ARGSUSED */
7543365Smckusick setpriority(curp, uap, retval)
7643365Smckusick 	struct proc *curp;
7743365Smckusick 	register struct args {
788031Sroot 		int	which;
798031Sroot 		int	who;
808031Sroot 		int	prio;
8143365Smckusick 	} *uap;
8243365Smckusick 	int *retval;
8343365Smckusick {
848031Sroot 	register struct proc *p;
8543365Smckusick 	int found = 0, error = 0;
868031Sroot 
878031Sroot 	switch (uap->which) {
888031Sroot 
898031Sroot 	case PRIO_PROCESS:
908176Sroot 		if (uap->who == 0)
9143365Smckusick 			p = curp;
928176Sroot 		else
938176Sroot 			p = pfind(uap->who);
948031Sroot 		if (p == 0)
9528149Skarels 			break;
9643365Smckusick 		error = donice(curp, p, uap->prio);
9717400Skarels 		found++;
988031Sroot 		break;
998031Sroot 
10035810Smarc 	case PRIO_PGRP: {
10135810Smarc 		register struct pgrp *pg;
10235810Smarc 
1038176Sroot 		if (uap->who == 0)
10443365Smckusick 			pg = curp->p_pgrp;
10535810Smarc 		else if ((pg = pgfind(uap->who)) == NULL)
10635810Smarc 			break;
10735810Smarc 		for (p = pg->pg_mem; p != NULL; p = p->p_pgrpnxt) {
10843365Smckusick 			error = donice(curp, p, uap->prio);
10935810Smarc 			found++;
11035810Smarc 		}
1118031Sroot 		break;
11235810Smarc 	}
1138031Sroot 
1148176Sroot 	case PRIO_USER:
1158176Sroot 		if (uap->who == 0)
11647541Skarels 			uap->who = curp->p_ucred->cr_uid;
11716530Skarels 		for (p = allproc; p != NULL; p = p->p_nxt)
11847541Skarels 			if (p->p_ucred->cr_uid == uap->who) {
11943365Smckusick 				error = donice(curp, p, uap->prio);
12017400Skarels 				found++;
12117400Skarels 			}
1228176Sroot 		break;
1238176Sroot 
1248031Sroot 	default:
12544405Skarels 		return (EINVAL);
1268031Sroot 	}
12717400Skarels 	if (found == 0)
12844405Skarels 		return (ESRCH);
12944405Skarels 	return (0);
1308031Sroot }
1318031Sroot 
13243365Smckusick donice(curp, chgp, n)
13343365Smckusick 	register struct proc *curp, *chgp;
1348031Sroot 	register int n;
1358031Sroot {
13647541Skarels 	register struct pcred *pcred = curp->p_cred;
1378031Sroot 
13847541Skarels 	if (pcred->pc_ucred->cr_uid && pcred->p_ruid &&
13947541Skarels 	    pcred->pc_ucred->cr_uid != chgp->p_ucred->cr_uid &&
14047541Skarels 	    pcred->p_ruid != chgp->p_ucred->cr_uid)
14143365Smckusick 		return (EPERM);
14217400Skarels 	if (n > PRIO_MAX)
14317400Skarels 		n = PRIO_MAX;
14417400Skarels 	if (n < PRIO_MIN)
14517400Skarels 		n = PRIO_MIN;
14647541Skarels 	if (n < chgp->p_nice && suser(pcred->pc_ucred, &curp->p_acflag))
14743365Smckusick 		return (EACCES);
14843365Smckusick 	chgp->p_nice = n;
14943365Smckusick 	(void) setpri(chgp);
15043365Smckusick 	return (0);
1518031Sroot }
1528031Sroot 
15343365Smckusick /* ARGSUSED */
15443365Smckusick setrlimit(p, uap, retval)
15543365Smckusick 	struct proc *p;
15643365Smckusick 	register struct args {
1578031Sroot 		u_int	which;
1588031Sroot 		struct	rlimit *lim;
15943365Smckusick 	} *uap;
16043365Smckusick 	int *retval;
16143365Smckusick {
1628031Sroot 	struct rlimit alim;
1638031Sroot 	register struct rlimit *alimp;
16425257Skarels 	extern unsigned maxdmap;
16543365Smckusick 	int error;
1668031Sroot 
16743365Smckusick 	if (uap->which >= RLIM_NLIMITS)
16844405Skarels 		return (EINVAL);
16947541Skarels 	alimp = &p->p_rlimit[uap->which];
17043365Smckusick 	if (error =
17143365Smckusick 	    copyin((caddr_t)uap->lim, (caddr_t)&alim, sizeof (struct rlimit)))
17244405Skarels 		return (error);
1738031Sroot 	if (alim.rlim_cur > alimp->rlim_max || alim.rlim_max > alimp->rlim_max)
17447541Skarels 		if (error = suser(p->p_ucred, &p->p_acflag))
17544405Skarels 			return (error);
17647541Skarels 	if (p->p_limit->p_refcnt > 1 &&
17747541Skarels 	    (p->p_limit->p_lflags & PL_SHAREMOD) == 0) {
17847541Skarels 		p->p_limit->p_refcnt--;
17947541Skarels 		p->p_limit = limcopy(p->p_limit);
18047541Skarels 	}
18147541Skarels 
1828031Sroot 	switch (uap->which) {
1838031Sroot 
1848031Sroot 	case RLIMIT_DATA:
18518279Smckusick 		if (alim.rlim_cur > maxdmap)
18618279Smckusick 			alim.rlim_cur = maxdmap;
18718279Smckusick 		if (alim.rlim_max > maxdmap)
18818279Smckusick 			alim.rlim_max = maxdmap;
1898031Sroot 		break;
1908031Sroot 
1918031Sroot 	case RLIMIT_STACK:
19218279Smckusick 		if (alim.rlim_cur > maxdmap)
19318279Smckusick 			alim.rlim_cur = maxdmap;
19418279Smckusick 		if (alim.rlim_max > maxdmap)
19518279Smckusick 			alim.rlim_max = maxdmap;
1968031Sroot 		break;
1978031Sroot 	}
198*48419Skarels 	p->p_rlimit[uap->which] = alim;
19944405Skarels 	return (0);
2008031Sroot }
2018031Sroot 
20243365Smckusick /* ARGSUSED */
20343365Smckusick getrlimit(p, uap, retval)
20443365Smckusick 	struct proc *p;
20543365Smckusick 	register struct args {
2068031Sroot 		u_int	which;
2078031Sroot 		struct	rlimit *rlp;
20843365Smckusick 	} *uap;
20943365Smckusick 	int *retval;
21043365Smckusick {
2118031Sroot 
21243365Smckusick 	if (uap->which >= RLIM_NLIMITS)
21344405Skarels 		return (EINVAL);
21447541Skarels 	return (copyout((caddr_t)&p->p_rlimit[uap->which], (caddr_t)uap->rlp,
21543365Smckusick 	    sizeof (struct rlimit)));
2168031Sroot }
2178031Sroot 
21843365Smckusick /* ARGSUSED */
21943365Smckusick getrusage(p, uap, retval)
22043365Smckusick 	register struct proc *p;
22143365Smckusick 	register struct args {
2228031Sroot 		int	who;
2238031Sroot 		struct	rusage *rusage;
22443365Smckusick 	} *uap;
22543365Smckusick 	int *retval;
22643365Smckusick {
2278031Sroot 	register struct rusage *rup;
2288031Sroot 
2298031Sroot 	switch (uap->who) {
2308031Sroot 
23140705Skarels 	case RUSAGE_SELF: {
23240705Skarels 		int s;
23340705Skarels 
23447541Skarels 		rup = &p->p_stats->p_ru;
23540705Skarels 		s = splclock();
23640705Skarels 		rup->ru_stime = p->p_stime;
23740705Skarels 		rup->ru_utime = p->p_utime;
23840705Skarels 		splx(s);
2398031Sroot 		break;
24040705Skarels 	}
2418031Sroot 
2428031Sroot 	case RUSAGE_CHILDREN:
24347541Skarels 		rup = &p->p_stats->p_cru;
2448031Sroot 		break;
2458031Sroot 
2468031Sroot 	default:
24744405Skarels 		return (EINVAL);
2488031Sroot 	}
24944405Skarels 	return (copyout((caddr_t)rup, (caddr_t)uap->rusage,
25043365Smckusick 	    sizeof (struct rusage)));
2518031Sroot }
2528031Sroot 
2538031Sroot ruadd(ru, ru2)
2548031Sroot 	register struct rusage *ru, *ru2;
2558031Sroot {
2568666Sroot 	register long *ip, *ip2;
2578031Sroot 	register int i;
2588031Sroot 
2598031Sroot 	timevaladd(&ru->ru_utime, &ru2->ru_utime);
2608031Sroot 	timevaladd(&ru->ru_stime, &ru2->ru_stime);
2618031Sroot 	if (ru->ru_maxrss < ru2->ru_maxrss)
2628031Sroot 		ru->ru_maxrss = ru2->ru_maxrss;
2638031Sroot 	ip = &ru->ru_first; ip2 = &ru2->ru_first;
2648031Sroot 	for (i = &ru->ru_last - &ru->ru_first; i > 0; i--)
2658031Sroot 		*ip++ += *ip2++;
2668031Sroot }
26747541Skarels 
26847541Skarels /*
26947541Skarels  * Make a copy of the plimit structure.
27047541Skarels  * We share these structures copy-on-write after fork,
27147541Skarels  * and copy when a limit is changed.
27247541Skarels  */
27347541Skarels struct plimit *
27447541Skarels limcopy(lim)
27547541Skarels 	struct plimit *lim;
27647541Skarels {
27747541Skarels 	register struct plimit *copy;
27847541Skarels 
27947541Skarels 	MALLOC(copy, struct plimit *, sizeof(struct plimit),
28047541Skarels 	    M_SUBPROC, M_WAITOK);
28147541Skarels 	bcopy(lim->pl_rlimit, copy->pl_rlimit,
28247541Skarels 	    sizeof(struct rlimit) * RLIM_NLIMITS);
28347541Skarels 	copy->p_lflags = 0;
28447541Skarels 	copy->p_refcnt = 1;
28547541Skarels 	return (copy);
28647541Skarels }
287