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*52952Smckusick * @(#)kern_resource.c 7.15 (Berkeley) 03/15/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); 179*52952Smckusick if (alim.rlim_cur > alim.rlim_max) 180*52952Smckusick alim.rlim_cur = alim.rlim_max; 18147541Skarels if (p->p_limit->p_refcnt > 1 && 18247541Skarels (p->p_limit->p_lflags & PL_SHAREMOD) == 0) { 18347541Skarels p->p_limit->p_refcnt--; 18447541Skarels p->p_limit = limcopy(p->p_limit); 18552496Storek alimp = &p->p_rlimit[uap->which]; 18647541Skarels } 18747541Skarels 1888031Sroot switch (uap->which) { 1898031Sroot 1908031Sroot case RLIMIT_DATA: 19118279Smckusick if (alim.rlim_cur > maxdmap) 19218279Smckusick alim.rlim_cur = maxdmap; 19318279Smckusick if (alim.rlim_max > maxdmap) 19418279Smckusick alim.rlim_max = maxdmap; 1958031Sroot break; 1968031Sroot 1978031Sroot case RLIMIT_STACK: 19818279Smckusick if (alim.rlim_cur > maxdmap) 19918279Smckusick alim.rlim_cur = maxdmap; 20018279Smckusick if (alim.rlim_max > maxdmap) 20118279Smckusick alim.rlim_max = maxdmap; 20249282Shibler /* 20349282Shibler * Stack is allocated to the max at exec time with only 20449282Shibler * "rlim_cur" bytes accessible. If stack limit is going 20549282Shibler * up make more accessible, if going down make inaccessible. 20649282Shibler */ 20749282Shibler if (alim.rlim_cur != alimp->rlim_cur) { 20849282Shibler vm_offset_t addr; 20949282Shibler vm_size_t size; 21049282Shibler vm_prot_t prot; 21149282Shibler 21249282Shibler if (alim.rlim_cur > alimp->rlim_cur) { 21349282Shibler prot = VM_PROT_ALL; 21449282Shibler size = alim.rlim_cur - alimp->rlim_cur; 21549282Shibler addr = USRSTACK - alim.rlim_cur; 21649282Shibler } else { 21749282Shibler prot = VM_PROT_NONE; 21849282Shibler size = alimp->rlim_cur - alim.rlim_cur; 21949282Shibler addr = USRSTACK - alimp->rlim_cur; 22049282Shibler } 22149282Shibler addr = trunc_page(addr); 22249282Shibler size = round_page(size); 22349282Shibler (void) vm_map_protect(&p->p_vmspace->vm_map, 22449282Shibler addr, addr+size, prot, FALSE); 22549282Shibler } 2268031Sroot break; 2278031Sroot } 22852496Storek *alimp = alim; 22944405Skarels return (0); 2308031Sroot } 2318031Sroot 23243365Smckusick /* ARGSUSED */ 23343365Smckusick getrlimit(p, uap, retval) 23443365Smckusick struct proc *p; 23543365Smckusick register struct args { 2368031Sroot u_int which; 2378031Sroot struct rlimit *rlp; 23843365Smckusick } *uap; 23943365Smckusick int *retval; 24043365Smckusick { 2418031Sroot 24243365Smckusick if (uap->which >= RLIM_NLIMITS) 24344405Skarels return (EINVAL); 24447541Skarels return (copyout((caddr_t)&p->p_rlimit[uap->which], (caddr_t)uap->rlp, 24543365Smckusick sizeof (struct rlimit))); 2468031Sroot } 2478031Sroot 24843365Smckusick /* ARGSUSED */ 24943365Smckusick getrusage(p, uap, retval) 25043365Smckusick register struct proc *p; 25143365Smckusick register struct args { 2528031Sroot int who; 2538031Sroot struct rusage *rusage; 25443365Smckusick } *uap; 25543365Smckusick int *retval; 25643365Smckusick { 2578031Sroot register struct rusage *rup; 2588031Sroot 2598031Sroot switch (uap->who) { 2608031Sroot 26140705Skarels case RUSAGE_SELF: { 26240705Skarels int s; 26340705Skarels 26447541Skarels rup = &p->p_stats->p_ru; 26540705Skarels s = splclock(); 26640705Skarels rup->ru_stime = p->p_stime; 26740705Skarels rup->ru_utime = p->p_utime; 26840705Skarels splx(s); 2698031Sroot break; 27040705Skarels } 2718031Sroot 2728031Sroot case RUSAGE_CHILDREN: 27347541Skarels rup = &p->p_stats->p_cru; 2748031Sroot break; 2758031Sroot 2768031Sroot default: 27744405Skarels return (EINVAL); 2788031Sroot } 27944405Skarels return (copyout((caddr_t)rup, (caddr_t)uap->rusage, 28043365Smckusick sizeof (struct rusage))); 2818031Sroot } 2828031Sroot 2838031Sroot ruadd(ru, ru2) 2848031Sroot register struct rusage *ru, *ru2; 2858031Sroot { 2868666Sroot register long *ip, *ip2; 2878031Sroot register int i; 2888031Sroot 2898031Sroot timevaladd(&ru->ru_utime, &ru2->ru_utime); 2908031Sroot timevaladd(&ru->ru_stime, &ru2->ru_stime); 2918031Sroot if (ru->ru_maxrss < ru2->ru_maxrss) 2928031Sroot ru->ru_maxrss = ru2->ru_maxrss; 2938031Sroot ip = &ru->ru_first; ip2 = &ru2->ru_first; 2948031Sroot for (i = &ru->ru_last - &ru->ru_first; i > 0; i--) 2958031Sroot *ip++ += *ip2++; 2968031Sroot } 29747541Skarels 29847541Skarels /* 29947541Skarels * Make a copy of the plimit structure. 30047541Skarels * We share these structures copy-on-write after fork, 30147541Skarels * and copy when a limit is changed. 30247541Skarels */ 30347541Skarels struct plimit * 30447541Skarels limcopy(lim) 30547541Skarels struct plimit *lim; 30647541Skarels { 30747541Skarels register struct plimit *copy; 30847541Skarels 30947541Skarels MALLOC(copy, struct plimit *, sizeof(struct plimit), 31047541Skarels M_SUBPROC, M_WAITOK); 31147541Skarels bcopy(lim->pl_rlimit, copy->pl_rlimit, 31247541Skarels sizeof(struct rlimit) * RLIM_NLIMITS); 31347541Skarels copy->p_lflags = 0; 31447541Skarels copy->p_refcnt = 1; 31547541Skarels return (copy); 31647541Skarels } 317