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
| 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
|
198 break; 199 } 200 201 case PRIO_USER: 202 if (uap->who == 0) 203 uap->who = curp->p_ucred->cr_uid; 204 sx_slock(&allproc_lock); 205 FOREACH_PROC_IN_SYSTEM(p) { 206 if (p->p_ucred->cr_uid == uap->who && 207 !p_cansee(curp, p)) { 208 error = donice(curp, p, uap->prio); 209 found++; 210 } 211 } 212 sx_sunlock(&allproc_lock); 213 break; 214 215 default: 216 error = EINVAL; 217 break; 218 } 219 if (found == 0 && error == 0) 220 error = ESRCH; 221 mtx_unlock(&Giant); 222 return (error); 223} 224 225static int 226donice(curp, chgp, n) 227 register struct proc *curp, *chgp; 228 register int n; 229{ 230 int error; 231 232 if ((error = p_cansched(curp, chgp))) 233 return (error); 234 if (n > PRIO_MAX) 235 n = PRIO_MAX; 236 if (n < PRIO_MIN) 237 n = PRIO_MIN; 238 if (n < chgp->p_ksegrp.kg_nice /* XXXKSE */ && 239 suser_xxx(curp->p_ucred, NULL, 0)) 240 return (EACCES); 241 chgp->p_ksegrp.kg_nice /* XXXKSE */ = n; 242 (void)resetpriority(&chgp->p_ksegrp); /* XXXKSE */ 243 return (0); 244} 245 246/* rtprio system call */ 247#ifndef _SYS_SYSPROTO_H_ 248struct rtprio_args { 249 int function; 250 pid_t pid; 251 struct rtprio *rtp; 252}; 253#endif 254 255/* 256 * Set realtime priority 257 */ 258 259/* 260 * MPSAFE 261 */ 262/* ARGSUSED */ 263int 264rtprio(td, uap) 265 struct thread *td; 266 register struct rtprio_args *uap; 267{ 268 struct proc *curp = td->td_proc; 269 register struct proc *p; 270 struct rtprio rtp; 271 int error; 272 273 mtx_lock(&Giant); 274 275 if (uap->pid == 0) { 276 p = curp; 277 PROC_LOCK(p); 278 } else { 279 p = pfind(uap->pid); 280 } 281 282 if (p == NULL) { 283 error = ESRCH; 284 goto done2; 285 } 286 287 switch (uap->function) { 288 case RTP_LOOKUP: 289 if ((error = p_cansee(curp, p))) 290 break; 291 mtx_lock_spin(&sched_lock); 292 pri_to_rtp(&p->p_ksegrp /* XXXKSE */ , &rtp); 293 mtx_unlock_spin(&sched_lock); 294 error = copyout(&rtp, uap->rtp, sizeof(struct rtprio)); 295 break; 296 case RTP_SET: 297 if ((error = p_cansched(curp, p)) || 298 (error = copyin(uap->rtp, &rtp, sizeof(struct rtprio)))) 299 break; 300 /* disallow setting rtprio in most cases if not superuser */ 301 if (suser_xxx(curp->p_ucred, NULL, 0) != 0) { 302 /* can't set someone else's */ 303 if (uap->pid) { 304 error = EPERM; 305 break; 306 } 307 /* can't set realtime priority */ 308/* 309 * Realtime priority has to be restricted for reasons which should be 310 * obvious. However, for idle priority, there is a potential for 311 * system deadlock if an idleprio process gains a lock on a resource 312 * that other processes need (and the idleprio process can't run 313 * due to a CPU-bound normal process). Fix me! XXX 314 */ 315#if 0 316 if (RTP_PRIO_IS_REALTIME(rtp.type)) 317#endif 318 if (rtp.type != RTP_PRIO_NORMAL) { 319 error = EPERM; 320 break; 321 } 322 } 323 mtx_lock_spin(&sched_lock); 324 error = rtp_to_pri(&rtp, &p->p_ksegrp); 325 mtx_unlock_spin(&sched_lock); 326 break; 327 default: 328 error = EINVAL; 329 break; 330 } 331 PROC_UNLOCK(p); 332done2: 333 mtx_unlock(&Giant); 334 return (error); 335} 336 337int 338rtp_to_pri(struct rtprio *rtp, struct ksegrp *kg) 339{ 340 341 if (rtp->prio > RTP_PRIO_MAX) 342 return (EINVAL); 343 switch (RTP_PRIO_BASE(rtp->type)) { 344 case RTP_PRIO_REALTIME: 345 kg->kg_user_pri = PRI_MIN_REALTIME + rtp->prio; 346 break; 347 case RTP_PRIO_NORMAL: 348 kg->kg_user_pri = PRI_MIN_TIMESHARE + rtp->prio; 349 break; 350 case RTP_PRIO_IDLE: 351 kg->kg_user_pri = PRI_MIN_IDLE + rtp->prio; 352 break; 353 default: 354 return (EINVAL); 355 } 356 kg->kg_pri_class = rtp->type; 357 if (curthread->td_ksegrp == kg) { 358 curthread->td_base_pri = kg->kg_user_pri; 359 curthread->td_priority = kg->kg_user_pri; /* XXX dubious */ 360 } 361 return (0); 362} 363 364void 365pri_to_rtp(struct ksegrp *kg, struct rtprio *rtp) 366{ 367 368 switch (PRI_BASE(kg->kg_pri_class)) { 369 case PRI_REALTIME: 370 rtp->prio = kg->kg_user_pri - PRI_MIN_REALTIME; 371 break; 372 case PRI_TIMESHARE: 373 rtp->prio = kg->kg_user_pri - PRI_MIN_TIMESHARE; 374 break; 375 case PRI_IDLE: 376 rtp->prio = kg->kg_user_pri - PRI_MIN_IDLE; 377 break; 378 default: 379 break; 380 } 381 rtp->type = kg->kg_pri_class; 382} 383 384#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 385#ifndef _SYS_SYSPROTO_H_ 386struct osetrlimit_args { 387 u_int which; 388 struct orlimit *rlp; 389}; 390#endif 391/* 392 * MPSAFE 393 */ 394/* ARGSUSED */ 395int 396osetrlimit(td, uap) 397 struct thread *td; 398 register struct osetrlimit_args *uap; 399{ 400 struct orlimit olim; 401 struct rlimit lim; 402 int error; 403 404 if ((error = 405 copyin((caddr_t)uap->rlp, (caddr_t)&olim, sizeof(struct orlimit)))) 406 return (error); 407 lim.rlim_cur = olim.rlim_cur; 408 lim.rlim_max = olim.rlim_max; 409 mtx_lock(&Giant); 410 error = dosetrlimit(td, uap->which, &lim); 411 mtx_unlock(&Giant); 412 return (error); 413} 414 415#ifndef _SYS_SYSPROTO_H_ 416struct ogetrlimit_args { 417 u_int which; 418 struct orlimit *rlp; 419}; 420#endif 421/* 422 * MPSAFE 423 */ 424/* ARGSUSED */ 425int 426ogetrlimit(td, uap) 427 struct thread *td; 428 register struct ogetrlimit_args *uap; 429{ 430 struct proc *p = td->td_proc; 431 struct orlimit olim; 432 int error; 433 434 if (uap->which >= RLIM_NLIMITS) 435 return (EINVAL); 436 mtx_lock(&Giant); 437 olim.rlim_cur = p->p_rlimit[uap->which].rlim_cur; 438 if (olim.rlim_cur == -1) 439 olim.rlim_cur = 0x7fffffff; 440 olim.rlim_max = p->p_rlimit[uap->which].rlim_max; 441 if (olim.rlim_max == -1) 442 olim.rlim_max = 0x7fffffff; 443 error = copyout((caddr_t)&olim, (caddr_t)uap->rlp, sizeof(olim)); 444 mtx_unlock(&Giant); 445 return (error); 446} 447#endif /* COMPAT_43 || COMPAT_SUNOS */ 448 449#ifndef _SYS_SYSPROTO_H_ 450struct __setrlimit_args { 451 u_int which; 452 struct rlimit *rlp; 453}; 454#endif 455/* 456 * MPSAFE 457 */ 458/* ARGSUSED */ 459int 460setrlimit(td, uap) 461 struct thread *td; 462 register struct __setrlimit_args *uap; 463{ 464 struct rlimit alim; 465 int error; 466 467 if ((error = 468 copyin((caddr_t)uap->rlp, (caddr_t)&alim, sizeof (struct rlimit)))) 469 return (error); 470 mtx_lock(&Giant); 471 error = dosetrlimit(td, uap->which, &alim); 472 mtx_unlock(&Giant); 473 return (error); 474} 475 476int 477dosetrlimit(td, which, limp) 478 struct thread *td; 479 u_int which; 480 struct rlimit *limp; 481{ 482 struct proc *p = td->td_proc; 483 register struct rlimit *alimp; 484 int error; 485 486 GIANT_REQUIRED; 487 488 if (which >= RLIM_NLIMITS) 489 return (EINVAL); 490 alimp = &p->p_rlimit[which]; 491 492 /* 493 * Preserve historical bugs by treating negative limits as unsigned. 494 */ 495 if (limp->rlim_cur < 0) 496 limp->rlim_cur = RLIM_INFINITY; 497 if (limp->rlim_max < 0) 498 limp->rlim_max = RLIM_INFINITY; 499 500 if (limp->rlim_cur > alimp->rlim_max || 501 limp->rlim_max > alimp->rlim_max) 502 if ((error = suser_xxx(0, p, PRISON_ROOT))) 503 return (error); 504 if (limp->rlim_cur > limp->rlim_max) 505 limp->rlim_cur = limp->rlim_max; 506 if (p->p_limit->p_refcnt > 1 && 507 (p->p_limit->p_lflags & PL_SHAREMOD) == 0) { 508 p->p_limit->p_refcnt--; 509 p->p_limit = limcopy(p->p_limit); 510 alimp = &p->p_rlimit[which]; 511 } 512 513 switch (which) { 514 515 case RLIMIT_CPU: 516 if (limp->rlim_cur > RLIM_INFINITY / (rlim_t)1000000) 517 p->p_limit->p_cpulimit = RLIM_INFINITY; 518 else 519 p->p_limit->p_cpulimit = 520 (rlim_t)1000000 * limp->rlim_cur; 521 break; 522 case RLIMIT_DATA: 523 if (limp->rlim_cur > maxdsiz) 524 limp->rlim_cur = maxdsiz; 525 if (limp->rlim_max > maxdsiz) 526 limp->rlim_max = maxdsiz; 527 break; 528 529 case RLIMIT_STACK: 530 if (limp->rlim_cur > maxssiz) 531 limp->rlim_cur = maxssiz; 532 if (limp->rlim_max > maxssiz) 533 limp->rlim_max = maxssiz; 534 /* 535 * Stack is allocated to the max at exec time with only 536 * "rlim_cur" bytes accessible. If stack limit is going 537 * up make more accessible, if going down make inaccessible. 538 */ 539 if (limp->rlim_cur != alimp->rlim_cur) { 540 vm_offset_t addr; 541 vm_size_t size; 542 vm_prot_t prot; 543 544 if (limp->rlim_cur > alimp->rlim_cur) { 545 prot = VM_PROT_ALL; 546 size = limp->rlim_cur - alimp->rlim_cur; 547 addr = USRSTACK - limp->rlim_cur; 548 } else { 549 prot = VM_PROT_NONE; 550 size = alimp->rlim_cur - limp->rlim_cur; 551 addr = USRSTACK - alimp->rlim_cur; 552 } 553 addr = trunc_page(addr); 554 size = round_page(size); 555 (void) vm_map_protect(&p->p_vmspace->vm_map, 556 addr, addr+size, prot, FALSE); 557 } 558 break; 559 560 case RLIMIT_NOFILE: 561 if (limp->rlim_cur > maxfilesperproc) 562 limp->rlim_cur = maxfilesperproc; 563 if (limp->rlim_max > maxfilesperproc) 564 limp->rlim_max = maxfilesperproc; 565 break; 566 567 case RLIMIT_NPROC: 568 if (limp->rlim_cur > maxprocperuid) 569 limp->rlim_cur = maxprocperuid; 570 if (limp->rlim_max > maxprocperuid) 571 limp->rlim_max = maxprocperuid; 572 if (limp->rlim_cur < 1) 573 limp->rlim_cur = 1; 574 if (limp->rlim_max < 1) 575 limp->rlim_max = 1; 576 break; 577 } 578 *alimp = *limp; 579 return (0); 580} 581 582#ifndef _SYS_SYSPROTO_H_ 583struct __getrlimit_args { 584 u_int which; 585 struct rlimit *rlp; 586}; 587#endif 588/* 589 * MPSAFE 590 */ 591/* ARGSUSED */ 592int 593getrlimit(td, uap) 594 struct thread *td; 595 register struct __getrlimit_args *uap; 596{ 597 int error; 598 struct proc *p = td->td_proc; 599 600 if (uap->which >= RLIM_NLIMITS) 601 return (EINVAL); 602 mtx_lock(&Giant); 603 error = copyout((caddr_t)&p->p_rlimit[uap->which], (caddr_t)uap->rlp, 604 sizeof (struct rlimit)); 605 mtx_unlock(&Giant); 606 return(error); 607} 608 609/* 610 * Transform the running time and tick information in proc p into user, 611 * system, and interrupt time usage. 612 */ 613void 614calcru(p, up, sp, ip) 615 struct proc *p; 616 struct timeval *up; 617 struct timeval *sp; 618 struct timeval *ip; 619{ 620 /* {user, system, interrupt, total} {ticks, usec}; previous tu: */ 621 u_int64_t ut, uu, st, su, it, iu, tt, tu, ptu; 622 u_int64_t uut = 0, sut = 0, iut = 0; 623 int s; 624 struct timeval tv; 625 struct bintime bt; 626 struct kse *ke; 627 struct ksegrp *kg; 628 629 mtx_assert(&sched_lock, MA_OWNED); 630 /* XXX: why spl-protect ? worst case is an off-by-one report */ 631 632 FOREACH_KSEGRP_IN_PROC(p, kg) { 633 /* we could accumulate per ksegrp and per process here*/ 634 FOREACH_KSE_IN_GROUP(kg, ke) { 635 s = splstatclock(); 636 ut = ke->ke_uticks; 637 st = ke->ke_sticks; 638 it = ke->ke_iticks; 639 splx(s); 640 641 tt = ut + st + it; 642 if (tt == 0) { 643 st = 1; 644 tt = 1; 645 } 646 647 if (ke == curthread->td_kse) { 648 /* 649 * Adjust for the current time slice. This is actually fairly 650 * important since the error here is on the order of a time 651 * quantum, which is much greater than the sampling error. 652 * XXXKSE use a different test due to threads on other 653 * processors also being 'current'. 654 */ 655 656 binuptime(&bt); 657 bintime_sub(&bt, PCPU_PTR(switchtime)); 658 bintime_add(&bt, &p->p_runtime); 659 } else { 660 bt = p->p_runtime; 661 } 662 bintime2timeval(&bt, &tv); 663 tu = tv.tv_sec * (u_int64_t)1000000 + tv.tv_usec; 664 ptu = ke->ke_uu + ke->ke_su + ke->ke_iu; 665 if (tu < ptu || (int64_t)tu < 0) { 666 /* XXX no %qd in kernel. Truncate. */ 667 printf("calcru: negative time of %ld usec for pid %d (%s)\n", 668 (long)tu, p->p_pid, p->p_comm); 669 tu = ptu; 670 } 671 672 /* Subdivide tu. */ 673 uu = (tu * ut) / tt; 674 su = (tu * st) / tt; 675 iu = tu - uu - su; 676 677 /* Enforce monotonicity. */ 678 if (uu < ke->ke_uu || su < ke->ke_su || iu < ke->ke_iu) { 679 if (uu < ke->ke_uu) 680 uu = ke->ke_uu; 681 else if (uu + ke->ke_su + ke->ke_iu > tu) 682 uu = tu - ke->ke_su - ke->ke_iu; 683 if (st == 0) 684 su = ke->ke_su; 685 else { 686 su = ((tu - uu) * st) / (st + it); 687 if (su < ke->ke_su) 688 su = ke->ke_su; 689 else if (uu + su + ke->ke_iu > tu) 690 su = tu - uu - ke->ke_iu; 691 } 692 KASSERT(uu + su + ke->ke_iu <= tu, 693 ("calcru: monotonisation botch 1")); 694 iu = tu - uu - su; 695 KASSERT(iu >= ke->ke_iu, 696 ("calcru: monotonisation botch 2")); 697 } 698 ke->ke_uu = uu; 699 ke->ke_su = su; 700 ke->ke_iu = iu; 701 uut += uu; 702 sut += su; 703 iut += iu; 704 705 } /* end kse loop */ 706 } /* end kseg loop */ 707 up->tv_sec = uut / 1000000; 708 up->tv_usec = uut % 1000000; 709 sp->tv_sec = sut / 1000000; 710 sp->tv_usec = sut % 1000000; 711 if (ip != NULL) { 712 ip->tv_sec = iut / 1000000; 713 ip->tv_usec = iut % 1000000; 714 } 715} 716 717#ifndef _SYS_SYSPROTO_H_ 718struct getrusage_args { 719 int who; 720 struct rusage *rusage; 721}; 722#endif 723/* 724 * MPSAFE 725 */ 726/* ARGSUSED */ 727int 728getrusage(td, uap) 729 register struct thread *td; 730 register struct getrusage_args *uap; 731{ 732 struct proc *p = td->td_proc; 733 register struct rusage *rup; 734 int error = 0; 735 736 mtx_lock(&Giant); 737 738 switch (uap->who) { 739 case RUSAGE_SELF: 740 rup = &p->p_stats->p_ru; 741 mtx_lock_spin(&sched_lock); 742 calcru(p, &rup->ru_utime, &rup->ru_stime, NULL); 743 mtx_unlock_spin(&sched_lock); 744 break; 745 746 case RUSAGE_CHILDREN: 747 rup = &p->p_stats->p_cru; 748 break; 749 750 default: 751 rup = NULL; 752 error = EINVAL; 753 break; 754 } 755 mtx_unlock(&Giant); 756 if (error == 0) { 757 error = copyout((caddr_t)rup, (caddr_t)uap->rusage, 758 sizeof (struct rusage)); 759 } 760 return(error); 761} 762 763void 764ruadd(ru, ru2) 765 register struct rusage *ru, *ru2; 766{ 767 register long *ip, *ip2; 768 register int i; 769 770 timevaladd(&ru->ru_utime, &ru2->ru_utime); 771 timevaladd(&ru->ru_stime, &ru2->ru_stime); 772 if (ru->ru_maxrss < ru2->ru_maxrss) 773 ru->ru_maxrss = ru2->ru_maxrss; 774 ip = &ru->ru_first; ip2 = &ru2->ru_first; 775 for (i = &ru->ru_last - &ru->ru_first; i >= 0; i--) 776 *ip++ += *ip2++; 777} 778 779/* 780 * Make a copy of the plimit structure. 781 * We share these structures copy-on-write after fork, 782 * and copy when a limit is changed. 783 */ 784struct plimit * 785limcopy(lim) 786 struct plimit *lim; 787{ 788 register struct plimit *copy; 789 790 MALLOC(copy, struct plimit *, sizeof(struct plimit), 791 M_SUBPROC, M_WAITOK); 792 bcopy(lim->pl_rlimit, copy->pl_rlimit, sizeof(struct plimit)); 793 copy->p_lflags = 0; 794 copy->p_refcnt = 1; 795 return (copy); 796} 797 798/* 799 * Find the uidinfo structure for a uid. This structure is used to 800 * track the total resource consumption (process count, socket buffer 801 * size, etc.) for the uid and impose limits. 802 */ 803void 804uihashinit() 805{ 806 807 uihashtbl = hashinit(maxproc / 16, M_UIDINFO, &uihash); 808 mtx_init(&uihashtbl_mtx, "uidinfo hash", MTX_DEF); 809} 810 811/* 812 * lookup a uidinfo struct for the parameter uid. 813 * uihashtbl_mtx must be locked. 814 */ 815static struct uidinfo * 816uilookup(uid) 817 uid_t uid; 818{ 819 struct uihashhead *uipp; 820 struct uidinfo *uip; 821 822 mtx_assert(&uihashtbl_mtx, MA_OWNED); 823 uipp = UIHASH(uid); 824 LIST_FOREACH(uip, uipp, ui_hash) 825 if (uip->ui_uid == uid) 826 break; 827 828 return (uip); 829} 830 831/* 832 * Find or allocate a struct uidinfo for a particular uid. 833 * Increase refcount on uidinfo struct returned. 834 * uifree() should be called on a struct uidinfo when released. 835 */ 836struct uidinfo * 837uifind(uid) 838 uid_t uid; 839{ 840 struct uidinfo *uip; 841 842 mtx_lock(&uihashtbl_mtx); 843 uip = uilookup(uid); 844 if (uip == NULL) { 845 struct uidinfo *old_uip; 846 847 mtx_unlock(&uihashtbl_mtx); 848 uip = malloc(sizeof(*uip), M_UIDINFO, M_WAITOK | M_ZERO); 849 mtx_lock(&uihashtbl_mtx); 850 /* 851 * There's a chance someone created our uidinfo while we 852 * were in malloc and not holding the lock, so we have to 853 * make sure we don't insert a duplicate uidinfo 854 */ 855 if ((old_uip = uilookup(uid)) != NULL) { 856 /* someone else beat us to it */ 857 free(uip, M_UIDINFO); 858 uip = old_uip; 859 } else { 860 uip->ui_mtxp = mtx_pool_alloc(); 861 uip->ui_uid = uid; 862 LIST_INSERT_HEAD(UIHASH(uid), uip, ui_hash); 863 } 864 } 865 uihold(uip); 866 mtx_unlock(&uihashtbl_mtx); 867 return (uip); 868} 869 870/* 871 * Place another refcount on a uidinfo struct. 872 */ 873void 874uihold(uip) 875 struct uidinfo *uip; 876{ 877 878 UIDINFO_LOCK(uip); 879 uip->ui_ref++; 880 UIDINFO_UNLOCK(uip); 881} 882 883/*- 884 * Since uidinfo structs have a long lifetime, we use an 885 * opportunistic refcounting scheme to avoid locking the lookup hash 886 * for each release. 887 * 888 * If the refcount hits 0, we need to free the structure, 889 * which means we need to lock the hash. 890 * Optimal case: 891 * After locking the struct and lowering the refcount, if we find 892 * that we don't need to free, simply unlock and return. 893 * Suboptimal case: 894 * If refcount lowering results in need to free, bump the count 895 * back up, loose the lock and aquire the locks in the proper 896 * order to try again. 897 */ 898void 899uifree(uip) 900 struct uidinfo *uip; 901{ 902 903 /* Prepare for optimal case. */ 904 UIDINFO_LOCK(uip); 905 906 if (--uip->ui_ref != 0) { 907 UIDINFO_UNLOCK(uip); 908 return; 909 } 910 911 /* Prepare for suboptimal case. */ 912 uip->ui_ref++; 913 UIDINFO_UNLOCK(uip); 914 mtx_lock(&uihashtbl_mtx); 915 UIDINFO_LOCK(uip); 916 917 /* 918 * We must subtract one from the count again because we backed out 919 * our initial subtraction before dropping the lock. 920 * Since another thread may have added a reference after we dropped the 921 * initial lock we have to test for zero again. 922 */ 923 if (--uip->ui_ref == 0) { 924 LIST_REMOVE(uip, ui_hash); 925 mtx_unlock(&uihashtbl_mtx); 926 if (uip->ui_sbsize != 0) 927 /* XXX no %qd in kernel. Truncate. */ 928 printf("freeing uidinfo: uid = %d, sbsize = %ld\n", 929 uip->ui_uid, (long)uip->ui_sbsize); 930 if (uip->ui_proccnt != 0) 931 printf("freeing uidinfo: uid = %d, proccnt = %ld\n", 932 uip->ui_uid, uip->ui_proccnt); 933 UIDINFO_UNLOCK(uip); 934 FREE(uip, M_UIDINFO); 935 return; 936 } 937 938 mtx_unlock(&uihashtbl_mtx); 939 UIDINFO_UNLOCK(uip); 940} 941 942/* 943 * Change the count associated with number of processes 944 * a given user is using. When 'max' is 0, don't enforce a limit 945 */ 946int 947chgproccnt(uip, diff, max) 948 struct uidinfo *uip; 949 int diff; 950 int max; 951{ 952 953 UIDINFO_LOCK(uip); 954 /* don't allow them to exceed max, but allow subtraction */ 955 if (diff > 0 && uip->ui_proccnt + diff > max && max != 0) { 956 UIDINFO_UNLOCK(uip); 957 return (0); 958 } 959 uip->ui_proccnt += diff; 960 if (uip->ui_proccnt < 0) 961 printf("negative proccnt for uid = %d\n", uip->ui_uid); 962 UIDINFO_UNLOCK(uip); 963 return (1); 964} 965 966/* 967 * Change the total socket buffer size a user has used. 968 */ 969int 970chgsbsize(uip, hiwat, to, max) 971 struct uidinfo *uip; 972 u_long *hiwat; 973 u_long to; 974 rlim_t max; 975{ 976 rlim_t new; 977 int s; 978 979 s = splnet(); 980 UIDINFO_LOCK(uip); 981 new = uip->ui_sbsize + to - *hiwat; 982 /* don't allow them to exceed max, but allow subtraction */ 983 if (to > *hiwat && new > max) { 984 splx(s); 985 UIDINFO_UNLOCK(uip); 986 return (0); 987 } 988 uip->ui_sbsize = new; 989 *hiwat = to; 990 if (uip->ui_sbsize < 0) 991 printf("negative sbsize for uid = %d\n", uip->ui_uid); 992 splx(s); 993 UIDINFO_UNLOCK(uip); 994 return (1); 995}
| 220 break; 221 } 222 223 case PRIO_USER: 224 if (uap->who == 0) 225 uap->who = curp->p_ucred->cr_uid; 226 sx_slock(&allproc_lock); 227 FOREACH_PROC_IN_SYSTEM(p) { 228 if (p->p_ucred->cr_uid == uap->who && 229 !p_cansee(curp, p)) { 230 error = donice(curp, p, uap->prio); 231 found++; 232 } 233 } 234 sx_sunlock(&allproc_lock); 235 break; 236 237 default: 238 error = EINVAL; 239 break; 240 } 241 if (found == 0 && error == 0) 242 error = ESRCH; 243 mtx_unlock(&Giant); 244 return (error); 245} 246 247static int 248donice(curp, chgp, n) 249 register struct proc *curp, *chgp; 250 register int n; 251{ 252 int error; 253 254 if ((error = p_cansched(curp, chgp))) 255 return (error); 256 if (n > PRIO_MAX) 257 n = PRIO_MAX; 258 if (n < PRIO_MIN) 259 n = PRIO_MIN; 260 if (n < chgp->p_ksegrp.kg_nice /* XXXKSE */ && 261 suser_xxx(curp->p_ucred, NULL, 0)) 262 return (EACCES); 263 chgp->p_ksegrp.kg_nice /* XXXKSE */ = n; 264 (void)resetpriority(&chgp->p_ksegrp); /* XXXKSE */ 265 return (0); 266} 267 268/* rtprio system call */ 269#ifndef _SYS_SYSPROTO_H_ 270struct rtprio_args { 271 int function; 272 pid_t pid; 273 struct rtprio *rtp; 274}; 275#endif 276 277/* 278 * Set realtime priority 279 */ 280 281/* 282 * MPSAFE 283 */ 284/* ARGSUSED */ 285int 286rtprio(td, uap) 287 struct thread *td; 288 register struct rtprio_args *uap; 289{ 290 struct proc *curp = td->td_proc; 291 register struct proc *p; 292 struct rtprio rtp; 293 int error; 294 295 mtx_lock(&Giant); 296 297 if (uap->pid == 0) { 298 p = curp; 299 PROC_LOCK(p); 300 } else { 301 p = pfind(uap->pid); 302 } 303 304 if (p == NULL) { 305 error = ESRCH; 306 goto done2; 307 } 308 309 switch (uap->function) { 310 case RTP_LOOKUP: 311 if ((error = p_cansee(curp, p))) 312 break; 313 mtx_lock_spin(&sched_lock); 314 pri_to_rtp(&p->p_ksegrp /* XXXKSE */ , &rtp); 315 mtx_unlock_spin(&sched_lock); 316 error = copyout(&rtp, uap->rtp, sizeof(struct rtprio)); 317 break; 318 case RTP_SET: 319 if ((error = p_cansched(curp, p)) || 320 (error = copyin(uap->rtp, &rtp, sizeof(struct rtprio)))) 321 break; 322 /* disallow setting rtprio in most cases if not superuser */ 323 if (suser_xxx(curp->p_ucred, NULL, 0) != 0) { 324 /* can't set someone else's */ 325 if (uap->pid) { 326 error = EPERM; 327 break; 328 } 329 /* can't set realtime priority */ 330/* 331 * Realtime priority has to be restricted for reasons which should be 332 * obvious. However, for idle priority, there is a potential for 333 * system deadlock if an idleprio process gains a lock on a resource 334 * that other processes need (and the idleprio process can't run 335 * due to a CPU-bound normal process). Fix me! XXX 336 */ 337#if 0 338 if (RTP_PRIO_IS_REALTIME(rtp.type)) 339#endif 340 if (rtp.type != RTP_PRIO_NORMAL) { 341 error = EPERM; 342 break; 343 } 344 } 345 mtx_lock_spin(&sched_lock); 346 error = rtp_to_pri(&rtp, &p->p_ksegrp); 347 mtx_unlock_spin(&sched_lock); 348 break; 349 default: 350 error = EINVAL; 351 break; 352 } 353 PROC_UNLOCK(p); 354done2: 355 mtx_unlock(&Giant); 356 return (error); 357} 358 359int 360rtp_to_pri(struct rtprio *rtp, struct ksegrp *kg) 361{ 362 363 if (rtp->prio > RTP_PRIO_MAX) 364 return (EINVAL); 365 switch (RTP_PRIO_BASE(rtp->type)) { 366 case RTP_PRIO_REALTIME: 367 kg->kg_user_pri = PRI_MIN_REALTIME + rtp->prio; 368 break; 369 case RTP_PRIO_NORMAL: 370 kg->kg_user_pri = PRI_MIN_TIMESHARE + rtp->prio; 371 break; 372 case RTP_PRIO_IDLE: 373 kg->kg_user_pri = PRI_MIN_IDLE + rtp->prio; 374 break; 375 default: 376 return (EINVAL); 377 } 378 kg->kg_pri_class = rtp->type; 379 if (curthread->td_ksegrp == kg) { 380 curthread->td_base_pri = kg->kg_user_pri; 381 curthread->td_priority = kg->kg_user_pri; /* XXX dubious */ 382 } 383 return (0); 384} 385 386void 387pri_to_rtp(struct ksegrp *kg, struct rtprio *rtp) 388{ 389 390 switch (PRI_BASE(kg->kg_pri_class)) { 391 case PRI_REALTIME: 392 rtp->prio = kg->kg_user_pri - PRI_MIN_REALTIME; 393 break; 394 case PRI_TIMESHARE: 395 rtp->prio = kg->kg_user_pri - PRI_MIN_TIMESHARE; 396 break; 397 case PRI_IDLE: 398 rtp->prio = kg->kg_user_pri - PRI_MIN_IDLE; 399 break; 400 default: 401 break; 402 } 403 rtp->type = kg->kg_pri_class; 404} 405 406#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 407#ifndef _SYS_SYSPROTO_H_ 408struct osetrlimit_args { 409 u_int which; 410 struct orlimit *rlp; 411}; 412#endif 413/* 414 * MPSAFE 415 */ 416/* ARGSUSED */ 417int 418osetrlimit(td, uap) 419 struct thread *td; 420 register struct osetrlimit_args *uap; 421{ 422 struct orlimit olim; 423 struct rlimit lim; 424 int error; 425 426 if ((error = 427 copyin((caddr_t)uap->rlp, (caddr_t)&olim, sizeof(struct orlimit)))) 428 return (error); 429 lim.rlim_cur = olim.rlim_cur; 430 lim.rlim_max = olim.rlim_max; 431 mtx_lock(&Giant); 432 error = dosetrlimit(td, uap->which, &lim); 433 mtx_unlock(&Giant); 434 return (error); 435} 436 437#ifndef _SYS_SYSPROTO_H_ 438struct ogetrlimit_args { 439 u_int which; 440 struct orlimit *rlp; 441}; 442#endif 443/* 444 * MPSAFE 445 */ 446/* ARGSUSED */ 447int 448ogetrlimit(td, uap) 449 struct thread *td; 450 register struct ogetrlimit_args *uap; 451{ 452 struct proc *p = td->td_proc; 453 struct orlimit olim; 454 int error; 455 456 if (uap->which >= RLIM_NLIMITS) 457 return (EINVAL); 458 mtx_lock(&Giant); 459 olim.rlim_cur = p->p_rlimit[uap->which].rlim_cur; 460 if (olim.rlim_cur == -1) 461 olim.rlim_cur = 0x7fffffff; 462 olim.rlim_max = p->p_rlimit[uap->which].rlim_max; 463 if (olim.rlim_max == -1) 464 olim.rlim_max = 0x7fffffff; 465 error = copyout((caddr_t)&olim, (caddr_t)uap->rlp, sizeof(olim)); 466 mtx_unlock(&Giant); 467 return (error); 468} 469#endif /* COMPAT_43 || COMPAT_SUNOS */ 470 471#ifndef _SYS_SYSPROTO_H_ 472struct __setrlimit_args { 473 u_int which; 474 struct rlimit *rlp; 475}; 476#endif 477/* 478 * MPSAFE 479 */ 480/* ARGSUSED */ 481int 482setrlimit(td, uap) 483 struct thread *td; 484 register struct __setrlimit_args *uap; 485{ 486 struct rlimit alim; 487 int error; 488 489 if ((error = 490 copyin((caddr_t)uap->rlp, (caddr_t)&alim, sizeof (struct rlimit)))) 491 return (error); 492 mtx_lock(&Giant); 493 error = dosetrlimit(td, uap->which, &alim); 494 mtx_unlock(&Giant); 495 return (error); 496} 497 498int 499dosetrlimit(td, which, limp) 500 struct thread *td; 501 u_int which; 502 struct rlimit *limp; 503{ 504 struct proc *p = td->td_proc; 505 register struct rlimit *alimp; 506 int error; 507 508 GIANT_REQUIRED; 509 510 if (which >= RLIM_NLIMITS) 511 return (EINVAL); 512 alimp = &p->p_rlimit[which]; 513 514 /* 515 * Preserve historical bugs by treating negative limits as unsigned. 516 */ 517 if (limp->rlim_cur < 0) 518 limp->rlim_cur = RLIM_INFINITY; 519 if (limp->rlim_max < 0) 520 limp->rlim_max = RLIM_INFINITY; 521 522 if (limp->rlim_cur > alimp->rlim_max || 523 limp->rlim_max > alimp->rlim_max) 524 if ((error = suser_xxx(0, p, PRISON_ROOT))) 525 return (error); 526 if (limp->rlim_cur > limp->rlim_max) 527 limp->rlim_cur = limp->rlim_max; 528 if (p->p_limit->p_refcnt > 1 && 529 (p->p_limit->p_lflags & PL_SHAREMOD) == 0) { 530 p->p_limit->p_refcnt--; 531 p->p_limit = limcopy(p->p_limit); 532 alimp = &p->p_rlimit[which]; 533 } 534 535 switch (which) { 536 537 case RLIMIT_CPU: 538 if (limp->rlim_cur > RLIM_INFINITY / (rlim_t)1000000) 539 p->p_limit->p_cpulimit = RLIM_INFINITY; 540 else 541 p->p_limit->p_cpulimit = 542 (rlim_t)1000000 * limp->rlim_cur; 543 break; 544 case RLIMIT_DATA: 545 if (limp->rlim_cur > maxdsiz) 546 limp->rlim_cur = maxdsiz; 547 if (limp->rlim_max > maxdsiz) 548 limp->rlim_max = maxdsiz; 549 break; 550 551 case RLIMIT_STACK: 552 if (limp->rlim_cur > maxssiz) 553 limp->rlim_cur = maxssiz; 554 if (limp->rlim_max > maxssiz) 555 limp->rlim_max = maxssiz; 556 /* 557 * Stack is allocated to the max at exec time with only 558 * "rlim_cur" bytes accessible. If stack limit is going 559 * up make more accessible, if going down make inaccessible. 560 */ 561 if (limp->rlim_cur != alimp->rlim_cur) { 562 vm_offset_t addr; 563 vm_size_t size; 564 vm_prot_t prot; 565 566 if (limp->rlim_cur > alimp->rlim_cur) { 567 prot = VM_PROT_ALL; 568 size = limp->rlim_cur - alimp->rlim_cur; 569 addr = USRSTACK - limp->rlim_cur; 570 } else { 571 prot = VM_PROT_NONE; 572 size = alimp->rlim_cur - limp->rlim_cur; 573 addr = USRSTACK - alimp->rlim_cur; 574 } 575 addr = trunc_page(addr); 576 size = round_page(size); 577 (void) vm_map_protect(&p->p_vmspace->vm_map, 578 addr, addr+size, prot, FALSE); 579 } 580 break; 581 582 case RLIMIT_NOFILE: 583 if (limp->rlim_cur > maxfilesperproc) 584 limp->rlim_cur = maxfilesperproc; 585 if (limp->rlim_max > maxfilesperproc) 586 limp->rlim_max = maxfilesperproc; 587 break; 588 589 case RLIMIT_NPROC: 590 if (limp->rlim_cur > maxprocperuid) 591 limp->rlim_cur = maxprocperuid; 592 if (limp->rlim_max > maxprocperuid) 593 limp->rlim_max = maxprocperuid; 594 if (limp->rlim_cur < 1) 595 limp->rlim_cur = 1; 596 if (limp->rlim_max < 1) 597 limp->rlim_max = 1; 598 break; 599 } 600 *alimp = *limp; 601 return (0); 602} 603 604#ifndef _SYS_SYSPROTO_H_ 605struct __getrlimit_args { 606 u_int which; 607 struct rlimit *rlp; 608}; 609#endif 610/* 611 * MPSAFE 612 */ 613/* ARGSUSED */ 614int 615getrlimit(td, uap) 616 struct thread *td; 617 register struct __getrlimit_args *uap; 618{ 619 int error; 620 struct proc *p = td->td_proc; 621 622 if (uap->which >= RLIM_NLIMITS) 623 return (EINVAL); 624 mtx_lock(&Giant); 625 error = copyout((caddr_t)&p->p_rlimit[uap->which], (caddr_t)uap->rlp, 626 sizeof (struct rlimit)); 627 mtx_unlock(&Giant); 628 return(error); 629} 630 631/* 632 * Transform the running time and tick information in proc p into user, 633 * system, and interrupt time usage. 634 */ 635void 636calcru(p, up, sp, ip) 637 struct proc *p; 638 struct timeval *up; 639 struct timeval *sp; 640 struct timeval *ip; 641{ 642 /* {user, system, interrupt, total} {ticks, usec}; previous tu: */ 643 u_int64_t ut, uu, st, su, it, iu, tt, tu, ptu; 644 u_int64_t uut = 0, sut = 0, iut = 0; 645 int s; 646 struct timeval tv; 647 struct bintime bt; 648 struct kse *ke; 649 struct ksegrp *kg; 650 651 mtx_assert(&sched_lock, MA_OWNED); 652 /* XXX: why spl-protect ? worst case is an off-by-one report */ 653 654 FOREACH_KSEGRP_IN_PROC(p, kg) { 655 /* we could accumulate per ksegrp and per process here*/ 656 FOREACH_KSE_IN_GROUP(kg, ke) { 657 s = splstatclock(); 658 ut = ke->ke_uticks; 659 st = ke->ke_sticks; 660 it = ke->ke_iticks; 661 splx(s); 662 663 tt = ut + st + it; 664 if (tt == 0) { 665 st = 1; 666 tt = 1; 667 } 668 669 if (ke == curthread->td_kse) { 670 /* 671 * Adjust for the current time slice. This is actually fairly 672 * important since the error here is on the order of a time 673 * quantum, which is much greater than the sampling error. 674 * XXXKSE use a different test due to threads on other 675 * processors also being 'current'. 676 */ 677 678 binuptime(&bt); 679 bintime_sub(&bt, PCPU_PTR(switchtime)); 680 bintime_add(&bt, &p->p_runtime); 681 } else { 682 bt = p->p_runtime; 683 } 684 bintime2timeval(&bt, &tv); 685 tu = tv.tv_sec * (u_int64_t)1000000 + tv.tv_usec; 686 ptu = ke->ke_uu + ke->ke_su + ke->ke_iu; 687 if (tu < ptu || (int64_t)tu < 0) { 688 /* XXX no %qd in kernel. Truncate. */ 689 printf("calcru: negative time of %ld usec for pid %d (%s)\n", 690 (long)tu, p->p_pid, p->p_comm); 691 tu = ptu; 692 } 693 694 /* Subdivide tu. */ 695 uu = (tu * ut) / tt; 696 su = (tu * st) / tt; 697 iu = tu - uu - su; 698 699 /* Enforce monotonicity. */ 700 if (uu < ke->ke_uu || su < ke->ke_su || iu < ke->ke_iu) { 701 if (uu < ke->ke_uu) 702 uu = ke->ke_uu; 703 else if (uu + ke->ke_su + ke->ke_iu > tu) 704 uu = tu - ke->ke_su - ke->ke_iu; 705 if (st == 0) 706 su = ke->ke_su; 707 else { 708 su = ((tu - uu) * st) / (st + it); 709 if (su < ke->ke_su) 710 su = ke->ke_su; 711 else if (uu + su + ke->ke_iu > tu) 712 su = tu - uu - ke->ke_iu; 713 } 714 KASSERT(uu + su + ke->ke_iu <= tu, 715 ("calcru: monotonisation botch 1")); 716 iu = tu - uu - su; 717 KASSERT(iu >= ke->ke_iu, 718 ("calcru: monotonisation botch 2")); 719 } 720 ke->ke_uu = uu; 721 ke->ke_su = su; 722 ke->ke_iu = iu; 723 uut += uu; 724 sut += su; 725 iut += iu; 726 727 } /* end kse loop */ 728 } /* end kseg loop */ 729 up->tv_sec = uut / 1000000; 730 up->tv_usec = uut % 1000000; 731 sp->tv_sec = sut / 1000000; 732 sp->tv_usec = sut % 1000000; 733 if (ip != NULL) { 734 ip->tv_sec = iut / 1000000; 735 ip->tv_usec = iut % 1000000; 736 } 737} 738 739#ifndef _SYS_SYSPROTO_H_ 740struct getrusage_args { 741 int who; 742 struct rusage *rusage; 743}; 744#endif 745/* 746 * MPSAFE 747 */ 748/* ARGSUSED */ 749int 750getrusage(td, uap) 751 register struct thread *td; 752 register struct getrusage_args *uap; 753{ 754 struct proc *p = td->td_proc; 755 register struct rusage *rup; 756 int error = 0; 757 758 mtx_lock(&Giant); 759 760 switch (uap->who) { 761 case RUSAGE_SELF: 762 rup = &p->p_stats->p_ru; 763 mtx_lock_spin(&sched_lock); 764 calcru(p, &rup->ru_utime, &rup->ru_stime, NULL); 765 mtx_unlock_spin(&sched_lock); 766 break; 767 768 case RUSAGE_CHILDREN: 769 rup = &p->p_stats->p_cru; 770 break; 771 772 default: 773 rup = NULL; 774 error = EINVAL; 775 break; 776 } 777 mtx_unlock(&Giant); 778 if (error == 0) { 779 error = copyout((caddr_t)rup, (caddr_t)uap->rusage, 780 sizeof (struct rusage)); 781 } 782 return(error); 783} 784 785void 786ruadd(ru, ru2) 787 register struct rusage *ru, *ru2; 788{ 789 register long *ip, *ip2; 790 register int i; 791 792 timevaladd(&ru->ru_utime, &ru2->ru_utime); 793 timevaladd(&ru->ru_stime, &ru2->ru_stime); 794 if (ru->ru_maxrss < ru2->ru_maxrss) 795 ru->ru_maxrss = ru2->ru_maxrss; 796 ip = &ru->ru_first; ip2 = &ru2->ru_first; 797 for (i = &ru->ru_last - &ru->ru_first; i >= 0; i--) 798 *ip++ += *ip2++; 799} 800 801/* 802 * Make a copy of the plimit structure. 803 * We share these structures copy-on-write after fork, 804 * and copy when a limit is changed. 805 */ 806struct plimit * 807limcopy(lim) 808 struct plimit *lim; 809{ 810 register struct plimit *copy; 811 812 MALLOC(copy, struct plimit *, sizeof(struct plimit), 813 M_SUBPROC, M_WAITOK); 814 bcopy(lim->pl_rlimit, copy->pl_rlimit, sizeof(struct plimit)); 815 copy->p_lflags = 0; 816 copy->p_refcnt = 1; 817 return (copy); 818} 819 820/* 821 * Find the uidinfo structure for a uid. This structure is used to 822 * track the total resource consumption (process count, socket buffer 823 * size, etc.) for the uid and impose limits. 824 */ 825void 826uihashinit() 827{ 828 829 uihashtbl = hashinit(maxproc / 16, M_UIDINFO, &uihash); 830 mtx_init(&uihashtbl_mtx, "uidinfo hash", MTX_DEF); 831} 832 833/* 834 * lookup a uidinfo struct for the parameter uid. 835 * uihashtbl_mtx must be locked. 836 */ 837static struct uidinfo * 838uilookup(uid) 839 uid_t uid; 840{ 841 struct uihashhead *uipp; 842 struct uidinfo *uip; 843 844 mtx_assert(&uihashtbl_mtx, MA_OWNED); 845 uipp = UIHASH(uid); 846 LIST_FOREACH(uip, uipp, ui_hash) 847 if (uip->ui_uid == uid) 848 break; 849 850 return (uip); 851} 852 853/* 854 * Find or allocate a struct uidinfo for a particular uid. 855 * Increase refcount on uidinfo struct returned. 856 * uifree() should be called on a struct uidinfo when released. 857 */ 858struct uidinfo * 859uifind(uid) 860 uid_t uid; 861{ 862 struct uidinfo *uip; 863 864 mtx_lock(&uihashtbl_mtx); 865 uip = uilookup(uid); 866 if (uip == NULL) { 867 struct uidinfo *old_uip; 868 869 mtx_unlock(&uihashtbl_mtx); 870 uip = malloc(sizeof(*uip), M_UIDINFO, M_WAITOK | M_ZERO); 871 mtx_lock(&uihashtbl_mtx); 872 /* 873 * There's a chance someone created our uidinfo while we 874 * were in malloc and not holding the lock, so we have to 875 * make sure we don't insert a duplicate uidinfo 876 */ 877 if ((old_uip = uilookup(uid)) != NULL) { 878 /* someone else beat us to it */ 879 free(uip, M_UIDINFO); 880 uip = old_uip; 881 } else { 882 uip->ui_mtxp = mtx_pool_alloc(); 883 uip->ui_uid = uid; 884 LIST_INSERT_HEAD(UIHASH(uid), uip, ui_hash); 885 } 886 } 887 uihold(uip); 888 mtx_unlock(&uihashtbl_mtx); 889 return (uip); 890} 891 892/* 893 * Place another refcount on a uidinfo struct. 894 */ 895void 896uihold(uip) 897 struct uidinfo *uip; 898{ 899 900 UIDINFO_LOCK(uip); 901 uip->ui_ref++; 902 UIDINFO_UNLOCK(uip); 903} 904 905/*- 906 * Since uidinfo structs have a long lifetime, we use an 907 * opportunistic refcounting scheme to avoid locking the lookup hash 908 * for each release. 909 * 910 * If the refcount hits 0, we need to free the structure, 911 * which means we need to lock the hash. 912 * Optimal case: 913 * After locking the struct and lowering the refcount, if we find 914 * that we don't need to free, simply unlock and return. 915 * Suboptimal case: 916 * If refcount lowering results in need to free, bump the count 917 * back up, loose the lock and aquire the locks in the proper 918 * order to try again. 919 */ 920void 921uifree(uip) 922 struct uidinfo *uip; 923{ 924 925 /* Prepare for optimal case. */ 926 UIDINFO_LOCK(uip); 927 928 if (--uip->ui_ref != 0) { 929 UIDINFO_UNLOCK(uip); 930 return; 931 } 932 933 /* Prepare for suboptimal case. */ 934 uip->ui_ref++; 935 UIDINFO_UNLOCK(uip); 936 mtx_lock(&uihashtbl_mtx); 937 UIDINFO_LOCK(uip); 938 939 /* 940 * We must subtract one from the count again because we backed out 941 * our initial subtraction before dropping the lock. 942 * Since another thread may have added a reference after we dropped the 943 * initial lock we have to test for zero again. 944 */ 945 if (--uip->ui_ref == 0) { 946 LIST_REMOVE(uip, ui_hash); 947 mtx_unlock(&uihashtbl_mtx); 948 if (uip->ui_sbsize != 0) 949 /* XXX no %qd in kernel. Truncate. */ 950 printf("freeing uidinfo: uid = %d, sbsize = %ld\n", 951 uip->ui_uid, (long)uip->ui_sbsize); 952 if (uip->ui_proccnt != 0) 953 printf("freeing uidinfo: uid = %d, proccnt = %ld\n", 954 uip->ui_uid, uip->ui_proccnt); 955 UIDINFO_UNLOCK(uip); 956 FREE(uip, M_UIDINFO); 957 return; 958 } 959 960 mtx_unlock(&uihashtbl_mtx); 961 UIDINFO_UNLOCK(uip); 962} 963 964/* 965 * Change the count associated with number of processes 966 * a given user is using. When 'max' is 0, don't enforce a limit 967 */ 968int 969chgproccnt(uip, diff, max) 970 struct uidinfo *uip; 971 int diff; 972 int max; 973{ 974 975 UIDINFO_LOCK(uip); 976 /* don't allow them to exceed max, but allow subtraction */ 977 if (diff > 0 && uip->ui_proccnt + diff > max && max != 0) { 978 UIDINFO_UNLOCK(uip); 979 return (0); 980 } 981 uip->ui_proccnt += diff; 982 if (uip->ui_proccnt < 0) 983 printf("negative proccnt for uid = %d\n", uip->ui_uid); 984 UIDINFO_UNLOCK(uip); 985 return (1); 986} 987 988/* 989 * Change the total socket buffer size a user has used. 990 */ 991int 992chgsbsize(uip, hiwat, to, max) 993 struct uidinfo *uip; 994 u_long *hiwat; 995 u_long to; 996 rlim_t max; 997{ 998 rlim_t new; 999 int s; 1000 1001 s = splnet(); 1002 UIDINFO_LOCK(uip); 1003 new = uip->ui_sbsize + to - *hiwat; 1004 /* don't allow them to exceed max, but allow subtraction */ 1005 if (to > *hiwat && new > max) { 1006 splx(s); 1007 UIDINFO_UNLOCK(uip); 1008 return (0); 1009 } 1010 uip->ui_sbsize = new; 1011 *hiwat = to; 1012 if (uip->ui_sbsize < 0) 1013 printf("negative sbsize for uid = %d\n", uip->ui_uid); 1014 splx(s); 1015 UIDINFO_UNLOCK(uip); 1016 return (1); 1017}
|