1 /* 2 * Copyright (c) 1982, 1986 Regents of the University of California. 3 * All rights reserved. The Berkeley software License Agreement 4 * specifies the terms and conditions for redistribution. 5 * 6 * @(#)kern_resource.c 7.12 (Berkeley) 05/07/91 7 */ 8 9 #include "param.h" 10 #include "resourcevar.h" 11 #include "malloc.h" 12 #include "proc.h" 13 14 #include "vm/vm.h" 15 16 /* 17 * Resource controls and accounting. 18 */ 19 20 getpriority(curp, uap, retval) 21 struct proc *curp; 22 register struct args { 23 int which; 24 int who; 25 } *uap; 26 int *retval; 27 { 28 register struct proc *p; 29 register int low = PRIO_MAX + 1; 30 31 switch (uap->which) { 32 33 case PRIO_PROCESS: 34 if (uap->who == 0) 35 p = curp; 36 else 37 p = pfind(uap->who); 38 if (p == 0) 39 break; 40 low = p->p_nice; 41 break; 42 43 case PRIO_PGRP: { 44 register struct pgrp *pg; 45 46 if (uap->who == 0) 47 pg = curp->p_pgrp; 48 else if ((pg = pgfind(uap->who)) == NULL) 49 break; 50 for (p = pg->pg_mem; p != NULL; p = p->p_pgrpnxt) { 51 if (p->p_nice < low) 52 low = p->p_nice; 53 } 54 break; 55 } 56 57 case PRIO_USER: 58 if (uap->who == 0) 59 uap->who = curp->p_ucred->cr_uid; 60 for (p = allproc; p != NULL; p = p->p_nxt) { 61 if (p->p_ucred->cr_uid == uap->who && 62 p->p_nice < low) 63 low = p->p_nice; 64 } 65 break; 66 67 default: 68 return (EINVAL); 69 } 70 if (low == PRIO_MAX + 1) 71 return (ESRCH); 72 *retval = low; 73 return (0); 74 } 75 76 /* ARGSUSED */ 77 setpriority(curp, uap, retval) 78 struct proc *curp; 79 register struct args { 80 int which; 81 int who; 82 int prio; 83 } *uap; 84 int *retval; 85 { 86 register struct proc *p; 87 int found = 0, error = 0; 88 89 switch (uap->which) { 90 91 case PRIO_PROCESS: 92 if (uap->who == 0) 93 p = curp; 94 else 95 p = pfind(uap->who); 96 if (p == 0) 97 break; 98 error = donice(curp, p, uap->prio); 99 found++; 100 break; 101 102 case PRIO_PGRP: { 103 register struct pgrp *pg; 104 105 if (uap->who == 0) 106 pg = curp->p_pgrp; 107 else if ((pg = pgfind(uap->who)) == NULL) 108 break; 109 for (p = pg->pg_mem; p != NULL; p = p->p_pgrpnxt) { 110 error = donice(curp, p, uap->prio); 111 found++; 112 } 113 break; 114 } 115 116 case PRIO_USER: 117 if (uap->who == 0) 118 uap->who = curp->p_ucred->cr_uid; 119 for (p = allproc; p != NULL; p = p->p_nxt) 120 if (p->p_ucred->cr_uid == uap->who) { 121 error = donice(curp, p, uap->prio); 122 found++; 123 } 124 break; 125 126 default: 127 return (EINVAL); 128 } 129 if (found == 0) 130 return (ESRCH); 131 return (0); 132 } 133 134 donice(curp, chgp, n) 135 register struct proc *curp, *chgp; 136 register int n; 137 { 138 register struct pcred *pcred = curp->p_cred; 139 140 if (pcred->pc_ucred->cr_uid && pcred->p_ruid && 141 pcred->pc_ucred->cr_uid != chgp->p_ucred->cr_uid && 142 pcred->p_ruid != chgp->p_ucred->cr_uid) 143 return (EPERM); 144 if (n > PRIO_MAX) 145 n = PRIO_MAX; 146 if (n < PRIO_MIN) 147 n = PRIO_MIN; 148 if (n < chgp->p_nice && suser(pcred->pc_ucred, &curp->p_acflag)) 149 return (EACCES); 150 chgp->p_nice = n; 151 (void) setpri(chgp); 152 return (0); 153 } 154 155 /* ARGSUSED */ 156 setrlimit(p, uap, retval) 157 struct proc *p; 158 register struct args { 159 u_int which; 160 struct rlimit *lim; 161 } *uap; 162 int *retval; 163 { 164 struct rlimit alim; 165 register struct rlimit *alimp; 166 extern unsigned maxdmap; 167 int error; 168 169 if (uap->which >= RLIM_NLIMITS) 170 return (EINVAL); 171 alimp = &p->p_rlimit[uap->which]; 172 if (error = 173 copyin((caddr_t)uap->lim, (caddr_t)&alim, sizeof (struct rlimit))) 174 return (error); 175 if (alim.rlim_cur > alimp->rlim_max || alim.rlim_max > alimp->rlim_max) 176 if (error = suser(p->p_ucred, &p->p_acflag)) 177 return (error); 178 if (p->p_limit->p_refcnt > 1 && 179 (p->p_limit->p_lflags & PL_SHAREMOD) == 0) { 180 p->p_limit->p_refcnt--; 181 p->p_limit = limcopy(p->p_limit); 182 } 183 184 switch (uap->which) { 185 186 case RLIMIT_DATA: 187 if (alim.rlim_cur > maxdmap) 188 alim.rlim_cur = maxdmap; 189 if (alim.rlim_max > maxdmap) 190 alim.rlim_max = maxdmap; 191 break; 192 193 case RLIMIT_STACK: 194 if (alim.rlim_cur > maxdmap) 195 alim.rlim_cur = maxdmap; 196 if (alim.rlim_max > maxdmap) 197 alim.rlim_max = maxdmap; 198 /* 199 * Stack is allocated to the max at exec time with only 200 * "rlim_cur" bytes accessible. If stack limit is going 201 * up make more accessible, if going down make inaccessible. 202 */ 203 if (alim.rlim_cur != alimp->rlim_cur) { 204 vm_offset_t addr; 205 vm_size_t size; 206 vm_prot_t prot; 207 208 if (alim.rlim_cur > alimp->rlim_cur) { 209 prot = VM_PROT_ALL; 210 size = alim.rlim_cur - alimp->rlim_cur; 211 addr = USRSTACK - alim.rlim_cur; 212 } else { 213 prot = VM_PROT_NONE; 214 size = alimp->rlim_cur - alim.rlim_cur; 215 addr = USRSTACK - alimp->rlim_cur; 216 } 217 addr = trunc_page(addr); 218 size = round_page(size); 219 (void) vm_map_protect(&p->p_vmspace->vm_map, 220 addr, addr+size, prot, FALSE); 221 } 222 break; 223 } 224 p->p_rlimit[uap->which] = alim; 225 return (0); 226 } 227 228 /* ARGSUSED */ 229 getrlimit(p, uap, retval) 230 struct proc *p; 231 register struct args { 232 u_int which; 233 struct rlimit *rlp; 234 } *uap; 235 int *retval; 236 { 237 238 if (uap->which >= RLIM_NLIMITS) 239 return (EINVAL); 240 return (copyout((caddr_t)&p->p_rlimit[uap->which], (caddr_t)uap->rlp, 241 sizeof (struct rlimit))); 242 } 243 244 /* ARGSUSED */ 245 getrusage(p, uap, retval) 246 register struct proc *p; 247 register struct args { 248 int who; 249 struct rusage *rusage; 250 } *uap; 251 int *retval; 252 { 253 register struct rusage *rup; 254 255 switch (uap->who) { 256 257 case RUSAGE_SELF: { 258 int s; 259 260 rup = &p->p_stats->p_ru; 261 s = splclock(); 262 rup->ru_stime = p->p_stime; 263 rup->ru_utime = p->p_utime; 264 splx(s); 265 break; 266 } 267 268 case RUSAGE_CHILDREN: 269 rup = &p->p_stats->p_cru; 270 break; 271 272 default: 273 return (EINVAL); 274 } 275 return (copyout((caddr_t)rup, (caddr_t)uap->rusage, 276 sizeof (struct rusage))); 277 } 278 279 ruadd(ru, ru2) 280 register struct rusage *ru, *ru2; 281 { 282 register long *ip, *ip2; 283 register int i; 284 285 timevaladd(&ru->ru_utime, &ru2->ru_utime); 286 timevaladd(&ru->ru_stime, &ru2->ru_stime); 287 if (ru->ru_maxrss < ru2->ru_maxrss) 288 ru->ru_maxrss = ru2->ru_maxrss; 289 ip = &ru->ru_first; ip2 = &ru2->ru_first; 290 for (i = &ru->ru_last - &ru->ru_first; i > 0; i--) 291 *ip++ += *ip2++; 292 } 293 294 /* 295 * Make a copy of the plimit structure. 296 * We share these structures copy-on-write after fork, 297 * and copy when a limit is changed. 298 */ 299 struct plimit * 300 limcopy(lim) 301 struct plimit *lim; 302 { 303 register struct plimit *copy; 304 305 MALLOC(copy, struct plimit *, sizeof(struct plimit), 306 M_SUBPROC, M_WAITOK); 307 bcopy(lim->pl_rlimit, copy->pl_rlimit, 308 sizeof(struct rlimit) * RLIM_NLIMITS); 309 copy->p_lflags = 0; 310 copy->p_refcnt = 1; 311 return (copy); 312 } 313