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*53761Smckusick * @(#)kern_resource.c 7.17 (Berkeley) 05/31/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*53761Smckusick #ifdef COMPAT_43 15743365Smckusick /* ARGSUSED */ 15843365Smckusick setrlimit(p, uap, retval) 15943365Smckusick struct proc *p; 16043365Smckusick register struct args { 1618031Sroot u_int which; 162*53761Smckusick struct orlimit *lim; 163*53761Smckusick } *uap; 164*53761Smckusick int *retval; 165*53761Smckusick { 166*53761Smckusick struct orlimit olim; 167*53761Smckusick struct rlimit lim; 168*53761Smckusick int error; 169*53761Smckusick 170*53761Smckusick if (error = 171*53761Smckusick copyin((caddr_t)uap->lim, (caddr_t)&olim, sizeof (struct orlimit))) 172*53761Smckusick return (error); 173*53761Smckusick lim.rlim_cur = olim.rlim_cur; 174*53761Smckusick lim.rlim_max = olim.rlim_max; 175*53761Smckusick return (dosetrlimit(p, uap->which, &lim)); 176*53761Smckusick } 177*53761Smckusick 178*53761Smckusick /* ARGSUSED */ 179*53761Smckusick getrlimit(p, uap, retval) 180*53761Smckusick struct proc *p; 181*53761Smckusick register struct args { 182*53761Smckusick u_int which; 183*53761Smckusick struct orlimit *rlp; 184*53761Smckusick } *uap; 185*53761Smckusick int *retval; 186*53761Smckusick { 187*53761Smckusick struct orlimit olim; 188*53761Smckusick 189*53761Smckusick if (uap->which >= RLIM_NLIMITS) 190*53761Smckusick return (EINVAL); 191*53761Smckusick olim.rlim_cur = p->p_rlimit[uap->which].rlim_cur; 192*53761Smckusick if (olim.rlim_cur == -1) 193*53761Smckusick olim.rlim_cur = 0x7fffffff; 194*53761Smckusick olim.rlim_max = p->p_rlimit[uap->which].rlim_max; 195*53761Smckusick if (olim.rlim_max == -1) 196*53761Smckusick olim.rlim_max = 0x7fffffff; 197*53761Smckusick return (copyout((caddr_t)&olim, (caddr_t)uap->rlp, sizeof(olim))); 198*53761Smckusick } 199*53761Smckusick #endif /* COMPAT_43 */ 200*53761Smckusick 201*53761Smckusick /* ARGSUSED */ 202*53761Smckusick __setrlimit(p, uap, retval) 203*53761Smckusick struct proc *p; 204*53761Smckusick register struct args { 205*53761Smckusick u_int which; 2068031Sroot struct rlimit *lim; 20743365Smckusick } *uap; 20843365Smckusick int *retval; 20943365Smckusick { 2108031Sroot struct rlimit alim; 211*53761Smckusick int error; 212*53761Smckusick 213*53761Smckusick if (error = 214*53761Smckusick copyin((caddr_t)uap->lim, (caddr_t)&alim, sizeof (struct rlimit))) 215*53761Smckusick return (error); 216*53761Smckusick return (dosetrlimit(p, uap->which, &alim)); 217*53761Smckusick } 218*53761Smckusick 219*53761Smckusick dosetrlimit(p, which, limp) 220*53761Smckusick struct proc *p; 221*53761Smckusick u_int which; 222*53761Smckusick struct rlimit *limp; 223*53761Smckusick { 2248031Sroot register struct rlimit *alimp; 22525257Skarels extern unsigned maxdmap; 22643365Smckusick int error; 2278031Sroot 228*53761Smckusick if (which >= RLIM_NLIMITS) 22944405Skarels return (EINVAL); 230*53761Smckusick alimp = &p->p_rlimit[which]; 231*53761Smckusick if (limp->rlim_cur > alimp->rlim_max || 232*53761Smckusick limp->rlim_max > alimp->rlim_max) 23347541Skarels if (error = suser(p->p_ucred, &p->p_acflag)) 23444405Skarels return (error); 235*53761Smckusick if (limp->rlim_cur > limp->rlim_max) 236*53761Smckusick 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); 241*53761Smckusick alimp = &p->p_rlimit[which]; 24247541Skarels } 24347541Skarels 244*53761Smckusick switch (which) { 2458031Sroot 2468031Sroot case RLIMIT_DATA: 247*53761Smckusick if (limp->rlim_cur > maxdmap) 248*53761Smckusick limp->rlim_cur = maxdmap; 249*53761Smckusick if (limp->rlim_max > maxdmap) 250*53761Smckusick limp->rlim_max = maxdmap; 2518031Sroot break; 2528031Sroot 2538031Sroot case RLIMIT_STACK: 254*53761Smckusick if (limp->rlim_cur > maxdmap) 255*53761Smckusick limp->rlim_cur = maxdmap; 256*53761Smckusick if (limp->rlim_max > maxdmap) 257*53761Smckusick 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 */ 263*53761Smckusick if (limp->rlim_cur != alimp->rlim_cur) { 26449282Shibler vm_offset_t addr; 26549282Shibler vm_size_t size; 26649282Shibler vm_prot_t prot; 26749282Shibler 268*53761Smckusick if (limp->rlim_cur > alimp->rlim_cur) { 26949282Shibler prot = VM_PROT_ALL; 270*53761Smckusick size = limp->rlim_cur - alimp->rlim_cur; 271*53761Smckusick addr = USRSTACK - limp->rlim_cur; 27249282Shibler } else { 27349282Shibler prot = VM_PROT_NONE; 274*53761Smckusick 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 } 284*53761Smckusick *alimp = *limp; 28544405Skarels return (0); 2868031Sroot } 2878031Sroot 28843365Smckusick /* ARGSUSED */ 289*53761Smckusick __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