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