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