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*49282Shibler * @(#)kern_resource.c 7.12 (Berkeley) 05/07/91 723373Smckusick */ 87Sbill 917092Sbloom #include "param.h" 1047541Skarels #include "resourcevar.h" 1147541Skarels #include "malloc.h" 1217092Sbloom #include "proc.h" 137Sbill 14*49282Shibler #include "vm/vm.h" 15*49282Shibler 168176Sroot /* 178176Sroot * Resource controls and accounting. 188176Sroot */ 198176Sroot 2043365Smckusick getpriority(curp, uap, retval) 2143365Smckusick struct proc *curp; 2243365Smckusick register struct args { 238031Sroot int which; 248031Sroot int who; 2543365Smckusick } *uap; 2643365Smckusick int *retval; 2743365Smckusick { 288031Sroot register struct proc *p; 2935810Smarc register int low = PRIO_MAX + 1; 308031Sroot 318031Sroot switch (uap->which) { 328031Sroot 338031Sroot case PRIO_PROCESS: 348031Sroot if (uap->who == 0) 3543365Smckusick p = curp; 368031Sroot else 378031Sroot p = pfind(uap->who); 388031Sroot if (p == 0) 3928149Skarels break; 4017400Skarels low = p->p_nice; 418031Sroot break; 428031Sroot 4335810Smarc case PRIO_PGRP: { 4435810Smarc register struct pgrp *pg; 4535810Smarc 468031Sroot if (uap->who == 0) 4743365Smckusick pg = curp->p_pgrp; 4835810Smarc else if ((pg = pgfind(uap->who)) == NULL) 4935810Smarc break; 5035810Smarc for (p = pg->pg_mem; p != NULL; p = p->p_pgrpnxt) { 5135810Smarc if (p->p_nice < low) 5217400Skarels low = p->p_nice; 538176Sroot } 548031Sroot break; 5535810Smarc } 568031Sroot 578176Sroot case PRIO_USER: 588176Sroot if (uap->who == 0) 5947541Skarels uap->who = curp->p_ucred->cr_uid; 6016530Skarels for (p = allproc; p != NULL; p = p->p_nxt) { 6147541Skarels if (p->p_ucred->cr_uid == uap->who && 6217400Skarels p->p_nice < low) 6317400Skarels low = p->p_nice; 648176Sroot } 658176Sroot break; 668176Sroot 678031Sroot default: 6844405Skarels return (EINVAL); 698031Sroot } 7043365Smckusick if (low == PRIO_MAX + 1) 7144405Skarels return (ESRCH); 7243365Smckusick *retval = low; 7344405Skarels return (0); 748031Sroot } 758031Sroot 7643365Smckusick /* ARGSUSED */ 7743365Smckusick setpriority(curp, uap, retval) 7843365Smckusick struct proc *curp; 7943365Smckusick register struct args { 808031Sroot int which; 818031Sroot int who; 828031Sroot int prio; 8343365Smckusick } *uap; 8443365Smckusick int *retval; 8543365Smckusick { 868031Sroot register struct proc *p; 8743365Smckusick int found = 0, error = 0; 888031Sroot 898031Sroot switch (uap->which) { 908031Sroot 918031Sroot case PRIO_PROCESS: 928176Sroot if (uap->who == 0) 9343365Smckusick p = curp; 948176Sroot else 958176Sroot p = pfind(uap->who); 968031Sroot if (p == 0) 9728149Skarels break; 9843365Smckusick error = donice(curp, p, uap->prio); 9917400Skarels found++; 1008031Sroot break; 1018031Sroot 10235810Smarc case PRIO_PGRP: { 10335810Smarc register struct pgrp *pg; 10435810Smarc 1058176Sroot if (uap->who == 0) 10643365Smckusick pg = curp->p_pgrp; 10735810Smarc else if ((pg = pgfind(uap->who)) == NULL) 10835810Smarc break; 10935810Smarc for (p = pg->pg_mem; p != NULL; p = p->p_pgrpnxt) { 11043365Smckusick error = donice(curp, p, uap->prio); 11135810Smarc found++; 11235810Smarc } 1138031Sroot break; 11435810Smarc } 1158031Sroot 1168176Sroot case PRIO_USER: 1178176Sroot if (uap->who == 0) 11847541Skarels uap->who = curp->p_ucred->cr_uid; 11916530Skarels for (p = allproc; p != NULL; p = p->p_nxt) 12047541Skarels if (p->p_ucred->cr_uid == uap->who) { 12143365Smckusick error = donice(curp, p, uap->prio); 12217400Skarels found++; 12317400Skarels } 1248176Sroot break; 1258176Sroot 1268031Sroot default: 12744405Skarels return (EINVAL); 1288031Sroot } 12917400Skarels if (found == 0) 13044405Skarels return (ESRCH); 13144405Skarels return (0); 1328031Sroot } 1338031Sroot 13443365Smckusick donice(curp, chgp, n) 13543365Smckusick register struct proc *curp, *chgp; 1368031Sroot register int n; 1378031Sroot { 13847541Skarels register struct pcred *pcred = curp->p_cred; 1398031Sroot 14047541Skarels if (pcred->pc_ucred->cr_uid && pcred->p_ruid && 14147541Skarels pcred->pc_ucred->cr_uid != chgp->p_ucred->cr_uid && 14247541Skarels pcred->p_ruid != chgp->p_ucred->cr_uid) 14343365Smckusick return (EPERM); 14417400Skarels if (n > PRIO_MAX) 14517400Skarels n = PRIO_MAX; 14617400Skarels if (n < PRIO_MIN) 14717400Skarels n = PRIO_MIN; 14847541Skarels if (n < chgp->p_nice && suser(pcred->pc_ucred, &curp->p_acflag)) 14943365Smckusick return (EACCES); 15043365Smckusick chgp->p_nice = n; 15143365Smckusick (void) setpri(chgp); 15243365Smckusick return (0); 1538031Sroot } 1548031Sroot 15543365Smckusick /* ARGSUSED */ 15643365Smckusick setrlimit(p, uap, retval) 15743365Smckusick struct proc *p; 15843365Smckusick register struct args { 1598031Sroot u_int which; 1608031Sroot struct rlimit *lim; 16143365Smckusick } *uap; 16243365Smckusick int *retval; 16343365Smckusick { 1648031Sroot struct rlimit alim; 1658031Sroot register struct rlimit *alimp; 16625257Skarels extern unsigned maxdmap; 16743365Smckusick int error; 1688031Sroot 16943365Smckusick if (uap->which >= RLIM_NLIMITS) 17044405Skarels return (EINVAL); 17147541Skarels alimp = &p->p_rlimit[uap->which]; 17243365Smckusick if (error = 17343365Smckusick copyin((caddr_t)uap->lim, (caddr_t)&alim, sizeof (struct rlimit))) 17444405Skarels return (error); 1758031Sroot if (alim.rlim_cur > alimp->rlim_max || alim.rlim_max > alimp->rlim_max) 17647541Skarels if (error = suser(p->p_ucred, &p->p_acflag)) 17744405Skarels return (error); 17847541Skarels if (p->p_limit->p_refcnt > 1 && 17947541Skarels (p->p_limit->p_lflags & PL_SHAREMOD) == 0) { 18047541Skarels p->p_limit->p_refcnt--; 18147541Skarels p->p_limit = limcopy(p->p_limit); 18247541Skarels } 18347541Skarels 1848031Sroot switch (uap->which) { 1858031Sroot 1868031Sroot case RLIMIT_DATA: 18718279Smckusick if (alim.rlim_cur > maxdmap) 18818279Smckusick alim.rlim_cur = maxdmap; 18918279Smckusick if (alim.rlim_max > maxdmap) 19018279Smckusick alim.rlim_max = maxdmap; 1918031Sroot break; 1928031Sroot 1938031Sroot case RLIMIT_STACK: 19418279Smckusick if (alim.rlim_cur > maxdmap) 19518279Smckusick alim.rlim_cur = maxdmap; 19618279Smckusick if (alim.rlim_max > maxdmap) 19718279Smckusick alim.rlim_max = maxdmap; 198*49282Shibler /* 199*49282Shibler * Stack is allocated to the max at exec time with only 200*49282Shibler * "rlim_cur" bytes accessible. If stack limit is going 201*49282Shibler * up make more accessible, if going down make inaccessible. 202*49282Shibler */ 203*49282Shibler if (alim.rlim_cur != alimp->rlim_cur) { 204*49282Shibler vm_offset_t addr; 205*49282Shibler vm_size_t size; 206*49282Shibler vm_prot_t prot; 207*49282Shibler 208*49282Shibler if (alim.rlim_cur > alimp->rlim_cur) { 209*49282Shibler prot = VM_PROT_ALL; 210*49282Shibler size = alim.rlim_cur - alimp->rlim_cur; 211*49282Shibler addr = USRSTACK - alim.rlim_cur; 212*49282Shibler } else { 213*49282Shibler prot = VM_PROT_NONE; 214*49282Shibler size = alimp->rlim_cur - alim.rlim_cur; 215*49282Shibler addr = USRSTACK - alimp->rlim_cur; 216*49282Shibler } 217*49282Shibler addr = trunc_page(addr); 218*49282Shibler size = round_page(size); 219*49282Shibler (void) vm_map_protect(&p->p_vmspace->vm_map, 220*49282Shibler addr, addr+size, prot, FALSE); 221*49282Shibler } 2228031Sroot break; 2238031Sroot } 22448419Skarels p->p_rlimit[uap->which] = alim; 22544405Skarels return (0); 2268031Sroot } 2278031Sroot 22843365Smckusick /* ARGSUSED */ 22943365Smckusick getrlimit(p, uap, retval) 23043365Smckusick struct proc *p; 23143365Smckusick register struct args { 2328031Sroot u_int which; 2338031Sroot struct rlimit *rlp; 23443365Smckusick } *uap; 23543365Smckusick int *retval; 23643365Smckusick { 2378031Sroot 23843365Smckusick if (uap->which >= RLIM_NLIMITS) 23944405Skarels return (EINVAL); 24047541Skarels return (copyout((caddr_t)&p->p_rlimit[uap->which], (caddr_t)uap->rlp, 24143365Smckusick sizeof (struct rlimit))); 2428031Sroot } 2438031Sroot 24443365Smckusick /* ARGSUSED */ 24543365Smckusick getrusage(p, uap, retval) 24643365Smckusick register struct proc *p; 24743365Smckusick register struct args { 2488031Sroot int who; 2498031Sroot struct rusage *rusage; 25043365Smckusick } *uap; 25143365Smckusick int *retval; 25243365Smckusick { 2538031Sroot register struct rusage *rup; 2548031Sroot 2558031Sroot switch (uap->who) { 2568031Sroot 25740705Skarels case RUSAGE_SELF: { 25840705Skarels int s; 25940705Skarels 26047541Skarels rup = &p->p_stats->p_ru; 26140705Skarels s = splclock(); 26240705Skarels rup->ru_stime = p->p_stime; 26340705Skarels rup->ru_utime = p->p_utime; 26440705Skarels splx(s); 2658031Sroot break; 26640705Skarels } 2678031Sroot 2688031Sroot case RUSAGE_CHILDREN: 26947541Skarels rup = &p->p_stats->p_cru; 2708031Sroot break; 2718031Sroot 2728031Sroot default: 27344405Skarels return (EINVAL); 2748031Sroot } 27544405Skarels return (copyout((caddr_t)rup, (caddr_t)uap->rusage, 27643365Smckusick sizeof (struct rusage))); 2778031Sroot } 2788031Sroot 2798031Sroot ruadd(ru, ru2) 2808031Sroot register struct rusage *ru, *ru2; 2818031Sroot { 2828666Sroot register long *ip, *ip2; 2838031Sroot register int i; 2848031Sroot 2858031Sroot timevaladd(&ru->ru_utime, &ru2->ru_utime); 2868031Sroot timevaladd(&ru->ru_stime, &ru2->ru_stime); 2878031Sroot if (ru->ru_maxrss < ru2->ru_maxrss) 2888031Sroot ru->ru_maxrss = ru2->ru_maxrss; 2898031Sroot ip = &ru->ru_first; ip2 = &ru2->ru_first; 2908031Sroot for (i = &ru->ru_last - &ru->ru_first; i > 0; i--) 2918031Sroot *ip++ += *ip2++; 2928031Sroot } 29347541Skarels 29447541Skarels /* 29547541Skarels * Make a copy of the plimit structure. 29647541Skarels * We share these structures copy-on-write after fork, 29747541Skarels * and copy when a limit is changed. 29847541Skarels */ 29947541Skarels struct plimit * 30047541Skarels limcopy(lim) 30147541Skarels struct plimit *lim; 30247541Skarels { 30347541Skarels register struct plimit *copy; 30447541Skarels 30547541Skarels MALLOC(copy, struct plimit *, sizeof(struct plimit), 30647541Skarels M_SUBPROC, M_WAITOK); 30747541Skarels bcopy(lim->pl_rlimit, copy->pl_rlimit, 30847541Skarels sizeof(struct rlimit) * RLIM_NLIMITS); 30947541Skarels copy->p_lflags = 0; 31047541Skarels copy->p_refcnt = 1; 31147541Skarels return (copy); 31247541Skarels } 313