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*54935Storek * @(#)kern_resource.c 7.21 (Berkeley) 07/10/92 823373Smckusick */ 97Sbill 1017092Sbloom #include "param.h" 1154815Storek #include "kernel.h" 1247541Skarels #include "resourcevar.h" 1347541Skarels #include "malloc.h" 1417092Sbloom #include "proc.h" 157Sbill 1649282Shibler #include "vm/vm.h" 1749282Shibler 188176Sroot /* 198176Sroot * Resource controls and accounting. 208176Sroot */ 218176Sroot 22*54935Storek struct getpriority_args { 23*54935Storek int which; 24*54935Storek int who; 25*54935Storek }; 2643365Smckusick getpriority(curp, uap, retval) 2743365Smckusick struct proc *curp; 28*54935Storek register struct getpriority_args *uap; 2943365Smckusick int *retval; 3043365Smckusick { 318031Sroot register struct proc *p; 3235810Smarc register int low = PRIO_MAX + 1; 338031Sroot 348031Sroot switch (uap->which) { 358031Sroot 368031Sroot case PRIO_PROCESS: 378031Sroot if (uap->who == 0) 3843365Smckusick p = curp; 398031Sroot else 408031Sroot p = pfind(uap->who); 418031Sroot if (p == 0) 4228149Skarels break; 4317400Skarels low = p->p_nice; 448031Sroot break; 458031Sroot 4635810Smarc case PRIO_PGRP: { 4735810Smarc register struct pgrp *pg; 4835810Smarc 498031Sroot if (uap->who == 0) 5043365Smckusick pg = curp->p_pgrp; 5135810Smarc else if ((pg = pgfind(uap->who)) == NULL) 5235810Smarc break; 5335810Smarc for (p = pg->pg_mem; p != NULL; p = p->p_pgrpnxt) { 5435810Smarc if (p->p_nice < low) 5517400Skarels low = p->p_nice; 568176Sroot } 578031Sroot break; 5835810Smarc } 598031Sroot 608176Sroot case PRIO_USER: 618176Sroot if (uap->who == 0) 6247541Skarels uap->who = curp->p_ucred->cr_uid; 6354783Storek for (p = (struct proc *)allproc; p != NULL; p = p->p_nxt) { 6447541Skarels if (p->p_ucred->cr_uid == uap->who && 6517400Skarels p->p_nice < low) 6617400Skarels low = p->p_nice; 678176Sroot } 688176Sroot break; 698176Sroot 708031Sroot default: 7144405Skarels return (EINVAL); 728031Sroot } 7343365Smckusick if (low == PRIO_MAX + 1) 7444405Skarels return (ESRCH); 7543365Smckusick *retval = low; 7644405Skarels return (0); 778031Sroot } 788031Sroot 79*54935Storek struct setpriority_args { 80*54935Storek int which; 81*54935Storek int who; 82*54935Storek int prio; 83*54935Storek }; 8443365Smckusick /* ARGSUSED */ 8543365Smckusick setpriority(curp, uap, retval) 8643365Smckusick struct proc *curp; 87*54935Storek register struct setpriority_args *uap; 8843365Smckusick int *retval; 8943365Smckusick { 908031Sroot register struct proc *p; 9143365Smckusick int found = 0, error = 0; 928031Sroot 938031Sroot switch (uap->which) { 948031Sroot 958031Sroot case PRIO_PROCESS: 968176Sroot if (uap->who == 0) 9743365Smckusick p = curp; 988176Sroot else 998176Sroot p = pfind(uap->who); 1008031Sroot if (p == 0) 10128149Skarels break; 10243365Smckusick error = donice(curp, p, uap->prio); 10317400Skarels found++; 1048031Sroot break; 1058031Sroot 10635810Smarc case PRIO_PGRP: { 10735810Smarc register struct pgrp *pg; 10835810Smarc 1098176Sroot if (uap->who == 0) 11043365Smckusick pg = curp->p_pgrp; 11135810Smarc else if ((pg = pgfind(uap->who)) == NULL) 11235810Smarc break; 11335810Smarc for (p = pg->pg_mem; p != NULL; p = p->p_pgrpnxt) { 11443365Smckusick error = donice(curp, p, uap->prio); 11535810Smarc found++; 11635810Smarc } 1178031Sroot break; 11835810Smarc } 1198031Sroot 1208176Sroot case PRIO_USER: 1218176Sroot if (uap->who == 0) 12247541Skarels uap->who = curp->p_ucred->cr_uid; 12354783Storek for (p = (struct proc *)allproc; p != NULL; p = p->p_nxt) 12447541Skarels if (p->p_ucred->cr_uid == uap->who) { 12543365Smckusick error = donice(curp, p, uap->prio); 12617400Skarels found++; 12717400Skarels } 1288176Sroot break; 1298176Sroot 1308031Sroot default: 13144405Skarels return (EINVAL); 1328031Sroot } 13317400Skarels if (found == 0) 13444405Skarels return (ESRCH); 13544405Skarels return (0); 1368031Sroot } 1378031Sroot 13843365Smckusick donice(curp, chgp, n) 13943365Smckusick register struct proc *curp, *chgp; 1408031Sroot register int n; 1418031Sroot { 14247541Skarels register struct pcred *pcred = curp->p_cred; 1438031Sroot 14447541Skarels if (pcred->pc_ucred->cr_uid && pcred->p_ruid && 14547541Skarels pcred->pc_ucred->cr_uid != chgp->p_ucred->cr_uid && 14647541Skarels pcred->p_ruid != chgp->p_ucred->cr_uid) 14743365Smckusick return (EPERM); 14817400Skarels if (n > PRIO_MAX) 14917400Skarels n = PRIO_MAX; 15017400Skarels if (n < PRIO_MIN) 15117400Skarels n = PRIO_MIN; 15247541Skarels if (n < chgp->p_nice && suser(pcred->pc_ucred, &curp->p_acflag)) 15343365Smckusick return (EACCES); 15443365Smckusick chgp->p_nice = n; 15543365Smckusick (void) setpri(chgp); 15643365Smckusick return (0); 1578031Sroot } 1588031Sroot 15954345Smckusick #if defined(COMPAT_43) || defined(COMPAT_SUNOS) 160*54935Storek struct setrlimit_args { 161*54935Storek u_int which; 162*54935Storek struct orlimit *lim; 163*54935Storek }; 16443365Smckusick /* ARGSUSED */ 16543365Smckusick setrlimit(p, uap, retval) 16643365Smckusick struct proc *p; 167*54935Storek register struct setrlimit_args *uap; 16853761Smckusick int *retval; 16953761Smckusick { 17053761Smckusick struct orlimit olim; 17153761Smckusick struct rlimit lim; 17253761Smckusick int error; 17353761Smckusick 17453761Smckusick if (error = 17553761Smckusick copyin((caddr_t)uap->lim, (caddr_t)&olim, sizeof (struct orlimit))) 17653761Smckusick return (error); 17753761Smckusick lim.rlim_cur = olim.rlim_cur; 17853761Smckusick lim.rlim_max = olim.rlim_max; 17953761Smckusick return (dosetrlimit(p, uap->which, &lim)); 18053761Smckusick } 18153761Smckusick 182*54935Storek struct getrlimit_args { 183*54935Storek u_int which; 184*54935Storek struct orlimit *rlp; 185*54935Storek }; 18653761Smckusick /* ARGSUSED */ 18753761Smckusick getrlimit(p, uap, retval) 18853761Smckusick struct proc *p; 189*54935Storek register struct getrlimit_args *uap; 19053761Smckusick int *retval; 19153761Smckusick { 19253761Smckusick struct orlimit olim; 19353761Smckusick 19453761Smckusick if (uap->which >= RLIM_NLIMITS) 19553761Smckusick return (EINVAL); 19653761Smckusick olim.rlim_cur = p->p_rlimit[uap->which].rlim_cur; 19753761Smckusick if (olim.rlim_cur == -1) 19853761Smckusick olim.rlim_cur = 0x7fffffff; 19953761Smckusick olim.rlim_max = p->p_rlimit[uap->which].rlim_max; 20053761Smckusick if (olim.rlim_max == -1) 20153761Smckusick olim.rlim_max = 0x7fffffff; 20253761Smckusick return (copyout((caddr_t)&olim, (caddr_t)uap->rlp, sizeof(olim))); 20353761Smckusick } 20454345Smckusick #endif /* COMPAT_43 || COMPAT_SUNOS */ 20553761Smckusick 206*54935Storek struct __setrlimit_args { 207*54935Storek u_int which; 208*54935Storek struct rlimit *lim; 209*54935Storek }; 21053761Smckusick /* ARGSUSED */ 21153761Smckusick __setrlimit(p, uap, retval) 21253761Smckusick struct proc *p; 213*54935Storek register struct __setrlimit_args *uap; 21443365Smckusick int *retval; 21543365Smckusick { 2168031Sroot struct rlimit alim; 21753761Smckusick int error; 21853761Smckusick 21953761Smckusick if (error = 22053761Smckusick copyin((caddr_t)uap->lim, (caddr_t)&alim, sizeof (struct rlimit))) 22153761Smckusick return (error); 22253761Smckusick return (dosetrlimit(p, uap->which, &alim)); 22353761Smckusick } 22453761Smckusick 22553761Smckusick dosetrlimit(p, which, limp) 22653761Smckusick struct proc *p; 22753761Smckusick u_int which; 22853761Smckusick struct rlimit *limp; 22953761Smckusick { 2308031Sroot register struct rlimit *alimp; 23125257Skarels extern unsigned maxdmap; 23243365Smckusick int error; 2338031Sroot 23453761Smckusick if (which >= RLIM_NLIMITS) 23544405Skarels return (EINVAL); 23653761Smckusick alimp = &p->p_rlimit[which]; 23753761Smckusick if (limp->rlim_cur > alimp->rlim_max || 23853761Smckusick limp->rlim_max > alimp->rlim_max) 23947541Skarels if (error = suser(p->p_ucred, &p->p_acflag)) 24044405Skarels return (error); 24153761Smckusick if (limp->rlim_cur > limp->rlim_max) 24253761Smckusick limp->rlim_cur = limp->rlim_max; 24347541Skarels if (p->p_limit->p_refcnt > 1 && 24447541Skarels (p->p_limit->p_lflags & PL_SHAREMOD) == 0) { 24547541Skarels p->p_limit->p_refcnt--; 24647541Skarels p->p_limit = limcopy(p->p_limit); 24753761Smckusick alimp = &p->p_rlimit[which]; 24847541Skarels } 24947541Skarels 25053761Smckusick switch (which) { 2518031Sroot 2528031Sroot case RLIMIT_DATA: 25353761Smckusick if (limp->rlim_cur > maxdmap) 25453761Smckusick limp->rlim_cur = maxdmap; 25553761Smckusick if (limp->rlim_max > maxdmap) 25653761Smckusick limp->rlim_max = maxdmap; 2578031Sroot break; 2588031Sroot 2598031Sroot case RLIMIT_STACK: 26053761Smckusick if (limp->rlim_cur > maxdmap) 26153761Smckusick limp->rlim_cur = maxdmap; 26253761Smckusick if (limp->rlim_max > maxdmap) 26353761Smckusick limp->rlim_max = maxdmap; 26449282Shibler /* 26549282Shibler * Stack is allocated to the max at exec time with only 26649282Shibler * "rlim_cur" bytes accessible. If stack limit is going 26749282Shibler * up make more accessible, if going down make inaccessible. 26849282Shibler */ 26953761Smckusick if (limp->rlim_cur != alimp->rlim_cur) { 27049282Shibler vm_offset_t addr; 27149282Shibler vm_size_t size; 27249282Shibler vm_prot_t prot; 27349282Shibler 27453761Smckusick if (limp->rlim_cur > alimp->rlim_cur) { 27549282Shibler prot = VM_PROT_ALL; 27653761Smckusick size = limp->rlim_cur - alimp->rlim_cur; 27753761Smckusick addr = USRSTACK - limp->rlim_cur; 27849282Shibler } else { 27949282Shibler prot = VM_PROT_NONE; 28053761Smckusick size = alimp->rlim_cur - limp->rlim_cur; 28149282Shibler addr = USRSTACK - alimp->rlim_cur; 28249282Shibler } 28349282Shibler addr = trunc_page(addr); 28449282Shibler size = round_page(size); 28549282Shibler (void) vm_map_protect(&p->p_vmspace->vm_map, 28649282Shibler addr, addr+size, prot, FALSE); 28749282Shibler } 2888031Sroot break; 2898031Sroot } 29053761Smckusick *alimp = *limp; 29144405Skarels return (0); 2928031Sroot } 2938031Sroot 294*54935Storek struct __getrlimit_args { 295*54935Storek u_int which; 296*54935Storek struct rlimit *rlp; 297*54935Storek }; 29843365Smckusick /* ARGSUSED */ 29953761Smckusick __getrlimit(p, uap, retval) 30043365Smckusick struct proc *p; 301*54935Storek register struct __getrlimit_args *uap; 30243365Smckusick int *retval; 30343365Smckusick { 3048031Sroot 30543365Smckusick if (uap->which >= RLIM_NLIMITS) 30644405Skarels return (EINVAL); 30747541Skarels return (copyout((caddr_t)&p->p_rlimit[uap->which], (caddr_t)uap->rlp, 30843365Smckusick sizeof (struct rlimit))); 3098031Sroot } 3108031Sroot 31154783Storek /* 31254783Storek * Transform the running time and tick information in proc p into user, 31354783Storek * system, and interrupt time usage. 31454783Storek */ 31554783Storek calcru(p, up, sp, ip) 31654783Storek register struct proc *p; 31754783Storek register struct timeval *up; 31854783Storek register struct timeval *sp; 31954783Storek register struct timeval *ip; 32054783Storek { 32154815Storek register u_quad_t u, st, ut, it, tot; 32254815Storek register u_long sec, usec; 32354815Storek register int s; 32454815Storek struct timeval tv; 32554783Storek 32654783Storek s = splstatclock(); 32754783Storek st = p->p_sticks; 32854783Storek ut = p->p_uticks; 32954783Storek it = p->p_iticks; 33054783Storek splx(s); 33154783Storek 33254783Storek tot = st + ut + it; 33354783Storek if (tot == 0) { 33454783Storek up->tv_sec = up->tv_usec = 0; 33554783Storek sp->tv_sec = sp->tv_usec = 0; 33654783Storek if (ip != NULL) 33754783Storek ip->tv_sec = ip->tv_usec = 0; 33854783Storek return; 33954783Storek } 34054815Storek 34154815Storek sec = p->p_rtime.tv_sec; 34254815Storek usec = p->p_rtime.tv_usec; 34354815Storek if (p == curproc) { 34454815Storek /* 34554815Storek * Adjust for the current time slice. This is actually fairly 34654815Storek * important since the error here is on the order of a time 34754815Storek * quantum, which is much greater than the sampling error. 34854815Storek */ 34954815Storek microtime(&tv); 35054815Storek sec += tv.tv_sec - runtime.tv_sec; 35154815Storek usec += tv.tv_usec - runtime.tv_usec; 35254815Storek } 35354815Storek u = sec * 1000000 + usec; 35454815Storek st = (u * st) / tot; 35554783Storek sp->tv_sec = st / 1000000; 35654783Storek sp->tv_usec = st % 1000000; 35754815Storek ut = (u * ut) / tot; 35854783Storek up->tv_sec = ut / 1000000; 35954783Storek up->tv_usec = ut % 1000000; 36054783Storek if (ip != NULL) { 36154815Storek it = (u * it) / tot; 36254783Storek ip->tv_sec = it / 1000000; 36354783Storek ip->tv_usec = it % 1000000; 36454783Storek } 36554783Storek } 36654783Storek 367*54935Storek struct getrusage_args { 368*54935Storek int who; 369*54935Storek struct rusage *rusage; 370*54935Storek }; 37143365Smckusick /* ARGSUSED */ 37243365Smckusick getrusage(p, uap, retval) 37343365Smckusick register struct proc *p; 374*54935Storek register struct getrusage_args *uap; 37543365Smckusick int *retval; 37643365Smckusick { 3778031Sroot register struct rusage *rup; 3788031Sroot 3798031Sroot switch (uap->who) { 3808031Sroot 38154815Storek case RUSAGE_SELF: 38247541Skarels rup = &p->p_stats->p_ru; 38354815Storek calcru(p, &rup->ru_utime, &rup->ru_stime, NULL); 3848031Sroot break; 3858031Sroot 3868031Sroot case RUSAGE_CHILDREN: 38747541Skarels rup = &p->p_stats->p_cru; 3888031Sroot break; 3898031Sroot 3908031Sroot default: 39144405Skarels return (EINVAL); 3928031Sroot } 39344405Skarels return (copyout((caddr_t)rup, (caddr_t)uap->rusage, 39443365Smckusick sizeof (struct rusage))); 3958031Sroot } 3968031Sroot 3978031Sroot ruadd(ru, ru2) 3988031Sroot register struct rusage *ru, *ru2; 3998031Sroot { 4008666Sroot register long *ip, *ip2; 4018031Sroot register int i; 4028031Sroot 4038031Sroot timevaladd(&ru->ru_utime, &ru2->ru_utime); 4048031Sroot timevaladd(&ru->ru_stime, &ru2->ru_stime); 4058031Sroot if (ru->ru_maxrss < ru2->ru_maxrss) 4068031Sroot ru->ru_maxrss = ru2->ru_maxrss; 4078031Sroot ip = &ru->ru_first; ip2 = &ru2->ru_first; 40853644Sbostic for (i = &ru->ru_last - &ru->ru_first; i >= 0; i--) 4098031Sroot *ip++ += *ip2++; 4108031Sroot } 41147541Skarels 41247541Skarels /* 41347541Skarels * Make a copy of the plimit structure. 41447541Skarels * We share these structures copy-on-write after fork, 41547541Skarels * and copy when a limit is changed. 41647541Skarels */ 41747541Skarels struct plimit * 41847541Skarels limcopy(lim) 41947541Skarels struct plimit *lim; 42047541Skarels { 42147541Skarels register struct plimit *copy; 42247541Skarels 42347541Skarels MALLOC(copy, struct plimit *, sizeof(struct plimit), 42447541Skarels M_SUBPROC, M_WAITOK); 42547541Skarels bcopy(lim->pl_rlimit, copy->pl_rlimit, 42647541Skarels sizeof(struct rlimit) * RLIM_NLIMITS); 42747541Skarels copy->p_lflags = 0; 42847541Skarels copy->p_refcnt = 1; 42947541Skarels return (copy); 43047541Skarels } 431