1 /*- 2 * Copyright (c) 1982, 1986, 1991 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * 7 * @(#)kern_resource.c 7.21 (Berkeley) 07/10/92 8 */ 9 10 #include "param.h" 11 #include "kernel.h" 12 #include "resourcevar.h" 13 #include "malloc.h" 14 #include "proc.h" 15 16 #include "vm/vm.h" 17 18 /* 19 * Resource controls and accounting. 20 */ 21 22 struct getpriority_args { 23 int which; 24 int who; 25 }; 26 getpriority(curp, uap, retval) 27 struct proc *curp; 28 register struct getpriority_args *uap; 29 int *retval; 30 { 31 register struct proc *p; 32 register int low = PRIO_MAX + 1; 33 34 switch (uap->which) { 35 36 case PRIO_PROCESS: 37 if (uap->who == 0) 38 p = curp; 39 else 40 p = pfind(uap->who); 41 if (p == 0) 42 break; 43 low = p->p_nice; 44 break; 45 46 case PRIO_PGRP: { 47 register struct pgrp *pg; 48 49 if (uap->who == 0) 50 pg = curp->p_pgrp; 51 else if ((pg = pgfind(uap->who)) == NULL) 52 break; 53 for (p = pg->pg_mem; p != NULL; p = p->p_pgrpnxt) { 54 if (p->p_nice < low) 55 low = p->p_nice; 56 } 57 break; 58 } 59 60 case PRIO_USER: 61 if (uap->who == 0) 62 uap->who = curp->p_ucred->cr_uid; 63 for (p = (struct proc *)allproc; p != NULL; p = p->p_nxt) { 64 if (p->p_ucred->cr_uid == uap->who && 65 p->p_nice < low) 66 low = p->p_nice; 67 } 68 break; 69 70 default: 71 return (EINVAL); 72 } 73 if (low == PRIO_MAX + 1) 74 return (ESRCH); 75 *retval = low; 76 return (0); 77 } 78 79 struct setpriority_args { 80 int which; 81 int who; 82 int prio; 83 }; 84 /* ARGSUSED */ 85 setpriority(curp, uap, retval) 86 struct proc *curp; 87 register struct setpriority_args *uap; 88 int *retval; 89 { 90 register struct proc *p; 91 int found = 0, error = 0; 92 93 switch (uap->which) { 94 95 case PRIO_PROCESS: 96 if (uap->who == 0) 97 p = curp; 98 else 99 p = pfind(uap->who); 100 if (p == 0) 101 break; 102 error = donice(curp, p, uap->prio); 103 found++; 104 break; 105 106 case PRIO_PGRP: { 107 register struct pgrp *pg; 108 109 if (uap->who == 0) 110 pg = curp->p_pgrp; 111 else if ((pg = pgfind(uap->who)) == NULL) 112 break; 113 for (p = pg->pg_mem; p != NULL; p = p->p_pgrpnxt) { 114 error = donice(curp, p, uap->prio); 115 found++; 116 } 117 break; 118 } 119 120 case PRIO_USER: 121 if (uap->who == 0) 122 uap->who = curp->p_ucred->cr_uid; 123 for (p = (struct proc *)allproc; p != NULL; p = p->p_nxt) 124 if (p->p_ucred->cr_uid == uap->who) { 125 error = donice(curp, p, uap->prio); 126 found++; 127 } 128 break; 129 130 default: 131 return (EINVAL); 132 } 133 if (found == 0) 134 return (ESRCH); 135 return (0); 136 } 137 138 donice(curp, chgp, n) 139 register struct proc *curp, *chgp; 140 register int n; 141 { 142 register struct pcred *pcred = curp->p_cred; 143 144 if (pcred->pc_ucred->cr_uid && pcred->p_ruid && 145 pcred->pc_ucred->cr_uid != chgp->p_ucred->cr_uid && 146 pcred->p_ruid != chgp->p_ucred->cr_uid) 147 return (EPERM); 148 if (n > PRIO_MAX) 149 n = PRIO_MAX; 150 if (n < PRIO_MIN) 151 n = PRIO_MIN; 152 if (n < chgp->p_nice && suser(pcred->pc_ucred, &curp->p_acflag)) 153 return (EACCES); 154 chgp->p_nice = n; 155 (void) setpri(chgp); 156 return (0); 157 } 158 159 #if defined(COMPAT_43) || defined(COMPAT_SUNOS) 160 struct setrlimit_args { 161 u_int which; 162 struct orlimit *lim; 163 }; 164 /* ARGSUSED */ 165 setrlimit(p, uap, retval) 166 struct proc *p; 167 register struct setrlimit_args *uap; 168 int *retval; 169 { 170 struct orlimit olim; 171 struct rlimit lim; 172 int error; 173 174 if (error = 175 copyin((caddr_t)uap->lim, (caddr_t)&olim, sizeof (struct orlimit))) 176 return (error); 177 lim.rlim_cur = olim.rlim_cur; 178 lim.rlim_max = olim.rlim_max; 179 return (dosetrlimit(p, uap->which, &lim)); 180 } 181 182 struct getrlimit_args { 183 u_int which; 184 struct orlimit *rlp; 185 }; 186 /* ARGSUSED */ 187 getrlimit(p, uap, retval) 188 struct proc *p; 189 register struct getrlimit_args *uap; 190 int *retval; 191 { 192 struct orlimit olim; 193 194 if (uap->which >= RLIM_NLIMITS) 195 return (EINVAL); 196 olim.rlim_cur = p->p_rlimit[uap->which].rlim_cur; 197 if (olim.rlim_cur == -1) 198 olim.rlim_cur = 0x7fffffff; 199 olim.rlim_max = p->p_rlimit[uap->which].rlim_max; 200 if (olim.rlim_max == -1) 201 olim.rlim_max = 0x7fffffff; 202 return (copyout((caddr_t)&olim, (caddr_t)uap->rlp, sizeof(olim))); 203 } 204 #endif /* COMPAT_43 || COMPAT_SUNOS */ 205 206 struct __setrlimit_args { 207 u_int which; 208 struct rlimit *lim; 209 }; 210 /* ARGSUSED */ 211 __setrlimit(p, uap, retval) 212 struct proc *p; 213 register struct __setrlimit_args *uap; 214 int *retval; 215 { 216 struct rlimit alim; 217 int error; 218 219 if (error = 220 copyin((caddr_t)uap->lim, (caddr_t)&alim, sizeof (struct rlimit))) 221 return (error); 222 return (dosetrlimit(p, uap->which, &alim)); 223 } 224 225 dosetrlimit(p, which, limp) 226 struct proc *p; 227 u_int which; 228 struct rlimit *limp; 229 { 230 register struct rlimit *alimp; 231 extern unsigned maxdmap; 232 int error; 233 234 if (which >= RLIM_NLIMITS) 235 return (EINVAL); 236 alimp = &p->p_rlimit[which]; 237 if (limp->rlim_cur > alimp->rlim_max || 238 limp->rlim_max > alimp->rlim_max) 239 if (error = suser(p->p_ucred, &p->p_acflag)) 240 return (error); 241 if (limp->rlim_cur > limp->rlim_max) 242 limp->rlim_cur = limp->rlim_max; 243 if (p->p_limit->p_refcnt > 1 && 244 (p->p_limit->p_lflags & PL_SHAREMOD) == 0) { 245 p->p_limit->p_refcnt--; 246 p->p_limit = limcopy(p->p_limit); 247 alimp = &p->p_rlimit[which]; 248 } 249 250 switch (which) { 251 252 case RLIMIT_DATA: 253 if (limp->rlim_cur > maxdmap) 254 limp->rlim_cur = maxdmap; 255 if (limp->rlim_max > maxdmap) 256 limp->rlim_max = maxdmap; 257 break; 258 259 case RLIMIT_STACK: 260 if (limp->rlim_cur > maxdmap) 261 limp->rlim_cur = maxdmap; 262 if (limp->rlim_max > maxdmap) 263 limp->rlim_max = maxdmap; 264 /* 265 * Stack is allocated to the max at exec time with only 266 * "rlim_cur" bytes accessible. If stack limit is going 267 * up make more accessible, if going down make inaccessible. 268 */ 269 if (limp->rlim_cur != alimp->rlim_cur) { 270 vm_offset_t addr; 271 vm_size_t size; 272 vm_prot_t prot; 273 274 if (limp->rlim_cur > alimp->rlim_cur) { 275 prot = VM_PROT_ALL; 276 size = limp->rlim_cur - alimp->rlim_cur; 277 addr = USRSTACK - limp->rlim_cur; 278 } else { 279 prot = VM_PROT_NONE; 280 size = alimp->rlim_cur - limp->rlim_cur; 281 addr = USRSTACK - alimp->rlim_cur; 282 } 283 addr = trunc_page(addr); 284 size = round_page(size); 285 (void) vm_map_protect(&p->p_vmspace->vm_map, 286 addr, addr+size, prot, FALSE); 287 } 288 break; 289 } 290 *alimp = *limp; 291 return (0); 292 } 293 294 struct __getrlimit_args { 295 u_int which; 296 struct rlimit *rlp; 297 }; 298 /* ARGSUSED */ 299 __getrlimit(p, uap, retval) 300 struct proc *p; 301 register struct __getrlimit_args *uap; 302 int *retval; 303 { 304 305 if (uap->which >= RLIM_NLIMITS) 306 return (EINVAL); 307 return (copyout((caddr_t)&p->p_rlimit[uap->which], (caddr_t)uap->rlp, 308 sizeof (struct rlimit))); 309 } 310 311 /* 312 * Transform the running time and tick information in proc p into user, 313 * system, and interrupt time usage. 314 */ 315 calcru(p, up, sp, ip) 316 register struct proc *p; 317 register struct timeval *up; 318 register struct timeval *sp; 319 register struct timeval *ip; 320 { 321 register u_quad_t u, st, ut, it, tot; 322 register u_long sec, usec; 323 register int s; 324 struct timeval tv; 325 326 s = splstatclock(); 327 st = p->p_sticks; 328 ut = p->p_uticks; 329 it = p->p_iticks; 330 splx(s); 331 332 tot = st + ut + it; 333 if (tot == 0) { 334 up->tv_sec = up->tv_usec = 0; 335 sp->tv_sec = sp->tv_usec = 0; 336 if (ip != NULL) 337 ip->tv_sec = ip->tv_usec = 0; 338 return; 339 } 340 341 sec = p->p_rtime.tv_sec; 342 usec = p->p_rtime.tv_usec; 343 if (p == curproc) { 344 /* 345 * Adjust for the current time slice. This is actually fairly 346 * important since the error here is on the order of a time 347 * quantum, which is much greater than the sampling error. 348 */ 349 microtime(&tv); 350 sec += tv.tv_sec - runtime.tv_sec; 351 usec += tv.tv_usec - runtime.tv_usec; 352 } 353 u = sec * 1000000 + usec; 354 st = (u * st) / tot; 355 sp->tv_sec = st / 1000000; 356 sp->tv_usec = st % 1000000; 357 ut = (u * ut) / tot; 358 up->tv_sec = ut / 1000000; 359 up->tv_usec = ut % 1000000; 360 if (ip != NULL) { 361 it = (u * it) / tot; 362 ip->tv_sec = it / 1000000; 363 ip->tv_usec = it % 1000000; 364 } 365 } 366 367 struct getrusage_args { 368 int who; 369 struct rusage *rusage; 370 }; 371 /* ARGSUSED */ 372 getrusage(p, uap, retval) 373 register struct proc *p; 374 register struct getrusage_args *uap; 375 int *retval; 376 { 377 register struct rusage *rup; 378 379 switch (uap->who) { 380 381 case RUSAGE_SELF: 382 rup = &p->p_stats->p_ru; 383 calcru(p, &rup->ru_utime, &rup->ru_stime, NULL); 384 break; 385 386 case RUSAGE_CHILDREN: 387 rup = &p->p_stats->p_cru; 388 break; 389 390 default: 391 return (EINVAL); 392 } 393 return (copyout((caddr_t)rup, (caddr_t)uap->rusage, 394 sizeof (struct rusage))); 395 } 396 397 ruadd(ru, ru2) 398 register struct rusage *ru, *ru2; 399 { 400 register long *ip, *ip2; 401 register int i; 402 403 timevaladd(&ru->ru_utime, &ru2->ru_utime); 404 timevaladd(&ru->ru_stime, &ru2->ru_stime); 405 if (ru->ru_maxrss < ru2->ru_maxrss) 406 ru->ru_maxrss = ru2->ru_maxrss; 407 ip = &ru->ru_first; ip2 = &ru2->ru_first; 408 for (i = &ru->ru_last - &ru->ru_first; i >= 0; i--) 409 *ip++ += *ip2++; 410 } 411 412 /* 413 * Make a copy of the plimit structure. 414 * We share these structures copy-on-write after fork, 415 * and copy when a limit is changed. 416 */ 417 struct plimit * 418 limcopy(lim) 419 struct plimit *lim; 420 { 421 register struct plimit *copy; 422 423 MALLOC(copy, struct plimit *, sizeof(struct plimit), 424 M_SUBPROC, M_WAITOK); 425 bcopy(lim->pl_rlimit, copy->pl_rlimit, 426 sizeof(struct rlimit) * RLIM_NLIMITS); 427 copy->p_lflags = 0; 428 copy->p_refcnt = 1; 429 return (copy); 430 } 431