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*52496Storek * @(#)kern_resource.c 7.14 (Berkeley) 02/14/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 15643365Smckusick /* ARGSUSED */ 15743365Smckusick setrlimit(p, uap, retval) 15843365Smckusick struct proc *p; 15943365Smckusick register struct args { 1608031Sroot u_int which; 1618031Sroot struct rlimit *lim; 16243365Smckusick } *uap; 16343365Smckusick int *retval; 16443365Smckusick { 1658031Sroot struct rlimit alim; 1668031Sroot register struct rlimit *alimp; 16725257Skarels extern unsigned maxdmap; 16843365Smckusick int error; 1698031Sroot 17043365Smckusick if (uap->which >= RLIM_NLIMITS) 17144405Skarels return (EINVAL); 17247541Skarels alimp = &p->p_rlimit[uap->which]; 17343365Smckusick if (error = 17443365Smckusick copyin((caddr_t)uap->lim, (caddr_t)&alim, sizeof (struct rlimit))) 17544405Skarels return (error); 1768031Sroot if (alim.rlim_cur > alimp->rlim_max || alim.rlim_max > alimp->rlim_max) 17747541Skarels if (error = suser(p->p_ucred, &p->p_acflag)) 17844405Skarels return (error); 17947541Skarels if (p->p_limit->p_refcnt > 1 && 18047541Skarels (p->p_limit->p_lflags & PL_SHAREMOD) == 0) { 18147541Skarels p->p_limit->p_refcnt--; 18247541Skarels p->p_limit = limcopy(p->p_limit); 183*52496Storek alimp = &p->p_rlimit[uap->which]; 18447541Skarels } 18547541Skarels 1868031Sroot switch (uap->which) { 1878031Sroot 1888031Sroot case RLIMIT_DATA: 18918279Smckusick if (alim.rlim_cur > maxdmap) 19018279Smckusick alim.rlim_cur = maxdmap; 19118279Smckusick if (alim.rlim_max > maxdmap) 19218279Smckusick alim.rlim_max = maxdmap; 1938031Sroot break; 1948031Sroot 1958031Sroot case RLIMIT_STACK: 19618279Smckusick if (alim.rlim_cur > maxdmap) 19718279Smckusick alim.rlim_cur = maxdmap; 19818279Smckusick if (alim.rlim_max > maxdmap) 19918279Smckusick alim.rlim_max = maxdmap; 20049282Shibler /* 20149282Shibler * Stack is allocated to the max at exec time with only 20249282Shibler * "rlim_cur" bytes accessible. If stack limit is going 20349282Shibler * up make more accessible, if going down make inaccessible. 20449282Shibler */ 20549282Shibler if (alim.rlim_cur != alimp->rlim_cur) { 20649282Shibler vm_offset_t addr; 20749282Shibler vm_size_t size; 20849282Shibler vm_prot_t prot; 20949282Shibler 21049282Shibler if (alim.rlim_cur > alimp->rlim_cur) { 21149282Shibler prot = VM_PROT_ALL; 21249282Shibler size = alim.rlim_cur - alimp->rlim_cur; 21349282Shibler addr = USRSTACK - alim.rlim_cur; 21449282Shibler } else { 21549282Shibler prot = VM_PROT_NONE; 21649282Shibler size = alimp->rlim_cur - alim.rlim_cur; 21749282Shibler addr = USRSTACK - alimp->rlim_cur; 21849282Shibler } 21949282Shibler addr = trunc_page(addr); 22049282Shibler size = round_page(size); 22149282Shibler (void) vm_map_protect(&p->p_vmspace->vm_map, 22249282Shibler addr, addr+size, prot, FALSE); 22349282Shibler } 2248031Sroot break; 2258031Sroot } 226*52496Storek *alimp = alim; 22744405Skarels return (0); 2288031Sroot } 2298031Sroot 23043365Smckusick /* ARGSUSED */ 23143365Smckusick getrlimit(p, uap, retval) 23243365Smckusick struct proc *p; 23343365Smckusick register struct args { 2348031Sroot u_int which; 2358031Sroot struct rlimit *rlp; 23643365Smckusick } *uap; 23743365Smckusick int *retval; 23843365Smckusick { 2398031Sroot 24043365Smckusick if (uap->which >= RLIM_NLIMITS) 24144405Skarels return (EINVAL); 24247541Skarels return (copyout((caddr_t)&p->p_rlimit[uap->which], (caddr_t)uap->rlp, 24343365Smckusick sizeof (struct rlimit))); 2448031Sroot } 2458031Sroot 24643365Smckusick /* ARGSUSED */ 24743365Smckusick getrusage(p, uap, retval) 24843365Smckusick register struct proc *p; 24943365Smckusick register struct args { 2508031Sroot int who; 2518031Sroot struct rusage *rusage; 25243365Smckusick } *uap; 25343365Smckusick int *retval; 25443365Smckusick { 2558031Sroot register struct rusage *rup; 2568031Sroot 2578031Sroot switch (uap->who) { 2588031Sroot 25940705Skarels case RUSAGE_SELF: { 26040705Skarels int s; 26140705Skarels 26247541Skarels rup = &p->p_stats->p_ru; 26340705Skarels s = splclock(); 26440705Skarels rup->ru_stime = p->p_stime; 26540705Skarels rup->ru_utime = p->p_utime; 26640705Skarels splx(s); 2678031Sroot break; 26840705Skarels } 2698031Sroot 2708031Sroot case RUSAGE_CHILDREN: 27147541Skarels rup = &p->p_stats->p_cru; 2728031Sroot break; 2738031Sroot 2748031Sroot default: 27544405Skarels return (EINVAL); 2768031Sroot } 27744405Skarels return (copyout((caddr_t)rup, (caddr_t)uap->rusage, 27843365Smckusick sizeof (struct rusage))); 2798031Sroot } 2808031Sroot 2818031Sroot ruadd(ru, ru2) 2828031Sroot register struct rusage *ru, *ru2; 2838031Sroot { 2848666Sroot register long *ip, *ip2; 2858031Sroot register int i; 2868031Sroot 2878031Sroot timevaladd(&ru->ru_utime, &ru2->ru_utime); 2888031Sroot timevaladd(&ru->ru_stime, &ru2->ru_stime); 2898031Sroot if (ru->ru_maxrss < ru2->ru_maxrss) 2908031Sroot ru->ru_maxrss = ru2->ru_maxrss; 2918031Sroot ip = &ru->ru_first; ip2 = &ru2->ru_first; 2928031Sroot for (i = &ru->ru_last - &ru->ru_first; i > 0; i--) 2938031Sroot *ip++ += *ip2++; 2948031Sroot } 29547541Skarels 29647541Skarels /* 29747541Skarels * Make a copy of the plimit structure. 29847541Skarels * We share these structures copy-on-write after fork, 29947541Skarels * and copy when a limit is changed. 30047541Skarels */ 30147541Skarels struct plimit * 30247541Skarels limcopy(lim) 30347541Skarels struct plimit *lim; 30447541Skarels { 30547541Skarels register struct plimit *copy; 30647541Skarels 30747541Skarels MALLOC(copy, struct plimit *, sizeof(struct plimit), 30847541Skarels M_SUBPROC, M_WAITOK); 30947541Skarels bcopy(lim->pl_rlimit, copy->pl_rlimit, 31047541Skarels sizeof(struct rlimit) * RLIM_NLIMITS); 31147541Skarels copy->p_lflags = 0; 31247541Skarels copy->p_refcnt = 1; 31347541Skarels return (copy); 31447541Skarels } 315