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. Neither the name of the University nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 * 34 * @(#)kern_resource.c 8.5 (Berkeley) 1/21/94 35 * $FreeBSD: src/sys/kern/kern_resource.c,v 1.55.2.5 2001/11/03 01:41:08 ps Exp $ 36 */ 37 38 #include <sys/param.h> 39 #include <sys/systm.h> 40 #include <sys/sysmsg.h> 41 #include <sys/file.h> 42 #include <sys/kernel.h> 43 #include <sys/resourcevar.h> 44 #include <sys/malloc.h> 45 #include <sys/proc.h> 46 #include <sys/priv.h> 47 #include <sys/time.h> 48 #include <sys/lockf.h> 49 50 #include <vm/vm.h> 51 #include <vm/vm_param.h> 52 #include <sys/lock.h> 53 #include <vm/pmap.h> 54 #include <vm/vm_map.h> 55 56 #include <sys/thread2.h> 57 #include <sys/spinlock2.h> 58 59 static int donice (struct proc *chgp, int n); 60 static int doionice (struct proc *chgp, int n); 61 62 static MALLOC_DEFINE(M_UIDINFO, "uidinfo", "uidinfo structures"); 63 #define UIHASH(uid) (&uihashtbl[(uid) & uihash]) 64 static struct spinlock uihash_lock; 65 static LIST_HEAD(uihashhead, uidinfo) *uihashtbl; 66 static u_long uihash; /* size of hash table - 1 */ 67 68 static struct uidinfo *uilookup (uid_t uid); 69 70 /* 71 * Resource controls and accounting. 72 */ 73 74 struct getpriority_info { 75 int low; 76 int who; 77 }; 78 79 static int getpriority_callback(struct proc *p, void *data); 80 81 /* 82 * MPALMOSTSAFE 83 */ 84 int 85 sys_getpriority(struct sysmsg *sysmsg, const struct getpriority_args *uap) 86 { 87 struct getpriority_info info; 88 thread_t curtd = curthread; 89 struct proc *curp = curproc; 90 struct proc *p; 91 struct pgrp *pg; 92 int low = PRIO_MAX + 1; 93 int who = uap->who; 94 int error; 95 96 switch (uap->which) { 97 case PRIO_PROCESS: 98 if (who == 0) { 99 low = curp->p_nice; 100 } else { 101 p = pfind(who); 102 if (p) { 103 lwkt_gettoken_shared(&p->p_token); 104 if (PRISON_CHECK(curtd->td_ucred, p->p_ucred)) 105 low = p->p_nice; 106 lwkt_reltoken(&p->p_token); 107 PRELE(p); 108 } 109 } 110 break; 111 case PRIO_PGRP: 112 if (who == 0) { 113 lwkt_gettoken_shared(&curp->p_token); 114 pg = curp->p_pgrp; 115 pgref(pg); 116 lwkt_reltoken(&curp->p_token); 117 } else if ((pg = pgfind(who)) == NULL) { 118 break; 119 } /* else ref held from pgfind */ 120 121 lwkt_gettoken_shared(&pg->pg_token); 122 LIST_FOREACH(p, &pg->pg_members, p_pglist) { 123 if (PRISON_CHECK(curtd->td_ucred, p->p_ucred) && 124 p->p_nice < low) { 125 low = p->p_nice; 126 } 127 } 128 lwkt_reltoken(&pg->pg_token); 129 pgrel(pg); 130 break; 131 case PRIO_USER: 132 if (who == 0) 133 who = curtd->td_ucred->cr_uid; 134 info.low = low; 135 info.who = who; 136 allproc_scan(getpriority_callback, &info, 0); 137 low = info.low; 138 break; 139 140 default: 141 error = EINVAL; 142 goto done; 143 } 144 if (low == PRIO_MAX + 1) { 145 error = ESRCH; 146 goto done; 147 } 148 sysmsg->sysmsg_result = low; 149 error = 0; 150 done: 151 return (error); 152 } 153 154 /* 155 * Figure out the current lowest nice priority for processes owned 156 * by the specified user. 157 */ 158 static 159 int 160 getpriority_callback(struct proc *p, void *data) 161 { 162 struct getpriority_info *info = data; 163 164 lwkt_gettoken_shared(&p->p_token); 165 if (PRISON_CHECK(curthread->td_ucred, p->p_ucred) && 166 p->p_ucred->cr_uid == info->who && 167 p->p_nice < info->low) { 168 info->low = p->p_nice; 169 } 170 lwkt_reltoken(&p->p_token); 171 return(0); 172 } 173 174 struct setpriority_info { 175 int prio; 176 int who; 177 int error; 178 int found; 179 }; 180 181 static int setpriority_callback(struct proc *p, void *data); 182 183 /* 184 * MPALMOSTSAFE 185 */ 186 int 187 sys_setpriority(struct sysmsg *sysmsg, const struct setpriority_args *uap) 188 { 189 struct setpriority_info info; 190 thread_t curtd = curthread; 191 struct proc *curp = curproc; 192 struct proc *p; 193 struct pgrp *pg; 194 int found = 0, error = 0; 195 int who = uap->who; 196 197 switch (uap->which) { 198 case PRIO_PROCESS: 199 if (who == 0) { 200 lwkt_gettoken(&curp->p_token); 201 error = donice(curp, uap->prio); 202 found++; 203 lwkt_reltoken(&curp->p_token); 204 } else { 205 p = pfind(who); 206 if (p) { 207 lwkt_gettoken(&p->p_token); 208 if (PRISON_CHECK(curtd->td_ucred, p->p_ucred)) { 209 error = donice(p, uap->prio); 210 found++; 211 } 212 lwkt_reltoken(&p->p_token); 213 PRELE(p); 214 } 215 } 216 break; 217 case PRIO_PGRP: 218 if (who == 0) { 219 lwkt_gettoken_shared(&curp->p_token); 220 pg = curp->p_pgrp; 221 pgref(pg); 222 lwkt_reltoken(&curp->p_token); 223 } else if ((pg = pgfind(who)) == NULL) { 224 break; 225 } /* else ref held from pgfind */ 226 227 lwkt_gettoken(&pg->pg_token); 228 restart: 229 LIST_FOREACH(p, &pg->pg_members, p_pglist) { 230 PHOLD(p); 231 lwkt_gettoken(&p->p_token); 232 if (p->p_pgrp == pg && 233 PRISON_CHECK(curtd->td_ucred, p->p_ucred)) { 234 error = donice(p, uap->prio); 235 found++; 236 } 237 lwkt_reltoken(&p->p_token); 238 if (p->p_pgrp != pg) { 239 PRELE(p); 240 goto restart; 241 } 242 PRELE(p); 243 } 244 lwkt_reltoken(&pg->pg_token); 245 pgrel(pg); 246 break; 247 case PRIO_USER: 248 if (who == 0) 249 who = curtd->td_ucred->cr_uid; 250 info.prio = uap->prio; 251 info.who = who; 252 info.error = 0; 253 info.found = 0; 254 allproc_scan(setpriority_callback, &info, 0); 255 error = info.error; 256 found = info.found; 257 break; 258 default: 259 error = EINVAL; 260 found = 1; 261 break; 262 } 263 264 if (found == 0) 265 error = ESRCH; 266 return (error); 267 } 268 269 static 270 int 271 setpriority_callback(struct proc *p, void *data) 272 { 273 struct setpriority_info *info = data; 274 int error; 275 276 lwkt_gettoken(&p->p_token); 277 if (p->p_ucred->cr_uid == info->who && 278 PRISON_CHECK(curthread->td_ucred, p->p_ucred)) { 279 error = donice(p, info->prio); 280 if (error) 281 info->error = error; 282 ++info->found; 283 } 284 lwkt_reltoken(&p->p_token); 285 return(0); 286 } 287 288 /* 289 * Caller must hold chgp->p_token 290 */ 291 static int 292 donice(struct proc *chgp, int n) 293 { 294 struct ucred *cr = curthread->td_ucred; 295 struct lwp *lp; 296 297 if (cr->cr_uid && cr->cr_ruid && 298 cr->cr_uid != chgp->p_ucred->cr_uid && 299 cr->cr_ruid != chgp->p_ucred->cr_uid) 300 return (EPERM); 301 if (n > PRIO_MAX) 302 n = PRIO_MAX; 303 if (n < PRIO_MIN) 304 n = PRIO_MIN; 305 if (n < chgp->p_nice && priv_check_cred(cr, PRIV_SCHED_SETPRIORITY, 0)) 306 return (EACCES); 307 chgp->p_nice = n; 308 FOREACH_LWP_IN_PROC(lp, chgp) { 309 LWPHOLD(lp); 310 chgp->p_usched->resetpriority(lp); 311 LWPRELE(lp); 312 } 313 return (0); 314 } 315 316 317 struct ioprio_get_info { 318 int high; 319 int who; 320 }; 321 322 static int ioprio_get_callback(struct proc *p, void *data); 323 324 /* 325 * MPALMOSTSAFE 326 */ 327 int 328 sys_ioprio_get(struct sysmsg *sysmsg, const struct ioprio_get_args *uap) 329 { 330 struct ioprio_get_info info; 331 thread_t curtd = curthread; 332 struct proc *curp = curproc; 333 struct proc *p; 334 struct pgrp *pg; 335 int high = IOPRIO_MIN-2; 336 int who = uap->who; 337 int error; 338 339 switch (uap->which) { 340 case PRIO_PROCESS: 341 if (who == 0) { 342 high = curp->p_ionice; 343 } else { 344 p = pfind(who); 345 if (p) { 346 lwkt_gettoken_shared(&p->p_token); 347 if (PRISON_CHECK(curtd->td_ucred, p->p_ucred)) 348 high = p->p_ionice; 349 lwkt_reltoken(&p->p_token); 350 PRELE(p); 351 } 352 } 353 break; 354 case PRIO_PGRP: 355 if (who == 0) { 356 lwkt_gettoken_shared(&curp->p_token); 357 pg = curp->p_pgrp; 358 pgref(pg); 359 lwkt_reltoken(&curp->p_token); 360 } else if ((pg = pgfind(who)) == NULL) { 361 break; 362 } /* else ref held from pgfind */ 363 364 lwkt_gettoken_shared(&pg->pg_token); 365 LIST_FOREACH(p, &pg->pg_members, p_pglist) { 366 if (PRISON_CHECK(curtd->td_ucred, p->p_ucred) && 367 p->p_nice > high) 368 high = p->p_ionice; 369 } 370 lwkt_reltoken(&pg->pg_token); 371 pgrel(pg); 372 break; 373 case PRIO_USER: 374 if (who == 0) 375 who = curtd->td_ucred->cr_uid; 376 info.high = high; 377 info.who = who; 378 allproc_scan(ioprio_get_callback, &info, 0); 379 high = info.high; 380 break; 381 default: 382 error = EINVAL; 383 goto done; 384 } 385 if (high == IOPRIO_MIN-2) { 386 error = ESRCH; 387 goto done; 388 } 389 sysmsg->sysmsg_result = high; 390 error = 0; 391 done: 392 return (error); 393 } 394 395 /* 396 * Figure out the current lowest nice priority for processes owned 397 * by the specified user. 398 */ 399 static 400 int 401 ioprio_get_callback(struct proc *p, void *data) 402 { 403 struct ioprio_get_info *info = data; 404 405 lwkt_gettoken_shared(&p->p_token); 406 if (PRISON_CHECK(curthread->td_ucred, p->p_ucred) && 407 p->p_ucred->cr_uid == info->who && 408 p->p_ionice > info->high) { 409 info->high = p->p_ionice; 410 } 411 lwkt_reltoken(&p->p_token); 412 return(0); 413 } 414 415 416 struct ioprio_set_info { 417 int prio; 418 int who; 419 int error; 420 int found; 421 }; 422 423 static int ioprio_set_callback(struct proc *p, void *data); 424 425 /* 426 * MPALMOSTSAFE 427 */ 428 int 429 sys_ioprio_set(struct sysmsg *sysmsg, const struct ioprio_set_args *uap) 430 { 431 struct ioprio_set_info info; 432 thread_t curtd = curthread; 433 struct proc *curp = curproc; 434 struct proc *p; 435 struct pgrp *pg; 436 int found = 0, error = 0; 437 int who = uap->who; 438 439 switch (uap->which) { 440 case PRIO_PROCESS: 441 if (who == 0) { 442 lwkt_gettoken(&curp->p_token); 443 error = doionice(curp, uap->prio); 444 lwkt_reltoken(&curp->p_token); 445 found++; 446 } else { 447 p = pfind(who); 448 if (p) { 449 lwkt_gettoken(&p->p_token); 450 if (PRISON_CHECK(curtd->td_ucred, p->p_ucred)) { 451 error = doionice(p, uap->prio); 452 found++; 453 } 454 lwkt_reltoken(&p->p_token); 455 PRELE(p); 456 } 457 } 458 break; 459 case PRIO_PGRP: 460 if (who == 0) { 461 lwkt_gettoken_shared(&curp->p_token); 462 pg = curp->p_pgrp; 463 pgref(pg); 464 lwkt_reltoken(&curp->p_token); 465 } else if ((pg = pgfind(who)) == NULL) { 466 break; 467 } /* else ref held from pgfind */ 468 469 lwkt_gettoken(&pg->pg_token); 470 restart: 471 LIST_FOREACH(p, &pg->pg_members, p_pglist) { 472 PHOLD(p); 473 lwkt_gettoken(&p->p_token); 474 if (p->p_pgrp == pg && 475 PRISON_CHECK(curtd->td_ucred, p->p_ucred)) { 476 error = doionice(p, uap->prio); 477 found++; 478 } 479 lwkt_reltoken(&p->p_token); 480 if (p->p_pgrp != pg) { 481 PRELE(p); 482 goto restart; 483 } 484 PRELE(p); 485 } 486 lwkt_reltoken(&pg->pg_token); 487 pgrel(pg); 488 break; 489 case PRIO_USER: 490 if (who == 0) 491 who = curtd->td_ucred->cr_uid; 492 info.prio = uap->prio; 493 info.who = who; 494 info.error = 0; 495 info.found = 0; 496 allproc_scan(ioprio_set_callback, &info, 0); 497 error = info.error; 498 found = info.found; 499 break; 500 default: 501 error = EINVAL; 502 found = 1; 503 break; 504 } 505 506 if (found == 0) 507 error = ESRCH; 508 return (error); 509 } 510 511 static 512 int 513 ioprio_set_callback(struct proc *p, void *data) 514 { 515 struct ioprio_set_info *info = data; 516 int error; 517 518 lwkt_gettoken(&p->p_token); 519 if (p->p_ucred->cr_uid == info->who && 520 PRISON_CHECK(curthread->td_ucred, p->p_ucred)) { 521 error = doionice(p, info->prio); 522 if (error) 523 info->error = error; 524 ++info->found; 525 } 526 lwkt_reltoken(&p->p_token); 527 return(0); 528 } 529 530 static int 531 doionice(struct proc *chgp, int n) 532 { 533 struct ucred *cr = curthread->td_ucred; 534 535 if (cr->cr_uid && cr->cr_ruid && 536 cr->cr_uid != chgp->p_ucred->cr_uid && 537 cr->cr_ruid != chgp->p_ucred->cr_uid) 538 return (EPERM); 539 if (n > IOPRIO_MAX) 540 n = IOPRIO_MAX; 541 if (n < IOPRIO_MIN) 542 n = IOPRIO_MIN; 543 if (n < chgp->p_ionice && 544 priv_check_cred(cr, PRIV_SCHED_SETPRIORITY, 0)) 545 return (EACCES); 546 chgp->p_ionice = n; 547 548 return (0); 549 550 } 551 552 /* 553 * MPALMOSTSAFE 554 */ 555 int 556 sys_lwp_rtprio(struct sysmsg *sysmsg, const struct lwp_rtprio_args *uap) 557 { 558 struct ucred *cr = curthread->td_ucred; 559 struct proc *p; 560 struct lwp *lp; 561 struct rtprio rtp; 562 int error; 563 564 error = copyin(uap->rtp, &rtp, sizeof(struct rtprio)); 565 if (error) 566 return error; 567 if (uap->pid < 0) 568 return EINVAL; 569 570 if (uap->pid == 0) { 571 p = curproc; 572 PHOLD(p); 573 } else { 574 p = pfind(uap->pid); 575 } 576 if (p == NULL) { 577 error = ESRCH; 578 goto done; 579 } 580 lwkt_gettoken(&p->p_token); 581 582 if (uap->tid < -1) { 583 error = EINVAL; 584 goto done; 585 } 586 if (uap->tid == -1) { 587 /* 588 * sadly, tid can be 0 so we can't use 0 here 589 * like sys_rtprio() 590 */ 591 lp = curthread->td_lwp; 592 } else { 593 lp = lwp_rb_tree_RB_LOOKUP(&p->p_lwp_tree, uap->tid); 594 if (lp == NULL) { 595 error = ESRCH; 596 goto done; 597 } 598 } 599 600 /* 601 * Make sure that this lwp is not ripped if any of the following 602 * code blocks, e.g. copyout. 603 */ 604 LWPHOLD(lp); 605 switch (uap->function) { 606 case RTP_LOOKUP: 607 error = copyout(&lp->lwp_rtprio, uap->rtp, 608 sizeof(struct rtprio)); 609 break; 610 case RTP_SET: 611 if (cr->cr_uid && cr->cr_ruid && 612 cr->cr_uid != p->p_ucred->cr_uid && 613 cr->cr_ruid != p->p_ucred->cr_uid) { 614 error = EPERM; 615 break; 616 } 617 /* disallow setting rtprio in most cases if not superuser */ 618 if (priv_check_cred(cr, PRIV_SCHED_RTPRIO, 0)) { 619 /* can't set someone else's */ 620 if (uap->pid) { /* XXX */ 621 error = EPERM; 622 break; 623 } 624 /* can't set realtime priority */ 625 /* 626 * Realtime priority has to be restricted for reasons which should be 627 * obvious. However, for idle priority, there is a potential for 628 * system deadlock if an idleprio process gains a lock on a resource 629 * that other processes need (and the idleprio process can't run 630 * due to a CPU-bound normal process). Fix me! XXX 631 */ 632 if (RTP_PRIO_IS_REALTIME(rtp.type)) { 633 error = EPERM; 634 break; 635 } 636 } 637 switch (rtp.type) { 638 #ifdef RTP_PRIO_FIFO 639 case RTP_PRIO_FIFO: 640 #endif 641 case RTP_PRIO_REALTIME: 642 case RTP_PRIO_NORMAL: 643 case RTP_PRIO_IDLE: 644 if (rtp.prio > RTP_PRIO_MAX) { 645 error = EINVAL; 646 } else { 647 lp->lwp_rtprio = rtp; 648 error = 0; 649 } 650 break; 651 default: 652 error = EINVAL; 653 break; 654 } 655 break; 656 default: 657 error = EINVAL; 658 break; 659 } 660 LWPRELE(lp); 661 662 done: 663 if (p) { 664 lwkt_reltoken(&p->p_token); 665 PRELE(p); 666 } 667 return (error); 668 } 669 670 /* 671 * Set realtime priority 672 * 673 * MPALMOSTSAFE 674 */ 675 int 676 sys_rtprio(struct sysmsg *sysmsg, const struct rtprio_args *uap) 677 { 678 struct ucred *cr = curthread->td_ucred; 679 struct proc *p; 680 struct lwp *lp; 681 struct rtprio rtp; 682 int error; 683 684 error = copyin(uap->rtp, &rtp, sizeof(struct rtprio)); 685 if (error) 686 return (error); 687 688 if (uap->pid == 0) { 689 p = curproc; 690 PHOLD(p); 691 } else { 692 p = pfind(uap->pid); 693 } 694 695 if (p == NULL) { 696 error = ESRCH; 697 goto done; 698 } 699 lwkt_gettoken(&p->p_token); 700 701 /* XXX lwp */ 702 lp = FIRST_LWP_IN_PROC(p); 703 switch (uap->function) { 704 case RTP_LOOKUP: 705 error = copyout(&lp->lwp_rtprio, uap->rtp, 706 sizeof(struct rtprio)); 707 break; 708 case RTP_SET: 709 if (cr->cr_uid && cr->cr_ruid && 710 cr->cr_uid != p->p_ucred->cr_uid && 711 cr->cr_ruid != p->p_ucred->cr_uid) { 712 error = EPERM; 713 break; 714 } 715 /* disallow setting rtprio in most cases if not superuser */ 716 if (priv_check_cred(cr, PRIV_SCHED_RTPRIO, 0)) { 717 /* can't set someone else's */ 718 if (uap->pid) { 719 error = EPERM; 720 break; 721 } 722 /* can't set realtime priority */ 723 /* 724 * Realtime priority has to be restricted for reasons which should be 725 * obvious. However, for idle priority, there is a potential for 726 * system deadlock if an idleprio process gains a lock on a resource 727 * that other processes need (and the idleprio process can't run 728 * due to a CPU-bound normal process). Fix me! XXX 729 */ 730 if (RTP_PRIO_IS_REALTIME(rtp.type)) { 731 error = EPERM; 732 break; 733 } 734 } 735 switch (rtp.type) { 736 #ifdef RTP_PRIO_FIFO 737 case RTP_PRIO_FIFO: 738 #endif 739 case RTP_PRIO_REALTIME: 740 case RTP_PRIO_NORMAL: 741 case RTP_PRIO_IDLE: 742 if (rtp.prio > RTP_PRIO_MAX) { 743 error = EINVAL; 744 break; 745 } 746 lp->lwp_rtprio = rtp; 747 error = 0; 748 break; 749 default: 750 error = EINVAL; 751 break; 752 } 753 break; 754 default: 755 error = EINVAL; 756 break; 757 } 758 done: 759 if (p) { 760 lwkt_reltoken(&p->p_token); 761 PRELE(p); 762 } 763 764 return (error); 765 } 766 767 /* 768 * Transform the running time and tick information in lwp lp's thread into user, 769 * system, and interrupt time usage. 770 * 771 * Since we are limited to statclock tick granularity this is a statisical 772 * calculation which will be correct over the long haul, but should not be 773 * expected to measure fine grained deltas. 774 * 775 * It is possible to catch a lwp in the midst of being created, so 776 * check whether lwp_thread is NULL or not. 777 */ 778 void 779 calcru(struct lwp *lp, struct timeval *up, struct timeval *sp) 780 { 781 struct thread *td; 782 783 /* 784 * Calculate at the statclock level. YYY if the thread is owned by 785 * another cpu we need to forward the request to the other cpu, or 786 * have a token to interlock the information in order to avoid racing 787 * thread destruction. 788 */ 789 if ((td = lp->lwp_thread) != NULL) { 790 crit_enter(); 791 up->tv_sec = td->td_uticks / 1000000; 792 up->tv_usec = td->td_uticks % 1000000; 793 sp->tv_sec = td->td_sticks / 1000000; 794 sp->tv_usec = td->td_sticks % 1000000; 795 crit_exit(); 796 } 797 } 798 799 /* 800 * Aggregate resource statistics of all lwps of a process. 801 * 802 * proc.p_ru keeps track of all statistics directly related to a proc. This 803 * consists of RSS usage and nswap information and aggregate numbers for all 804 * former lwps of this proc. 805 * 806 * proc.p_cru is the sum of all stats of reaped children. 807 * 808 * lwp.lwp_ru contains the stats directly related to one specific lwp, meaning 809 * packet, scheduler switch or page fault counts, etc. This information gets 810 * added to lwp.lwp_proc.p_ru when the lwp exits. 811 */ 812 void 813 calcru_proc(struct proc *p, struct rusage *ru) 814 { 815 struct timeval upt, spt; 816 long *rip1, *rip2; 817 struct lwp *lp; 818 819 *ru = p->p_ru; 820 821 FOREACH_LWP_IN_PROC(lp, p) { 822 calcru(lp, &upt, &spt); 823 timevaladd(&ru->ru_utime, &upt); 824 timevaladd(&ru->ru_stime, &spt); 825 for (rip1 = &ru->ru_first, rip2 = &lp->lwp_ru.ru_first; 826 rip1 <= &ru->ru_last; 827 rip1++, rip2++) 828 *rip1 += *rip2; 829 } 830 } 831 832 833 /* 834 * MPALMOSTSAFE 835 */ 836 int 837 sys_getrusage(struct sysmsg *sysmsg, const struct getrusage_args *uap) 838 { 839 struct proc *p = curproc; 840 struct rusage ru; 841 struct rusage *rup; 842 int error; 843 844 lwkt_gettoken(&p->p_token); 845 846 switch (uap->who) { 847 case RUSAGE_SELF: 848 rup = &ru; 849 calcru_proc(p, rup); 850 error = 0; 851 break; 852 case RUSAGE_CHILDREN: 853 rup = &p->p_cru; 854 error = 0; 855 break; 856 default: 857 error = EINVAL; 858 break; 859 } 860 lwkt_reltoken(&p->p_token); 861 862 if (error == 0) 863 error = copyout(rup, uap->rusage, sizeof(struct rusage)); 864 return (error); 865 } 866 867 void 868 ruadd(struct rusage *ru, struct rusage *ru2) 869 { 870 long *ip, *ip2; 871 int i; 872 873 timevaladd(&ru->ru_utime, &ru2->ru_utime); 874 timevaladd(&ru->ru_stime, &ru2->ru_stime); 875 if (ru->ru_maxrss < ru2->ru_maxrss) 876 ru->ru_maxrss = ru2->ru_maxrss; 877 ip = &ru->ru_first; ip2 = &ru2->ru_first; 878 for (i = &ru->ru_last - &ru->ru_first; i >= 0; i--) 879 *ip++ += *ip2++; 880 } 881 882 /* 883 * Find the uidinfo structure for a uid. This structure is used to 884 * track the total resource consumption (process count, socket buffer 885 * size, etc.) for the uid and impose limits. 886 */ 887 void 888 uihashinit(void) 889 { 890 spin_init(&uihash_lock, "uihashinit"); 891 uihashtbl = hashinit(maxproc / 16, M_UIDINFO, &uihash); 892 } 893 894 /* 895 * NOTE: Must be called with uihash_lock held 896 */ 897 static struct uidinfo * 898 uilookup(uid_t uid) 899 { 900 struct uihashhead *uipp; 901 struct uidinfo *uip; 902 903 uipp = UIHASH(uid); 904 LIST_FOREACH(uip, uipp, ui_hash) { 905 if (uip->ui_uid == uid) 906 break; 907 } 908 return (uip); 909 } 910 911 /* 912 * Helper function to creat ea uid that could not be found. 913 * This function will properly deal with races. 914 * 915 * WARNING! Should only be used by this source file and by the proc0 916 * creation code. 917 */ 918 struct uidinfo * 919 uicreate(uid_t uid) 920 { 921 struct uidinfo *uip, *tmp; 922 923 /* 924 * Allocate space and check for a race 925 */ 926 uip = kmalloc(sizeof(*uip), M_UIDINFO, M_WAITOK | M_ZERO); 927 928 /* 929 * Initialize structure and enter it into the hash table 930 */ 931 spin_init(&uip->ui_lock, "uicreate"); 932 uip->ui_uid = uid; 933 uip->ui_ref = 1; /* we're returning a ref */ 934 varsymset_init(&uip->ui_varsymset, NULL); 935 uip->ui_pcpu = kmalloc(sizeof(*uip->ui_pcpu) * ncpus, 936 M_UIDINFO, M_WAITOK | M_ZERO); 937 938 /* 939 * Somebody may have already created the uidinfo for this 940 * uid. If so, return that instead. 941 */ 942 spin_lock(&uihash_lock); 943 tmp = uilookup(uid); 944 if (tmp != NULL) { 945 uihold(tmp); 946 spin_unlock(&uihash_lock); 947 948 spin_uninit(&uip->ui_lock); 949 varsymset_clean(&uip->ui_varsymset); 950 kfree(uip->ui_pcpu, M_UIDINFO); 951 kfree(uip, M_UIDINFO); 952 uip = tmp; 953 } else { 954 LIST_INSERT_HEAD(UIHASH(uid), uip, ui_hash); 955 spin_unlock(&uihash_lock); 956 } 957 return (uip); 958 } 959 960 /* 961 * Find the uidinfo for a uid, creating one if necessary 962 */ 963 struct uidinfo * 964 uifind(uid_t uid) 965 { 966 struct uidinfo *uip; 967 thread_t td = curthread; 968 969 if (td->td_ucred) { 970 uip = td->td_ucred->cr_uidinfo; 971 if (uip->ui_uid == uid) { 972 uihold(uip); 973 return uip; 974 } 975 uip = td->td_ucred->cr_ruidinfo; 976 if (uip->ui_uid == uid) { 977 uihold(uip); 978 return uip; 979 } 980 } 981 982 spin_lock_shared(&uihash_lock); 983 uip = uilookup(uid); 984 if (uip == NULL) { 985 spin_unlock_shared(&uihash_lock); 986 uip = uicreate(uid); 987 } else { 988 uihold(uip); 989 spin_unlock_shared(&uihash_lock); 990 } 991 return (uip); 992 } 993 994 /* 995 * Helper funtion to remove a uidinfo whos reference count may 996 * have transitioned to 0. The reference count is likely 0 997 * on-call. 998 */ 999 static __inline void 1000 uifree(uid_t uid) 1001 { 1002 struct uidinfo *uip; 1003 1004 /* 1005 * If we are still the only holder after acquiring the uihash_lock 1006 * we can safely unlink the uip and destroy it. Otherwise we lost 1007 * a race and must fail. 1008 */ 1009 spin_lock(&uihash_lock); 1010 uip = uilookup(uid); 1011 if (uip && uip->ui_ref == 0) { 1012 LIST_REMOVE(uip, ui_hash); 1013 spin_unlock(&uihash_lock); 1014 1015 /* 1016 * The uip is now orphaned and we can destroy it at our 1017 * leisure. 1018 */ 1019 if (uip->ui_sbsize != 0) 1020 kprintf("freeing uidinfo: uid = %d, sbsize = %jd\n", 1021 uip->ui_uid, (intmax_t)uip->ui_sbsize); 1022 if (uip->ui_proccnt != 0) 1023 kprintf("freeing uidinfo: uid = %d, proccnt = %ld\n", 1024 uip->ui_uid, uip->ui_proccnt); 1025 1026 varsymset_clean(&uip->ui_varsymset); 1027 lockuninit(&uip->ui_varsymset.vx_lock); 1028 spin_uninit(&uip->ui_lock); 1029 kfree(uip->ui_pcpu, M_UIDINFO); 1030 kfree(uip, M_UIDINFO); 1031 } else { 1032 spin_unlock(&uihash_lock); 1033 } 1034 } 1035 1036 /* 1037 * Bump the ref count 1038 */ 1039 void 1040 uihold(struct uidinfo *uip) 1041 { 1042 KKASSERT(uip->ui_ref >= 0); 1043 atomic_add_int(&uip->ui_ref, 1); 1044 } 1045 1046 /* 1047 * Drop the ref count. The last-drop code still needs to remove the 1048 * uidinfo from the hash table which it does by re-looking-it-up. 1049 * 1050 * NOTE: The uip can be ripped out from under us after the fetchadd. 1051 */ 1052 void 1053 uidrop(struct uidinfo *uip) 1054 { 1055 uid_t uid; 1056 1057 KKASSERT(uip->ui_ref > 0); 1058 uid = uip->ui_uid; 1059 cpu_ccfence(); 1060 if (atomic_fetchadd_int(&uip->ui_ref, -1) == 1) { 1061 uifree(uid); 1062 } 1063 } 1064 1065 void 1066 uireplace(struct uidinfo **puip, struct uidinfo *nuip) 1067 { 1068 uidrop(*puip); 1069 *puip = nuip; 1070 } 1071 1072 /* 1073 * Change the count associated with number of processes 1074 * a given user is using. 1075 * 1076 * NOTE: When 'max' is 0, don't enforce a limit. 1077 * 1078 * NOTE: Due to concurrency, the count can sometimes exceed the max 1079 * by a small amount. 1080 */ 1081 int 1082 chgproccnt(struct uidinfo *uip, int diff, int max) 1083 { 1084 int ret; 1085 1086 /* don't allow them to exceed max, but allow subtraction */ 1087 if (diff > 0 && uip->ui_proccnt + diff > max && max != 0) { 1088 ret = 0; 1089 } else { 1090 atomic_add_long(&uip->ui_proccnt, diff); 1091 if (uip->ui_proccnt < 0) 1092 kprintf("negative proccnt for uid = %d\n", uip->ui_uid); 1093 ret = 1; 1094 } 1095 return ret; 1096 } 1097 1098 /* 1099 * Change the total socket buffer size a user has used. 1100 */ 1101 int 1102 chgsbsize(struct uidinfo *uip, u_long *hiwat, u_long to, rlim_t max) 1103 { 1104 rlim_t new; 1105 1106 rlim_t sbsize; 1107 1108 sbsize = atomic_fetchadd_long(&uip->ui_sbsize, to - *hiwat); 1109 new = sbsize + to - *hiwat; 1110 KKASSERT(new >= 0); 1111 1112 /* 1113 * If we are trying to increase the socket buffer size 1114 * Scale down the hi water mark when we exceed the user's 1115 * allowed socket buffer space. 1116 * 1117 * We can't scale down too much or we will blow up atomic packet 1118 * operations. 1119 */ 1120 if (to > *hiwat && to > MCLBYTES && new > max) { 1121 to = to * max / new; 1122 if (to < MCLBYTES) 1123 to = MCLBYTES; 1124 } 1125 *hiwat = to; 1126 return (1); 1127 } 1128