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 */ && 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_ 248 struct 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 */ 263 int 264 rtprio(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); 332 done2: 333 mtx_unlock(&Giant); 334 return (error); 335 } 336 337 int 338 rtp_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 364 void 365 pri_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_ 386 struct osetrlimit_args { 387 u_int which; 388 struct orlimit *rlp; 389 }; 390 #endif 391 /* 392 * MPSAFE 393 */ 394 /* ARGSUSED */ 395 int 396 osetrlimit(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_ 416 struct ogetrlimit_args { 417 u_int which; 418 struct orlimit *rlp; 419 }; 420 #endif 421 /* 422 * MPSAFE 423 */ 424 /* ARGSUSED */ 425 int 426 ogetrlimit(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_ 450 struct __setrlimit_args { 451 u_int which; 452 struct rlimit *rlp; 453 }; 454 #endif 455 /* 456 * MPSAFE 457 */ 458 /* ARGSUSED */ 459 int 460 setrlimit(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 476 int 477 dosetrlimit(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_ 583 struct __getrlimit_args { 584 u_int which; 585 struct rlimit *rlp; 586 }; 587 #endif 588 /* 589 * MPSAFE 590 */ 591 /* ARGSUSED */ 592 int 593 getrlimit(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 */ 613 void 614 calcru(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 kse *ke; 626 struct ksegrp *kg; 627 628 mtx_assert(&sched_lock, MA_OWNED); 629 /* XXX: why spl-protect ? worst case is an off-by-one report */ 630 631 FOREACH_KSEGRP_IN_PROC(p, kg) { 632 /* we could accumulate per ksegrp and per process here*/ 633 FOREACH_KSE_IN_GROUP(kg, ke) { 634 s = splstatclock(); 635 ut = ke->ke_uticks; 636 st = ke->ke_sticks; 637 it = ke->ke_iticks; 638 splx(s); 639 640 tt = ut + st + it; 641 if (tt == 0) { 642 st = 1; 643 tt = 1; 644 } 645 646 tu = p->p_runtime; 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 microuptime(&tv); 656 if (timevalcmp(&tv, PCPU_PTR(switchtime), <)) 657 printf("microuptime() went backwards (%ld.%06ld -> %ld.%06ld)\n", 658 (long)PCPU_GET(switchtime.tv_sec), 659 PCPU_GET(switchtime.tv_usec), 660 (long)tv.tv_sec, tv.tv_usec); 661 else 662 tu += (tv.tv_usec 663 - PCPU_GET(switchtime.tv_usec)) 664 + (tv.tv_sec 665 - PCPU_GET(switchtime.tv_sec)) 666 * (int64_t)1000000; 667 } 668 ptu = ke->ke_uu + ke->ke_su + ke->ke_iu; 669 if (tu < ptu || (int64_t)tu < 0) { 670 /* XXX no %qd in kernel. Truncate. */ 671 printf("calcru: negative time of %ld usec for pid %d (%s)\n", 672 (long)tu, p->p_pid, p->p_comm); 673 tu = ptu; 674 } 675 676 /* Subdivide tu. */ 677 uu = (tu * ut) / tt; 678 su = (tu * st) / tt; 679 iu = tu - uu - su; 680 681 /* Enforce monotonicity. */ 682 if (uu < ke->ke_uu || su < ke->ke_su || iu < ke->ke_iu) { 683 if (uu < ke->ke_uu) 684 uu = ke->ke_uu; 685 else if (uu + ke->ke_su + ke->ke_iu > tu) 686 uu = tu - ke->ke_su - ke->ke_iu; 687 if (st == 0) 688 su = ke->ke_su; 689 else { 690 su = ((tu - uu) * st) / (st + it); 691 if (su < ke->ke_su) 692 su = ke->ke_su; 693 else if (uu + su + ke->ke_iu > tu) 694 su = tu - uu - ke->ke_iu; 695 } 696 KASSERT(uu + su + ke->ke_iu <= tu, 697 ("calcru: monotonisation botch 1")); 698 iu = tu - uu - su; 699 KASSERT(iu >= ke->ke_iu, 700 ("calcru: monotonisation botch 2")); 701 } 702 ke->ke_uu = uu; 703 ke->ke_su = su; 704 ke->ke_iu = iu; 705 uut += uu; 706 sut += su; 707 iut += iu; 708 709 } /* end kse loop */ 710 } /* end kseg loop */ 711 up->tv_sec = uut / 1000000; 712 up->tv_usec = uut % 1000000; 713 sp->tv_sec = sut / 1000000; 714 sp->tv_usec = sut % 1000000; 715 if (ip != NULL) { 716 ip->tv_sec = iut / 1000000; 717 ip->tv_usec = iut % 1000000; 718 } 719 } 720 721 #ifndef _SYS_SYSPROTO_H_ 722 struct getrusage_args { 723 int who; 724 struct rusage *rusage; 725 }; 726 #endif 727 /* 728 * MPSAFE 729 */ 730 /* ARGSUSED */ 731 int 732 getrusage(td, uap) 733 register struct thread *td; 734 register struct getrusage_args *uap; 735 { 736 struct proc *p = td->td_proc; 737 register struct rusage *rup; 738 int error = 0; 739 740 mtx_lock(&Giant); 741 742 switch (uap->who) { 743 case RUSAGE_SELF: 744 rup = &p->p_stats->p_ru; 745 mtx_lock_spin(&sched_lock); 746 calcru(p, &rup->ru_utime, &rup->ru_stime, NULL); 747 mtx_unlock_spin(&sched_lock); 748 break; 749 750 case RUSAGE_CHILDREN: 751 rup = &p->p_stats->p_cru; 752 break; 753 754 default: 755 rup = NULL; 756 error = EINVAL; 757 break; 758 } 759 mtx_unlock(&Giant); 760 if (error == 0) { 761 error = copyout((caddr_t)rup, (caddr_t)uap->rusage, 762 sizeof (struct rusage)); 763 } 764 return(error); 765 } 766 767 void 768 ruadd(ru, ru2) 769 register struct rusage *ru, *ru2; 770 { 771 register long *ip, *ip2; 772 register int i; 773 774 timevaladd(&ru->ru_utime, &ru2->ru_utime); 775 timevaladd(&ru->ru_stime, &ru2->ru_stime); 776 if (ru->ru_maxrss < ru2->ru_maxrss) 777 ru->ru_maxrss = ru2->ru_maxrss; 778 ip = &ru->ru_first; ip2 = &ru2->ru_first; 779 for (i = &ru->ru_last - &ru->ru_first; i >= 0; i--) 780 *ip++ += *ip2++; 781 } 782 783 /* 784 * Make a copy of the plimit structure. 785 * We share these structures copy-on-write after fork, 786 * and copy when a limit is changed. 787 */ 788 struct plimit * 789 limcopy(lim) 790 struct plimit *lim; 791 { 792 register struct plimit *copy; 793 794 MALLOC(copy, struct plimit *, sizeof(struct plimit), 795 M_SUBPROC, M_WAITOK); 796 bcopy(lim->pl_rlimit, copy->pl_rlimit, sizeof(struct plimit)); 797 copy->p_lflags = 0; 798 copy->p_refcnt = 1; 799 return (copy); 800 } 801 802 /* 803 * Find the uidinfo structure for a uid. This structure is used to 804 * track the total resource consumption (process count, socket buffer 805 * size, etc.) for the uid and impose limits. 806 */ 807 void 808 uihashinit() 809 { 810 811 uihashtbl = hashinit(maxproc / 16, M_UIDINFO, &uihash); 812 mtx_init(&uihashtbl_mtx, "uidinfo hash", MTX_DEF); 813 } 814 815 /* 816 * lookup a uidinfo struct for the parameter uid. 817 * uihashtbl_mtx must be locked. 818 */ 819 static struct uidinfo * 820 uilookup(uid) 821 uid_t uid; 822 { 823 struct uihashhead *uipp; 824 struct uidinfo *uip; 825 826 mtx_assert(&uihashtbl_mtx, MA_OWNED); 827 uipp = UIHASH(uid); 828 LIST_FOREACH(uip, uipp, ui_hash) 829 if (uip->ui_uid == uid) 830 break; 831 832 return (uip); 833 } 834 835 /* 836 * Find or allocate a struct uidinfo for a particular uid. 837 * Increase refcount on uidinfo struct returned. 838 * uifree() should be called on a struct uidinfo when released. 839 */ 840 struct uidinfo * 841 uifind(uid) 842 uid_t uid; 843 { 844 struct uidinfo *uip; 845 846 mtx_lock(&uihashtbl_mtx); 847 uip = uilookup(uid); 848 if (uip == NULL) { 849 struct uidinfo *old_uip; 850 851 mtx_unlock(&uihashtbl_mtx); 852 uip = malloc(sizeof(*uip), M_UIDINFO, M_WAITOK | M_ZERO); 853 mtx_lock(&uihashtbl_mtx); 854 /* 855 * There's a chance someone created our uidinfo while we 856 * were in malloc and not holding the lock, so we have to 857 * make sure we don't insert a duplicate uidinfo 858 */ 859 if ((old_uip = uilookup(uid)) != NULL) { 860 /* someone else beat us to it */ 861 free(uip, M_UIDINFO); 862 uip = old_uip; 863 } else { 864 uip->ui_mtxp = mtx_pool_alloc(); 865 uip->ui_uid = uid; 866 LIST_INSERT_HEAD(UIHASH(uid), uip, ui_hash); 867 } 868 } 869 uihold(uip); 870 mtx_unlock(&uihashtbl_mtx); 871 return (uip); 872 } 873 874 /* 875 * Place another refcount on a uidinfo struct. 876 */ 877 void 878 uihold(uip) 879 struct uidinfo *uip; 880 { 881 882 UIDINFO_LOCK(uip); 883 uip->ui_ref++; 884 UIDINFO_UNLOCK(uip); 885 } 886 887 /*- 888 * Since uidinfo structs have a long lifetime, we use an 889 * opportunistic refcounting scheme to avoid locking the lookup hash 890 * for each release. 891 * 892 * If the refcount hits 0, we need to free the structure, 893 * which means we need to lock the hash. 894 * Optimal case: 895 * After locking the struct and lowering the refcount, if we find 896 * that we don't need to free, simply unlock and return. 897 * Suboptimal case: 898 * If refcount lowering results in need to free, bump the count 899 * back up, loose the lock and aquire the locks in the proper 900 * order to try again. 901 */ 902 void 903 uifree(uip) 904 struct uidinfo *uip; 905 { 906 907 /* Prepare for optimal case. */ 908 UIDINFO_LOCK(uip); 909 910 if (--uip->ui_ref != 0) { 911 UIDINFO_UNLOCK(uip); 912 return; 913 } 914 915 /* Prepare for suboptimal case. */ 916 uip->ui_ref++; 917 UIDINFO_UNLOCK(uip); 918 mtx_lock(&uihashtbl_mtx); 919 UIDINFO_LOCK(uip); 920 921 /* 922 * We must subtract one from the count again because we backed out 923 * our initial subtraction before dropping the lock. 924 * Since another thread may have added a reference after we dropped the 925 * initial lock we have to test for zero again. 926 */ 927 if (--uip->ui_ref == 0) { 928 LIST_REMOVE(uip, ui_hash); 929 mtx_unlock(&uihashtbl_mtx); 930 if (uip->ui_sbsize != 0) 931 /* XXX no %qd in kernel. Truncate. */ 932 printf("freeing uidinfo: uid = %d, sbsize = %ld\n", 933 uip->ui_uid, (long)uip->ui_sbsize); 934 if (uip->ui_proccnt != 0) 935 printf("freeing uidinfo: uid = %d, proccnt = %ld\n", 936 uip->ui_uid, uip->ui_proccnt); 937 UIDINFO_UNLOCK(uip); 938 FREE(uip, M_UIDINFO); 939 return; 940 } 941 942 mtx_unlock(&uihashtbl_mtx); 943 UIDINFO_UNLOCK(uip); 944 } 945 946 /* 947 * Change the count associated with number of processes 948 * a given user is using. When 'max' is 0, don't enforce a limit 949 */ 950 int 951 chgproccnt(uip, diff, max) 952 struct uidinfo *uip; 953 int diff; 954 int max; 955 { 956 957 UIDINFO_LOCK(uip); 958 /* don't allow them to exceed max, but allow subtraction */ 959 if (diff > 0 && uip->ui_proccnt + diff > max && max != 0) { 960 UIDINFO_UNLOCK(uip); 961 return (0); 962 } 963 uip->ui_proccnt += diff; 964 if (uip->ui_proccnt < 0) 965 printf("negative proccnt for uid = %d\n", uip->ui_uid); 966 UIDINFO_UNLOCK(uip); 967 return (1); 968 } 969 970 /* 971 * Change the total socket buffer size a user has used. 972 */ 973 int 974 chgsbsize(uip, hiwat, to, max) 975 struct uidinfo *uip; 976 u_long *hiwat; 977 u_long to; 978 rlim_t max; 979 { 980 rlim_t new; 981 int s; 982 983 s = splnet(); 984 UIDINFO_LOCK(uip); 985 new = uip->ui_sbsize + to - *hiwat; 986 /* don't allow them to exceed max, but allow subtraction */ 987 if (to > *hiwat && new > max) { 988 splx(s); 989 UIDINFO_UNLOCK(uip); 990 return (0); 991 } 992 uip->ui_sbsize = new; 993 *hiwat = to; 994 if (uip->ui_sbsize < 0) 995 printf("negative sbsize for uid = %d\n", uip->ui_uid); 996 splx(s); 997 UIDINFO_UNLOCK(uip); 998 return (1); 999 } 1000