1 /*- 2 * Copyright (c) 1982, 1986, 1991, 1993 3 * The Regents of the University of California. All rights reserved. 4 * (c) UNIX System Laboratories, Inc. 5 * All or some portions of this file are derived from material licensed 6 * to the University of California by American Telephone and Telegraph 7 * Co. or Unix System Laboratories, Inc. and are reproduced herein with 8 * the permission of UNIX System Laboratories, Inc. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the University of 21 * California, Berkeley and its contributors. 22 * 4. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 * 38 * @(#)kern_resource.c 8.5 (Berkeley) 1/21/94 39 * $Id: kern_resource.c,v 1.37 1998/05/28 09:30:18 phk Exp $ 40 */ 41 42 #include "opt_compat.h" 43 #include "opt_rlimit.h" 44 45 #include <sys/param.h> 46 #include <sys/systm.h> 47 #include <sys/sysproto.h> 48 #include <sys/kernel.h> 49 #include <sys/file.h> 50 #include <sys/resourcevar.h> 51 #include <sys/malloc.h> 52 #include <sys/proc.h> 53 54 #include <vm/vm.h> 55 #include <vm/vm_param.h> 56 #include <vm/vm_prot.h> 57 #include <sys/lock.h> 58 #include <vm/pmap.h> 59 #include <vm/vm_map.h> 60 61 static int donice __P((struct proc *curp, struct proc *chgp, int n)); 62 static int dosetrlimit __P((struct proc *p, u_int which, struct rlimit *limp)); 63 64 /* 65 * Resource controls and accounting. 66 */ 67 68 #ifndef _SYS_SYSPROTO_H_ 69 struct getpriority_args { 70 int which; 71 int who; 72 }; 73 #endif 74 int 75 getpriority(curp, uap) 76 struct proc *curp; 77 register struct getpriority_args *uap; 78 { 79 register struct proc *p; 80 register int low = PRIO_MAX + 1; 81 82 switch (uap->which) { 83 84 case PRIO_PROCESS: 85 if (uap->who == 0) 86 p = curp; 87 else 88 p = pfind(uap->who); 89 if (p == 0) 90 break; 91 low = p->p_nice; 92 break; 93 94 case PRIO_PGRP: { 95 register struct pgrp *pg; 96 97 if (uap->who == 0) 98 pg = curp->p_pgrp; 99 else if ((pg = pgfind(uap->who)) == NULL) 100 break; 101 for (p = pg->pg_members.lh_first; p != 0; 102 p = p->p_pglist.le_next) { 103 if (p->p_nice < low) 104 low = p->p_nice; 105 } 106 break; 107 } 108 109 case PRIO_USER: 110 if (uap->who == 0) 111 uap->who = curp->p_ucred->cr_uid; 112 for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) 113 if (p->p_ucred->cr_uid == uap->who && 114 p->p_nice < low) 115 low = p->p_nice; 116 break; 117 118 default: 119 return (EINVAL); 120 } 121 if (low == PRIO_MAX + 1) 122 return (ESRCH); 123 curp->p_retval[0] = low; 124 return (0); 125 } 126 127 #ifndef _SYS_SYSPROTO_H_ 128 struct setpriority_args { 129 int which; 130 int who; 131 int prio; 132 }; 133 #endif 134 /* ARGSUSED */ 135 int 136 setpriority(curp, uap) 137 struct proc *curp; 138 register struct setpriority_args *uap; 139 { 140 register struct proc *p; 141 int found = 0, error = 0; 142 143 switch (uap->which) { 144 145 case PRIO_PROCESS: 146 if (uap->who == 0) 147 p = curp; 148 else 149 p = pfind(uap->who); 150 if (p == 0) 151 break; 152 error = donice(curp, p, uap->prio); 153 found++; 154 break; 155 156 case PRIO_PGRP: { 157 register struct pgrp *pg; 158 159 if (uap->who == 0) 160 pg = curp->p_pgrp; 161 else if ((pg = pgfind(uap->who)) == NULL) 162 break; 163 for (p = pg->pg_members.lh_first; p != 0; 164 p = p->p_pglist.le_next) { 165 error = donice(curp, p, uap->prio); 166 found++; 167 } 168 break; 169 } 170 171 case PRIO_USER: 172 if (uap->who == 0) 173 uap->who = curp->p_ucred->cr_uid; 174 for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) 175 if (p->p_ucred->cr_uid == uap->who) { 176 error = donice(curp, p, uap->prio); 177 found++; 178 } 179 break; 180 181 default: 182 return (EINVAL); 183 } 184 if (found == 0) 185 return (ESRCH); 186 return (error); 187 } 188 189 static int 190 donice(curp, chgp, n) 191 register struct proc *curp, *chgp; 192 register int n; 193 { 194 register struct pcred *pcred = curp->p_cred; 195 196 if (pcred->pc_ucred->cr_uid && pcred->p_ruid && 197 pcred->pc_ucred->cr_uid != chgp->p_ucred->cr_uid && 198 pcred->p_ruid != chgp->p_ucred->cr_uid) 199 return (EPERM); 200 if (n > PRIO_MAX) 201 n = PRIO_MAX; 202 if (n < PRIO_MIN) 203 n = PRIO_MIN; 204 if (n < chgp->p_nice && suser(pcred->pc_ucred, &curp->p_acflag)) 205 return (EACCES); 206 chgp->p_nice = n; 207 (void)resetpriority(chgp); 208 return (0); 209 } 210 211 /* rtprio system call */ 212 #ifndef _SYS_SYSPROTO_H_ 213 struct rtprio_args { 214 int function; 215 pid_t pid; 216 struct rtprio *rtp; 217 }; 218 #endif 219 220 /* 221 * Set realtime priority 222 */ 223 224 /* ARGSUSED */ 225 int 226 rtprio(curp, uap) 227 struct proc *curp; 228 register struct rtprio_args *uap; 229 { 230 register struct proc *p; 231 register struct pcred *pcred = curp->p_cred; 232 struct rtprio rtp; 233 int error; 234 235 error = copyin(uap->rtp, &rtp, sizeof(struct rtprio)); 236 if (error) 237 return (error); 238 239 if (uap->pid == 0) 240 p = curp; 241 else 242 p = pfind(uap->pid); 243 244 if (p == 0) 245 return (ESRCH); 246 247 switch (uap->function) { 248 case RTP_LOOKUP: 249 return (copyout(&p->p_rtprio, uap->rtp, sizeof(struct rtprio))); 250 case RTP_SET: 251 if (pcred->pc_ucred->cr_uid && pcred->p_ruid && 252 pcred->pc_ucred->cr_uid != p->p_ucred->cr_uid && 253 pcred->p_ruid != p->p_ucred->cr_uid) 254 return (EPERM); 255 /* disallow setting rtprio in most cases if not superuser */ 256 if (suser(pcred->pc_ucred, &curp->p_acflag)) { 257 /* can't set someone else's */ 258 if (uap->pid) 259 return (EPERM); 260 /* can't set realtime priority */ 261 /* 262 * Realtime priority has to be restricted for reasons which should be 263 * obvious. However, for idle priority, there is a potential for 264 * system deadlock if an idleprio process gains a lock on a resource 265 * that other processes need (and the idleprio process can't run 266 * due to a CPU-bound normal process). Fix me! XXX 267 */ 268 #if 0 269 if (RTP_PRIO_IS_REALTIME(rtp.type)) 270 #endif 271 if (rtp.type != RTP_PRIO_NORMAL) 272 return (EPERM); 273 } 274 switch (rtp.type) { 275 #ifdef RTP_PRIO_FIFO 276 case RTP_PRIO_FIFO: 277 #endif 278 case RTP_PRIO_REALTIME: 279 case RTP_PRIO_NORMAL: 280 case RTP_PRIO_IDLE: 281 if (rtp.prio > RTP_PRIO_MAX) 282 return (EINVAL); 283 p->p_rtprio = rtp; 284 return (0); 285 default: 286 return (EINVAL); 287 } 288 289 default: 290 return (EINVAL); 291 } 292 } 293 294 #if defined(COMPAT_43) || defined(COMPAT_SUNOS) 295 #ifndef _SYS_SYSPROTO_H_ 296 struct osetrlimit_args { 297 u_int which; 298 struct orlimit *rlp; 299 }; 300 #endif 301 /* ARGSUSED */ 302 int 303 osetrlimit(p, uap) 304 struct proc *p; 305 register struct osetrlimit_args *uap; 306 { 307 struct orlimit olim; 308 struct rlimit lim; 309 int error; 310 311 if ((error = 312 copyin((caddr_t)uap->rlp, (caddr_t)&olim, sizeof(struct orlimit)))) 313 return (error); 314 lim.rlim_cur = olim.rlim_cur; 315 lim.rlim_max = olim.rlim_max; 316 return (dosetrlimit(p, uap->which, &lim)); 317 } 318 319 #ifndef _SYS_SYSPROTO_H_ 320 struct ogetrlimit_args { 321 u_int which; 322 struct orlimit *rlp; 323 }; 324 #endif 325 /* ARGSUSED */ 326 int 327 ogetrlimit(p, uap) 328 struct proc *p; 329 register struct ogetrlimit_args *uap; 330 { 331 struct orlimit olim; 332 333 if (uap->which >= RLIM_NLIMITS) 334 return (EINVAL); 335 olim.rlim_cur = p->p_rlimit[uap->which].rlim_cur; 336 if (olim.rlim_cur == -1) 337 olim.rlim_cur = 0x7fffffff; 338 olim.rlim_max = p->p_rlimit[uap->which].rlim_max; 339 if (olim.rlim_max == -1) 340 olim.rlim_max = 0x7fffffff; 341 return (copyout((caddr_t)&olim, (caddr_t)uap->rlp, sizeof(olim))); 342 } 343 #endif /* COMPAT_43 || COMPAT_SUNOS */ 344 345 #ifndef _SYS_SYSPROTO_H_ 346 struct __setrlimit_args { 347 u_int which; 348 struct rlimit *rlp; 349 }; 350 #endif 351 /* ARGSUSED */ 352 int 353 setrlimit(p, uap) 354 struct proc *p; 355 register struct __setrlimit_args *uap; 356 { 357 struct rlimit alim; 358 int error; 359 360 if ((error = 361 copyin((caddr_t)uap->rlp, (caddr_t)&alim, sizeof (struct rlimit)))) 362 return (error); 363 return (dosetrlimit(p, uap->which, &alim)); 364 } 365 366 static int 367 dosetrlimit(p, which, limp) 368 struct proc *p; 369 u_int which; 370 struct rlimit *limp; 371 { 372 register struct rlimit *alimp; 373 int error; 374 375 if (which >= RLIM_NLIMITS) 376 return (EINVAL); 377 alimp = &p->p_rlimit[which]; 378 379 /* 380 * Preserve historical bugs by treating negative limits as unsigned. 381 */ 382 if (limp->rlim_cur < 0) 383 limp->rlim_cur = RLIM_INFINITY; 384 if (limp->rlim_max < 0) 385 limp->rlim_max = RLIM_INFINITY; 386 387 if (limp->rlim_cur > alimp->rlim_max || 388 limp->rlim_max > alimp->rlim_max) 389 if ((error = suser(p->p_ucred, &p->p_acflag))) 390 return (error); 391 if (limp->rlim_cur > limp->rlim_max) 392 limp->rlim_cur = limp->rlim_max; 393 if (p->p_limit->p_refcnt > 1 && 394 (p->p_limit->p_lflags & PL_SHAREMOD) == 0) { 395 p->p_limit->p_refcnt--; 396 p->p_limit = limcopy(p->p_limit); 397 alimp = &p->p_rlimit[which]; 398 } 399 400 switch (which) { 401 402 case RLIMIT_CPU: 403 if (limp->rlim_cur > RLIM_INFINITY / (rlim_t)1000000) 404 p->p_limit->p_cpulimit = RLIM_INFINITY; 405 else 406 p->p_limit->p_cpulimit = 407 (rlim_t)1000000 * limp->rlim_cur; 408 break; 409 case RLIMIT_DATA: 410 if (limp->rlim_cur > MAXDSIZ) 411 limp->rlim_cur = MAXDSIZ; 412 if (limp->rlim_max > MAXDSIZ) 413 limp->rlim_max = MAXDSIZ; 414 break; 415 416 case RLIMIT_STACK: 417 if (limp->rlim_cur > MAXSSIZ) 418 limp->rlim_cur = MAXSSIZ; 419 if (limp->rlim_max > MAXSSIZ) 420 limp->rlim_max = MAXSSIZ; 421 /* 422 * Stack is allocated to the max at exec time with only 423 * "rlim_cur" bytes accessible. If stack limit is going 424 * up make more accessible, if going down make inaccessible. 425 */ 426 if (limp->rlim_cur != alimp->rlim_cur) { 427 vm_offset_t addr; 428 vm_size_t size; 429 vm_prot_t prot; 430 431 if (limp->rlim_cur > alimp->rlim_cur) { 432 prot = VM_PROT_ALL; 433 size = limp->rlim_cur - alimp->rlim_cur; 434 addr = USRSTACK - limp->rlim_cur; 435 } else { 436 prot = VM_PROT_NONE; 437 size = alimp->rlim_cur - limp->rlim_cur; 438 addr = USRSTACK - alimp->rlim_cur; 439 } 440 addr = trunc_page(addr); 441 size = round_page(size); 442 (void) vm_map_protect(&p->p_vmspace->vm_map, 443 addr, addr+size, prot, FALSE); 444 } 445 break; 446 447 case RLIMIT_NOFILE: 448 if (limp->rlim_cur > maxfilesperproc) 449 limp->rlim_cur = maxfilesperproc; 450 if (limp->rlim_max > maxfilesperproc) 451 limp->rlim_max = maxfilesperproc; 452 break; 453 454 case RLIMIT_NPROC: 455 if (limp->rlim_cur > maxprocperuid) 456 limp->rlim_cur = maxprocperuid; 457 if (limp->rlim_max > maxprocperuid) 458 limp->rlim_max = maxprocperuid; 459 break; 460 } 461 *alimp = *limp; 462 return (0); 463 } 464 465 #ifndef _SYS_SYSPROTO_H_ 466 struct __getrlimit_args { 467 u_int which; 468 struct rlimit *rlp; 469 }; 470 #endif 471 /* ARGSUSED */ 472 int 473 getrlimit(p, uap) 474 struct proc *p; 475 register struct __getrlimit_args *uap; 476 { 477 478 if (uap->which >= RLIM_NLIMITS) 479 return (EINVAL); 480 return (copyout((caddr_t)&p->p_rlimit[uap->which], (caddr_t)uap->rlp, 481 sizeof (struct rlimit))); 482 } 483 484 /* 485 * Transform the running time and tick information in proc p into user, 486 * system, and interrupt time usage. 487 */ 488 void 489 calcru(p, up, sp, ip) 490 struct proc *p; 491 struct timeval *up; 492 struct timeval *sp; 493 struct timeval *ip; 494 { 495 int64_t totusec; 496 u_int64_t u, st, ut, it, tot; 497 int s; 498 struct timeval tv; 499 500 /* XXX: why spl-protect ? worst case is an off-by-one report */ 501 s = splstatclock(); 502 st = p->p_sticks; 503 ut = p->p_uticks; 504 it = p->p_iticks; 505 splx(s); 506 507 tot = st + ut + it; 508 if (tot == 0) { 509 st = 1; 510 tot = 1; 511 } 512 513 totusec = p->p_runtime; 514 #ifdef SMP 515 if (p->p_oncpu != (char)0xff) { 516 #else 517 if (p == curproc) { 518 #endif 519 /* 520 * Adjust for the current time slice. This is actually fairly 521 * important since the error here is on the order of a time 522 * quantum, which is much greater than the sampling error. 523 */ 524 microuptime(&tv); 525 totusec += (tv.tv_usec - p->p_switchtime.tv_usec) + 526 (tv.tv_sec - p->p_switchtime.tv_sec) * (int64_t)1000000; 527 528 /* 529 * Copy the time that was just read to `switchtime' in case 530 * we are being called from exit1(). Exits don't go through 531 * mi_switch(), so `switchtime' doesn't get set in the normal 532 * way. We set it here instead of more cleanly in exit1() 533 * to avoid losing track of the time between the calls to 534 * microuptime(). 535 */ 536 switchtime = tv; 537 } 538 if (totusec < 0) { 539 /* XXX no %qd in kernel. Truncate. */ 540 printf("calcru: negative time of %ld usec for pid %d (%s)\n", 541 (long)totusec, p->p_pid, p->p_comm); 542 totusec = 0; 543 } 544 u = totusec; 545 st = (u * st) / tot; 546 sp->tv_sec = st / 1000000; 547 sp->tv_usec = st % 1000000; 548 ut = (u * ut) / tot; 549 up->tv_sec = ut / 1000000; 550 up->tv_usec = ut % 1000000; 551 if (ip != NULL) { 552 it = (u * it) / tot; 553 ip->tv_sec = it / 1000000; 554 ip->tv_usec = it % 1000000; 555 } 556 } 557 558 #ifndef _SYS_SYSPROTO_H_ 559 struct getrusage_args { 560 int who; 561 struct rusage *rusage; 562 }; 563 #endif 564 /* ARGSUSED */ 565 int 566 getrusage(p, uap) 567 register struct proc *p; 568 register struct getrusage_args *uap; 569 { 570 register struct rusage *rup; 571 572 switch (uap->who) { 573 574 case RUSAGE_SELF: 575 rup = &p->p_stats->p_ru; 576 calcru(p, &rup->ru_utime, &rup->ru_stime, NULL); 577 break; 578 579 case RUSAGE_CHILDREN: 580 rup = &p->p_stats->p_cru; 581 break; 582 583 default: 584 return (EINVAL); 585 } 586 return (copyout((caddr_t)rup, (caddr_t)uap->rusage, 587 sizeof (struct rusage))); 588 } 589 590 void 591 ruadd(ru, ru2) 592 register struct rusage *ru, *ru2; 593 { 594 register long *ip, *ip2; 595 register int i; 596 597 timevaladd(&ru->ru_utime, &ru2->ru_utime); 598 timevaladd(&ru->ru_stime, &ru2->ru_stime); 599 if (ru->ru_maxrss < ru2->ru_maxrss) 600 ru->ru_maxrss = ru2->ru_maxrss; 601 ip = &ru->ru_first; ip2 = &ru2->ru_first; 602 for (i = &ru->ru_last - &ru->ru_first; i >= 0; i--) 603 *ip++ += *ip2++; 604 } 605 606 /* 607 * Make a copy of the plimit structure. 608 * We share these structures copy-on-write after fork, 609 * and copy when a limit is changed. 610 */ 611 struct plimit * 612 limcopy(lim) 613 struct plimit *lim; 614 { 615 register struct plimit *copy; 616 617 MALLOC(copy, struct plimit *, sizeof(struct plimit), 618 M_SUBPROC, M_WAITOK); 619 bcopy(lim->pl_rlimit, copy->pl_rlimit, sizeof(struct plimit)); 620 copy->p_lflags = 0; 621 copy->p_refcnt = 1; 622 return (copy); 623 } 624