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