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.19 1996/03/11 06:04:20 hsu Exp $ 40 */ 41 42 #include <sys/param.h> 43 #include <sys/systm.h> 44 #include <sys/sysproto.h> 45 #include <sys/kernel.h> 46 #include <sys/file.h> 47 #include <sys/resourcevar.h> 48 #include <sys/malloc.h> 49 #include <sys/proc.h> 50 51 #include <vm/vm.h> 52 #include <vm/vm_param.h> 53 #include <vm/vm_prot.h> 54 #include <vm/lock.h> 55 #include <vm/pmap.h> 56 #include <vm/vm_map.h> 57 58 int donice __P((struct proc *curp, struct proc *chgp, int n)); 59 int dosetrlimit __P((struct proc *p, u_int which, struct rlimit *limp)); 60 61 /* 62 * Resource controls and accounting. 63 */ 64 65 #ifndef _SYS_SYSPROTO_H_ 66 struct getpriority_args { 67 int which; 68 int who; 69 }; 70 #endif 71 int 72 getpriority(curp, uap, retval) 73 struct proc *curp; 74 register struct getpriority_args *uap; 75 int *retval; 76 { 77 register struct proc *p; 78 register int low = PRIO_MAX + 1; 79 80 switch (uap->which) { 81 82 case PRIO_PROCESS: 83 if (uap->who == 0) 84 p = curp; 85 else 86 p = pfind(uap->who); 87 if (p == 0) 88 break; 89 low = p->p_nice; 90 break; 91 92 case PRIO_PGRP: { 93 register struct pgrp *pg; 94 95 if (uap->who == 0) 96 pg = curp->p_pgrp; 97 else if ((pg = pgfind(uap->who)) == NULL) 98 break; 99 for (p = pg->pg_members.lh_first; p != 0; 100 p = p->p_pglist.le_next) { 101 if (p->p_nice < low) 102 low = p->p_nice; 103 } 104 break; 105 } 106 107 case PRIO_USER: 108 if (uap->who == 0) 109 uap->who = curp->p_ucred->cr_uid; 110 for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) 111 if (p->p_ucred->cr_uid == uap->who && 112 p->p_nice < low) 113 low = p->p_nice; 114 break; 115 116 default: 117 return (EINVAL); 118 } 119 if (low == PRIO_MAX + 1) 120 return (ESRCH); 121 *retval = low; 122 return (0); 123 } 124 125 #ifndef _SYS_SYSPROTO_H_ 126 struct setpriority_args { 127 int which; 128 int who; 129 int prio; 130 }; 131 #endif 132 /* ARGSUSED */ 133 int 134 setpriority(curp, uap, retval) 135 struct proc *curp; 136 register struct setpriority_args *uap; 137 int *retval; 138 { 139 register struct proc *p; 140 int found = 0, error = 0; 141 142 switch (uap->which) { 143 144 case PRIO_PROCESS: 145 if (uap->who == 0) 146 p = curp; 147 else 148 p = pfind(uap->who); 149 if (p == 0) 150 break; 151 error = donice(curp, p, uap->prio); 152 found++; 153 break; 154 155 case PRIO_PGRP: { 156 register struct pgrp *pg; 157 158 if (uap->who == 0) 159 pg = curp->p_pgrp; 160 else if ((pg = pgfind(uap->who)) == NULL) 161 break; 162 for (p = pg->pg_members.lh_first; p != 0; 163 p = p->p_pglist.le_next) { 164 error = donice(curp, p, uap->prio); 165 found++; 166 } 167 break; 168 } 169 170 case PRIO_USER: 171 if (uap->who == 0) 172 uap->who = curp->p_ucred->cr_uid; 173 for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) 174 if (p->p_ucred->cr_uid == uap->who) { 175 error = donice(curp, p, uap->prio); 176 found++; 177 } 178 break; 179 180 default: 181 return (EINVAL); 182 } 183 if (found == 0) 184 return (ESRCH); 185 return (error); 186 } 187 188 int 189 donice(curp, chgp, n) 190 register struct proc *curp, *chgp; 191 register int n; 192 { 193 register struct pcred *pcred = curp->p_cred; 194 195 if (pcred->pc_ucred->cr_uid && pcred->p_ruid && 196 pcred->pc_ucred->cr_uid != chgp->p_ucred->cr_uid && 197 pcred->p_ruid != chgp->p_ucred->cr_uid) 198 return (EPERM); 199 if (n > PRIO_MAX) 200 n = PRIO_MAX; 201 if (n < PRIO_MIN) 202 n = PRIO_MIN; 203 if (n < chgp->p_nice && suser(pcred->pc_ucred, &curp->p_acflag)) 204 return (EACCES); 205 chgp->p_nice = n; 206 (void)resetpriority(chgp); 207 return (0); 208 } 209 210 /* rtprio system call */ 211 #ifndef _SYS_SYSPROTO_H_ 212 struct rtprio_args { 213 int function; 214 pid_t pid; 215 struct rtprio *rtp; 216 }; 217 #endif 218 219 /* 220 * Set realtime priority 221 */ 222 223 /* ARGSUSED */ 224 int 225 rtprio(curp, uap, retval) 226 struct proc *curp; 227 register struct rtprio_args *uap; 228 int *retval; 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 if (rtp.type == RTP_PRIO_REALTIME) 262 return (EPERM); 263 } 264 switch (rtp.type) { 265 case RTP_PRIO_REALTIME: 266 case RTP_PRIO_NORMAL: 267 case RTP_PRIO_IDLE: 268 if (rtp.prio > RTP_PRIO_MAX) 269 return (EINVAL); 270 p->p_rtprio = rtp; 271 return (0); 272 default: 273 return (EINVAL); 274 } 275 276 default: 277 return (EINVAL); 278 } 279 } 280 281 #if defined(COMPAT_43) || defined(COMPAT_SUNOS) 282 #ifndef _SYS_SYSPROTO_H_ 283 struct osetrlimit_args { 284 u_int which; 285 struct orlimit *rlp; 286 }; 287 #endif 288 /* ARGSUSED */ 289 int 290 osetrlimit(p, uap, retval) 291 struct proc *p; 292 register struct osetrlimit_args *uap; 293 int *retval; 294 { 295 struct orlimit olim; 296 struct rlimit lim; 297 int error; 298 299 if ((error = 300 copyin((caddr_t)uap->rlp, (caddr_t)&olim, sizeof(struct orlimit)))) 301 return (error); 302 lim.rlim_cur = olim.rlim_cur; 303 lim.rlim_max = olim.rlim_max; 304 return (dosetrlimit(p, uap->which, &lim)); 305 } 306 307 #ifndef _SYS_SYSPROTO_H_ 308 struct ogetrlimit_args { 309 u_int which; 310 struct orlimit *rlp; 311 }; 312 #endif 313 /* ARGSUSED */ 314 int 315 ogetrlimit(p, uap, retval) 316 struct proc *p; 317 register struct ogetrlimit_args *uap; 318 int *retval; 319 { 320 struct orlimit olim; 321 322 if (uap->which >= RLIM_NLIMITS) 323 return (EINVAL); 324 olim.rlim_cur = p->p_rlimit[uap->which].rlim_cur; 325 if (olim.rlim_cur == -1) 326 olim.rlim_cur = 0x7fffffff; 327 olim.rlim_max = p->p_rlimit[uap->which].rlim_max; 328 if (olim.rlim_max == -1) 329 olim.rlim_max = 0x7fffffff; 330 return (copyout((caddr_t)&olim, (caddr_t)uap->rlp, sizeof(olim))); 331 } 332 #endif /* COMPAT_43 || COMPAT_SUNOS */ 333 334 #ifndef _SYS_SYSPROTO_H_ 335 struct __setrlimit_args { 336 u_int which; 337 struct rlimit *rlp; 338 }; 339 #endif 340 /* ARGSUSED */ 341 int 342 setrlimit(p, uap, retval) 343 struct proc *p; 344 register struct __setrlimit_args *uap; 345 int *retval; 346 { 347 struct rlimit alim; 348 int error; 349 350 if ((error = 351 copyin((caddr_t)uap->rlp, (caddr_t)&alim, sizeof (struct rlimit)))) 352 return (error); 353 return (dosetrlimit(p, uap->which, &alim)); 354 } 355 356 int 357 dosetrlimit(p, which, limp) 358 struct proc *p; 359 u_int which; 360 struct rlimit *limp; 361 { 362 register struct rlimit *alimp; 363 int error; 364 365 if (which >= RLIM_NLIMITS) 366 return (EINVAL); 367 alimp = &p->p_rlimit[which]; 368 369 /* 370 * Preserve historical bugs by treating negative limits as unsigned. 371 */ 372 if (limp->rlim_cur < 0) 373 limp->rlim_cur = RLIM_INFINITY; 374 if (limp->rlim_max < 0) 375 limp->rlim_max = RLIM_INFINITY; 376 377 if (limp->rlim_cur > alimp->rlim_max || 378 limp->rlim_max > alimp->rlim_max) 379 if ((error = suser(p->p_ucred, &p->p_acflag))) 380 return (error); 381 if (limp->rlim_cur > limp->rlim_max) 382 limp->rlim_cur = limp->rlim_max; 383 if (p->p_limit->p_refcnt > 1 && 384 (p->p_limit->p_lflags & PL_SHAREMOD) == 0) { 385 p->p_limit->p_refcnt--; 386 p->p_limit = limcopy(p->p_limit); 387 alimp = &p->p_rlimit[which]; 388 } 389 390 switch (which) { 391 392 case RLIMIT_DATA: 393 if (limp->rlim_cur > MAXDSIZ) 394 limp->rlim_cur = MAXDSIZ; 395 if (limp->rlim_max > MAXDSIZ) 396 limp->rlim_max = MAXDSIZ; 397 break; 398 399 case RLIMIT_STACK: 400 if (limp->rlim_cur > MAXSSIZ) 401 limp->rlim_cur = MAXSSIZ; 402 if (limp->rlim_max > MAXSSIZ) 403 limp->rlim_max = MAXSSIZ; 404 /* 405 * Stack is allocated to the max at exec time with only 406 * "rlim_cur" bytes accessible. If stack limit is going 407 * up make more accessible, if going down make inaccessible. 408 */ 409 if (limp->rlim_cur != alimp->rlim_cur) { 410 vm_offset_t addr; 411 vm_size_t size; 412 vm_prot_t prot; 413 414 if (limp->rlim_cur > alimp->rlim_cur) { 415 prot = VM_PROT_ALL; 416 size = limp->rlim_cur - alimp->rlim_cur; 417 addr = USRSTACK - limp->rlim_cur; 418 } else { 419 prot = VM_PROT_NONE; 420 size = alimp->rlim_cur - limp->rlim_cur; 421 addr = USRSTACK - alimp->rlim_cur; 422 } 423 addr = trunc_page(addr); 424 size = round_page(size); 425 (void) vm_map_protect(&p->p_vmspace->vm_map, 426 addr, addr+size, prot, FALSE); 427 } 428 break; 429 430 case RLIMIT_NOFILE: 431 if (limp->rlim_cur > maxfilesperproc) 432 limp->rlim_cur = maxfilesperproc; 433 if (limp->rlim_max > maxfilesperproc) 434 limp->rlim_max = maxfilesperproc; 435 break; 436 437 case RLIMIT_NPROC: 438 if (limp->rlim_cur > maxprocperuid) 439 limp->rlim_cur = maxprocperuid; 440 if (limp->rlim_max > maxprocperuid) 441 limp->rlim_max = maxprocperuid; 442 break; 443 } 444 *alimp = *limp; 445 return (0); 446 } 447 448 #ifndef _SYS_SYSPROTO_H_ 449 struct __getrlimit_args { 450 u_int which; 451 struct rlimit *rlp; 452 }; 453 #endif 454 /* ARGSUSED */ 455 int 456 getrlimit(p, uap, retval) 457 struct proc *p; 458 register struct __getrlimit_args *uap; 459 int *retval; 460 { 461 462 if (uap->which >= RLIM_NLIMITS) 463 return (EINVAL); 464 return (copyout((caddr_t)&p->p_rlimit[uap->which], (caddr_t)uap->rlp, 465 sizeof (struct rlimit))); 466 } 467 468 /* 469 * Transform the running time and tick information in proc p into user, 470 * system, and interrupt time usage. 471 */ 472 void 473 calcru(p, up, sp, ip) 474 struct proc *p; 475 struct timeval *up; 476 struct timeval *sp; 477 struct timeval *ip; 478 { 479 quad_t totusec; 480 u_quad_t u, st, ut, it, tot; 481 long sec, usec; 482 int s; 483 struct timeval tv; 484 485 s = splstatclock(); 486 st = p->p_sticks; 487 ut = p->p_uticks; 488 it = p->p_iticks; 489 splx(s); 490 491 tot = st + ut + it; 492 if (tot == 0) { 493 st = 1; 494 tot = 1; 495 } 496 497 sec = p->p_rtime.tv_sec; 498 usec = p->p_rtime.tv_usec; 499 if (p == curproc) { 500 /* 501 * Adjust for the current time slice. This is actually fairly 502 * important since the error here is on the order of a time 503 * quantum, which is much greater than the sampling error. 504 */ 505 microtime(&tv); 506 sec += tv.tv_sec - runtime.tv_sec; 507 usec += tv.tv_usec - runtime.tv_usec; 508 } 509 totusec = (quad_t)sec * 1000000 + usec; 510 if (totusec < 0) { 511 /* XXX no %qd in kernel. Truncate. */ 512 printf("calcru: negative time: %ld usec\n", (long)totusec); 513 totusec = 0; 514 } 515 u = totusec; 516 st = (u * st) / tot; 517 sp->tv_sec = st / 1000000; 518 sp->tv_usec = st % 1000000; 519 ut = (u * ut) / tot; 520 up->tv_sec = ut / 1000000; 521 up->tv_usec = ut % 1000000; 522 if (ip != NULL) { 523 it = (u * it) / tot; 524 ip->tv_sec = it / 1000000; 525 ip->tv_usec = it % 1000000; 526 } 527 } 528 529 #ifndef _SYS_SYSPROTO_H_ 530 struct getrusage_args { 531 int who; 532 struct rusage *rusage; 533 }; 534 #endif 535 /* ARGSUSED */ 536 int 537 getrusage(p, uap, retval) 538 register struct proc *p; 539 register struct getrusage_args *uap; 540 int *retval; 541 { 542 register struct rusage *rup; 543 544 switch (uap->who) { 545 546 case RUSAGE_SELF: 547 rup = &p->p_stats->p_ru; 548 calcru(p, &rup->ru_utime, &rup->ru_stime, NULL); 549 break; 550 551 case RUSAGE_CHILDREN: 552 rup = &p->p_stats->p_cru; 553 break; 554 555 default: 556 return (EINVAL); 557 } 558 return (copyout((caddr_t)rup, (caddr_t)uap->rusage, 559 sizeof (struct rusage))); 560 } 561 562 void 563 ruadd(ru, ru2) 564 register struct rusage *ru, *ru2; 565 { 566 register long *ip, *ip2; 567 register int i; 568 569 timevaladd(&ru->ru_utime, &ru2->ru_utime); 570 timevaladd(&ru->ru_stime, &ru2->ru_stime); 571 if (ru->ru_maxrss < ru2->ru_maxrss) 572 ru->ru_maxrss = ru2->ru_maxrss; 573 ip = &ru->ru_first; ip2 = &ru2->ru_first; 574 for (i = &ru->ru_last - &ru->ru_first; i >= 0; i--) 575 *ip++ += *ip2++; 576 } 577 578 /* 579 * Make a copy of the plimit structure. 580 * We share these structures copy-on-write after fork, 581 * and copy when a limit is changed. 582 */ 583 struct plimit * 584 limcopy(lim) 585 struct plimit *lim; 586 { 587 register struct plimit *copy; 588 589 MALLOC(copy, struct plimit *, sizeof(struct plimit), 590 M_SUBPROC, M_WAITOK); 591 bcopy(lim->pl_rlimit, copy->pl_rlimit, 592 sizeof(struct rlimit) * RLIM_NLIMITS); 593 copy->p_lflags = 0; 594 copy->p_refcnt = 1; 595 return (copy); 596 } 597