1 /*- 2 * Copyright (c) 1982, 1986, 1991, 1993 3 * The Regents of the University of California. All rights reserved. 4 * (c) UNIX System Laboratories, Inc. 5 * All or some portions of this file are derived from material licensed 6 * to the University of California by American Telephone and Telegraph 7 * Co. or Unix System Laboratories, Inc. and are reproduced herein with 8 * the permission of UNIX System Laboratories, Inc. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the University of 21 * California, Berkeley and its contributors. 22 * 4. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 * 38 * @(#)kern_resource.c 8.5 (Berkeley) 1/21/94 39 * $FreeBSD: src/sys/kern/kern_resource.c,v 1.55.2.5 2001/11/03 01:41:08 ps Exp $ 40 */ 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/resourcevar.h> 50 #include <sys/malloc.h> 51 #include <sys/proc.h> 52 #include <sys/time.h> 53 54 #include <vm/vm.h> 55 #include <vm/vm_param.h> 56 #include <sys/lock.h> 57 #include <vm/pmap.h> 58 #include <vm/vm_map.h> 59 60 static int donice __P((struct proc *curp, struct proc *chgp, int n)); 61 /* dosetrlimit non-static: Needed by SysVR4 emulator */ 62 int dosetrlimit __P((struct proc *p, u_int which, struct rlimit *limp)); 63 64 static MALLOC_DEFINE(M_UIDINFO, "uidinfo", "uidinfo structures"); 65 #define UIHASH(uid) (&uihashtbl[(uid) & uihash]) 66 static LIST_HEAD(uihashhead, uidinfo) *uihashtbl; 67 static u_long uihash; /* size of hash table - 1 */ 68 69 static struct uidinfo *uicreate __P((uid_t uid)); 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 int 83 getpriority(curp, uap) 84 struct proc *curp; 85 register struct getpriority_args *uap; 86 { 87 register struct proc *p; 88 register int low = PRIO_MAX + 1; 89 90 switch (uap->which) { 91 92 case PRIO_PROCESS: 93 if (uap->who == 0) 94 p = curp; 95 else 96 p = pfind(uap->who); 97 if (p == 0) 98 break; 99 if (!PRISON_CHECK(curp, p)) 100 break; 101 low = p->p_nice; 102 break; 103 104 case PRIO_PGRP: { 105 register struct pgrp *pg; 106 107 if (uap->who == 0) 108 pg = curp->p_pgrp; 109 else if ((pg = pgfind(uap->who)) == NULL) 110 break; 111 LIST_FOREACH(p, &pg->pg_members, p_pglist) { 112 if ((PRISON_CHECK(curp, p) && p->p_nice < low)) 113 low = p->p_nice; 114 } 115 break; 116 } 117 118 case PRIO_USER: 119 if (uap->who == 0) 120 uap->who = curp->p_ucred->cr_uid; 121 LIST_FOREACH(p, &allproc, p_list) 122 if (PRISON_CHECK(curp, p) && 123 p->p_ucred->cr_uid == uap->who && 124 p->p_nice < low) 125 low = p->p_nice; 126 break; 127 128 default: 129 return (EINVAL); 130 } 131 if (low == PRIO_MAX + 1) 132 return (ESRCH); 133 curp->p_retval[0] = low; 134 return (0); 135 } 136 137 #ifndef _SYS_SYSPROTO_H_ 138 struct setpriority_args { 139 int which; 140 int who; 141 int prio; 142 }; 143 #endif 144 /* ARGSUSED */ 145 int 146 setpriority(curp, uap) 147 struct proc *curp; 148 register struct setpriority_args *uap; 149 { 150 register struct proc *p; 151 int found = 0, error = 0; 152 153 switch (uap->which) { 154 155 case PRIO_PROCESS: 156 if (uap->who == 0) 157 p = curp; 158 else 159 p = pfind(uap->who); 160 if (p == 0) 161 break; 162 if (!PRISON_CHECK(curp, p)) 163 break; 164 error = donice(curp, p, uap->prio); 165 found++; 166 break; 167 168 case PRIO_PGRP: { 169 register struct pgrp *pg; 170 171 if (uap->who == 0) 172 pg = curp->p_pgrp; 173 else if ((pg = pgfind(uap->who)) == NULL) 174 break; 175 LIST_FOREACH(p, &pg->pg_members, p_pglist) { 176 if (PRISON_CHECK(curp, p)) { 177 error = donice(curp, p, uap->prio); 178 found++; 179 } 180 } 181 break; 182 } 183 184 case PRIO_USER: 185 if (uap->who == 0) 186 uap->who = curp->p_ucred->cr_uid; 187 LIST_FOREACH(p, &allproc, p_list) 188 if (p->p_ucred->cr_uid == uap->who && 189 PRISON_CHECK(curp, p)) { 190 error = donice(curp, p, uap->prio); 191 found++; 192 } 193 break; 194 195 default: 196 return (EINVAL); 197 } 198 if (found == 0) 199 return (ESRCH); 200 return (error); 201 } 202 203 static int 204 donice(curp, chgp, n) 205 register struct proc *curp, *chgp; 206 register int n; 207 { 208 register struct pcred *pcred = curp->p_cred; 209 210 if (pcred->pc_ucred->cr_uid && pcred->p_ruid && 211 pcred->pc_ucred->cr_uid != chgp->p_ucred->cr_uid && 212 pcred->p_ruid != chgp->p_ucred->cr_uid) 213 return (EPERM); 214 if (n > PRIO_MAX) 215 n = PRIO_MAX; 216 if (n < PRIO_MIN) 217 n = PRIO_MIN; 218 if (n < chgp->p_nice && suser(curp)) 219 return (EACCES); 220 chgp->p_nice = n; 221 (void)resetpriority(chgp); 222 return (0); 223 } 224 225 /* rtprio system call */ 226 #ifndef _SYS_SYSPROTO_H_ 227 struct rtprio_args { 228 int function; 229 pid_t pid; 230 struct rtprio *rtp; 231 }; 232 #endif 233 234 /* 235 * Set realtime priority 236 */ 237 238 /* ARGSUSED */ 239 int 240 rtprio(curp, uap) 241 struct proc *curp; 242 register struct rtprio_args *uap; 243 { 244 register struct proc *p; 245 register struct pcred *pcred = curp->p_cred; 246 struct rtprio rtp; 247 int error; 248 249 error = copyin(uap->rtp, &rtp, sizeof(struct rtprio)); 250 if (error) 251 return (error); 252 253 if (uap->pid == 0) 254 p = curp; 255 else 256 p = pfind(uap->pid); 257 258 if (p == 0) 259 return (ESRCH); 260 261 switch (uap->function) { 262 case RTP_LOOKUP: 263 return (copyout(&p->p_rtprio, uap->rtp, sizeof(struct rtprio))); 264 case RTP_SET: 265 if (pcred->pc_ucred->cr_uid && pcred->p_ruid && 266 pcred->pc_ucred->cr_uid != p->p_ucred->cr_uid && 267 pcred->p_ruid != p->p_ucred->cr_uid) 268 return (EPERM); 269 /* disallow setting rtprio in most cases if not superuser */ 270 if (suser(curp)) { 271 /* can't set someone else's */ 272 if (uap->pid) 273 return (EPERM); 274 /* can't set realtime priority */ 275 /* 276 * Realtime priority has to be restricted for reasons which should be 277 * obvious. However, for idle priority, there is a potential for 278 * system deadlock if an idleprio process gains a lock on a resource 279 * that other processes need (and the idleprio process can't run 280 * due to a CPU-bound normal process). Fix me! XXX 281 */ 282 #if 0 283 if (RTP_PRIO_IS_REALTIME(rtp.type)) 284 #endif 285 if (rtp.type != RTP_PRIO_NORMAL) 286 return (EPERM); 287 } 288 switch (rtp.type) { 289 #ifdef RTP_PRIO_FIFO 290 case RTP_PRIO_FIFO: 291 #endif 292 case RTP_PRIO_REALTIME: 293 case RTP_PRIO_NORMAL: 294 case RTP_PRIO_IDLE: 295 if (rtp.prio > RTP_PRIO_MAX) 296 return (EINVAL); 297 p->p_rtprio = rtp; 298 return (0); 299 default: 300 return (EINVAL); 301 } 302 303 default: 304 return (EINVAL); 305 } 306 } 307 308 #if defined(COMPAT_43) || defined(COMPAT_SUNOS) 309 #ifndef _SYS_SYSPROTO_H_ 310 struct osetrlimit_args { 311 u_int which; 312 struct orlimit *rlp; 313 }; 314 #endif 315 /* ARGSUSED */ 316 int 317 osetrlimit(p, uap) 318 struct proc *p; 319 register struct osetrlimit_args *uap; 320 { 321 struct orlimit olim; 322 struct rlimit lim; 323 int error; 324 325 if ((error = 326 copyin((caddr_t)uap->rlp, (caddr_t)&olim, sizeof(struct orlimit)))) 327 return (error); 328 lim.rlim_cur = olim.rlim_cur; 329 lim.rlim_max = olim.rlim_max; 330 return (dosetrlimit(p, uap->which, &lim)); 331 } 332 333 #ifndef _SYS_SYSPROTO_H_ 334 struct ogetrlimit_args { 335 u_int which; 336 struct orlimit *rlp; 337 }; 338 #endif 339 /* ARGSUSED */ 340 int 341 ogetrlimit(p, uap) 342 struct proc *p; 343 register struct ogetrlimit_args *uap; 344 { 345 struct orlimit olim; 346 347 if (uap->which >= RLIM_NLIMITS) 348 return (EINVAL); 349 olim.rlim_cur = p->p_rlimit[uap->which].rlim_cur; 350 if (olim.rlim_cur == -1) 351 olim.rlim_cur = 0x7fffffff; 352 olim.rlim_max = p->p_rlimit[uap->which].rlim_max; 353 if (olim.rlim_max == -1) 354 olim.rlim_max = 0x7fffffff; 355 return (copyout((caddr_t)&olim, (caddr_t)uap->rlp, sizeof(olim))); 356 } 357 #endif /* COMPAT_43 || COMPAT_SUNOS */ 358 359 #ifndef _SYS_SYSPROTO_H_ 360 struct __setrlimit_args { 361 u_int which; 362 struct rlimit *rlp; 363 }; 364 #endif 365 /* ARGSUSED */ 366 int 367 setrlimit(p, uap) 368 struct proc *p; 369 register struct __setrlimit_args *uap; 370 { 371 struct rlimit alim; 372 int error; 373 374 if ((error = 375 copyin((caddr_t)uap->rlp, (caddr_t)&alim, sizeof (struct rlimit)))) 376 return (error); 377 return (dosetrlimit(p, uap->which, &alim)); 378 } 379 380 int 381 dosetrlimit(p, which, limp) 382 struct proc *p; 383 u_int which; 384 struct rlimit *limp; 385 { 386 register struct rlimit *alimp; 387 int error; 388 389 if (which >= RLIM_NLIMITS) 390 return (EINVAL); 391 alimp = &p->p_rlimit[which]; 392 393 /* 394 * Preserve historical bugs by treating negative limits as unsigned. 395 */ 396 if (limp->rlim_cur < 0) 397 limp->rlim_cur = RLIM_INFINITY; 398 if (limp->rlim_max < 0) 399 limp->rlim_max = RLIM_INFINITY; 400 401 if (limp->rlim_cur > alimp->rlim_max || 402 limp->rlim_max > alimp->rlim_max) 403 if ((error = suser_xxx(0, p, PRISON_ROOT))) 404 return (error); 405 if (limp->rlim_cur > limp->rlim_max) 406 limp->rlim_cur = limp->rlim_max; 407 if (p->p_limit->p_refcnt > 1 && 408 (p->p_limit->p_lflags & PL_SHAREMOD) == 0) { 409 p->p_limit->p_refcnt--; 410 p->p_limit = limcopy(p->p_limit); 411 alimp = &p->p_rlimit[which]; 412 } 413 414 switch (which) { 415 416 case RLIMIT_CPU: 417 if (limp->rlim_cur > RLIM_INFINITY / (rlim_t)1000000) 418 p->p_limit->p_cpulimit = RLIM_INFINITY; 419 else 420 p->p_limit->p_cpulimit = 421 (rlim_t)1000000 * limp->rlim_cur; 422 break; 423 case RLIMIT_DATA: 424 if (limp->rlim_cur > maxdsiz) 425 limp->rlim_cur = maxdsiz; 426 if (limp->rlim_max > maxdsiz) 427 limp->rlim_max = maxdsiz; 428 break; 429 430 case RLIMIT_STACK: 431 if (limp->rlim_cur > maxssiz) 432 limp->rlim_cur = maxssiz; 433 if (limp->rlim_max > maxssiz) 434 limp->rlim_max = maxssiz; 435 /* 436 * Stack is allocated to the max at exec time with only 437 * "rlim_cur" bytes accessible. If stack limit is going 438 * up make more accessible, if going down make inaccessible. 439 */ 440 if (limp->rlim_cur != alimp->rlim_cur) { 441 vm_offset_t addr; 442 vm_size_t size; 443 vm_prot_t prot; 444 445 if (limp->rlim_cur > alimp->rlim_cur) { 446 prot = VM_PROT_ALL; 447 size = limp->rlim_cur - alimp->rlim_cur; 448 addr = USRSTACK - limp->rlim_cur; 449 } else { 450 prot = VM_PROT_NONE; 451 size = alimp->rlim_cur - limp->rlim_cur; 452 addr = USRSTACK - alimp->rlim_cur; 453 } 454 addr = trunc_page(addr); 455 size = round_page(size); 456 (void) vm_map_protect(&p->p_vmspace->vm_map, 457 addr, addr+size, prot, FALSE); 458 } 459 break; 460 461 case RLIMIT_NOFILE: 462 if (limp->rlim_cur > maxfilesperproc) 463 limp->rlim_cur = maxfilesperproc; 464 if (limp->rlim_max > maxfilesperproc) 465 limp->rlim_max = maxfilesperproc; 466 break; 467 468 case RLIMIT_NPROC: 469 if (limp->rlim_cur > maxprocperuid) 470 limp->rlim_cur = maxprocperuid; 471 if (limp->rlim_max > maxprocperuid) 472 limp->rlim_max = maxprocperuid; 473 if (limp->rlim_cur < 1) 474 limp->rlim_cur = 1; 475 if (limp->rlim_max < 1) 476 limp->rlim_max = 1; 477 break; 478 } 479 *alimp = *limp; 480 return (0); 481 } 482 483 #ifndef _SYS_SYSPROTO_H_ 484 struct __getrlimit_args { 485 u_int which; 486 struct rlimit *rlp; 487 }; 488 #endif 489 /* ARGSUSED */ 490 int 491 getrlimit(p, uap) 492 struct proc *p; 493 register struct __getrlimit_args *uap; 494 { 495 496 if (uap->which >= RLIM_NLIMITS) 497 return (EINVAL); 498 return (copyout((caddr_t)&p->p_rlimit[uap->which], (caddr_t)uap->rlp, 499 sizeof (struct rlimit))); 500 } 501 502 /* 503 * Transform the running time and tick information in proc p into user, 504 * system, and interrupt time usage. 505 */ 506 void 507 calcru(p, up, sp, ip) 508 struct proc *p; 509 struct timeval *up; 510 struct timeval *sp; 511 struct timeval *ip; 512 { 513 /* {user, system, interrupt, total} {ticks, usec}; previous tu: */ 514 u_int64_t ut, uu, st, su, it, iu, tt, tu, ptu; 515 int s; 516 struct timeval tv; 517 518 /* XXX: why spl-protect ? worst case is an off-by-one report */ 519 s = splstatclock(); 520 ut = p->p_uticks; 521 st = p->p_sticks; 522 it = p->p_iticks; 523 splx(s); 524 525 tt = ut + st + it; 526 if (tt == 0) { 527 st = 1; 528 tt = 1; 529 } 530 531 tu = p->p_runtime; 532 if (p == curproc) { 533 /* 534 * Adjust for the current time slice. This is actually fairly 535 * important since the error here is on the order of a time 536 * quantum, which is much greater than the sampling error. 537 */ 538 microuptime(&tv); 539 if (timevalcmp(&tv, &switchtime, <)) 540 printf("microuptime() went backwards (%ld.%06ld -> %ld.%06ld)\n", 541 switchtime.tv_sec, switchtime.tv_usec, 542 tv.tv_sec, tv.tv_usec); 543 else 544 tu += (tv.tv_usec - switchtime.tv_usec) + 545 (tv.tv_sec - switchtime.tv_sec) * (int64_t)1000000; 546 } 547 ptu = p->p_uu + p->p_su + p->p_iu; 548 if (tu < ptu || (int64_t)tu < 0) { 549 /* XXX no %qd in kernel. Truncate. */ 550 printf("calcru: negative time of %ld usec for pid %d (%s)\n", 551 (long)tu, p->p_pid, p->p_comm); 552 tu = ptu; 553 } 554 555 /* Subdivide tu. */ 556 uu = (tu * ut) / tt; 557 su = (tu * st) / tt; 558 iu = tu - uu - su; 559 560 /* Enforce monotonicity. */ 561 if (uu < p->p_uu || su < p->p_su || iu < p->p_iu) { 562 if (uu < p->p_uu) 563 uu = p->p_uu; 564 else if (uu + p->p_su + p->p_iu > tu) 565 uu = tu - p->p_su - p->p_iu; 566 if (st == 0) 567 su = p->p_su; 568 else { 569 su = ((tu - uu) * st) / (st + it); 570 if (su < p->p_su) 571 su = p->p_su; 572 else if (uu + su + p->p_iu > tu) 573 su = tu - uu - p->p_iu; 574 } 575 KASSERT(uu + su + p->p_iu <= tu, 576 ("calcru: monotonisation botch 1")); 577 iu = tu - uu - su; 578 KASSERT(iu >= p->p_iu, 579 ("calcru: monotonisation botch 2")); 580 } 581 p->p_uu = uu; 582 p->p_su = su; 583 p->p_iu = iu; 584 585 up->tv_sec = uu / 1000000; 586 up->tv_usec = uu % 1000000; 587 sp->tv_sec = su / 1000000; 588 sp->tv_usec = su % 1000000; 589 if (ip != NULL) { 590 ip->tv_sec = iu / 1000000; 591 ip->tv_usec = iu % 1000000; 592 } 593 } 594 595 #ifndef _SYS_SYSPROTO_H_ 596 struct getrusage_args { 597 int who; 598 struct rusage *rusage; 599 }; 600 #endif 601 /* ARGSUSED */ 602 int 603 getrusage(p, uap) 604 register struct proc *p; 605 register struct getrusage_args *uap; 606 { 607 register struct rusage *rup; 608 609 switch (uap->who) { 610 611 case RUSAGE_SELF: 612 rup = &p->p_stats->p_ru; 613 calcru(p, &rup->ru_utime, &rup->ru_stime, NULL); 614 break; 615 616 case RUSAGE_CHILDREN: 617 rup = &p->p_stats->p_cru; 618 break; 619 620 default: 621 return (EINVAL); 622 } 623 return (copyout((caddr_t)rup, (caddr_t)uap->rusage, 624 sizeof (struct rusage))); 625 } 626 627 void 628 ruadd(ru, ru2) 629 register struct rusage *ru, *ru2; 630 { 631 register long *ip, *ip2; 632 register int i; 633 634 timevaladd(&ru->ru_utime, &ru2->ru_utime); 635 timevaladd(&ru->ru_stime, &ru2->ru_stime); 636 if (ru->ru_maxrss < ru2->ru_maxrss) 637 ru->ru_maxrss = ru2->ru_maxrss; 638 ip = &ru->ru_first; ip2 = &ru2->ru_first; 639 for (i = &ru->ru_last - &ru->ru_first; i >= 0; i--) 640 *ip++ += *ip2++; 641 } 642 643 /* 644 * Make a copy of the plimit structure. 645 * We share these structures copy-on-write after fork, 646 * and copy when a limit is changed. 647 */ 648 struct plimit * 649 limcopy(lim) 650 struct plimit *lim; 651 { 652 register struct plimit *copy; 653 654 MALLOC(copy, struct plimit *, sizeof(struct plimit), 655 M_SUBPROC, M_WAITOK); 656 bcopy(lim->pl_rlimit, copy->pl_rlimit, sizeof(struct plimit)); 657 copy->p_lflags = 0; 658 copy->p_refcnt = 1; 659 return (copy); 660 } 661 662 /* 663 * Find the uidinfo structure for a uid. This structure is used to 664 * track the total resource consumption (process count, socket buffer 665 * size, etc.) for the uid and impose limits. 666 */ 667 void 668 uihashinit() 669 { 670 uihashtbl = hashinit(maxproc / 16, M_UIDINFO, &uihash); 671 } 672 673 static struct uidinfo * 674 uilookup(uid) 675 uid_t uid; 676 { 677 struct uihashhead *uipp; 678 struct uidinfo *uip; 679 680 uipp = UIHASH(uid); 681 LIST_FOREACH(uip, uipp, ui_hash) 682 if (uip->ui_uid == uid) 683 break; 684 685 return (uip); 686 } 687 688 static struct uidinfo * 689 uicreate(uid) 690 uid_t uid; 691 { 692 struct uidinfo *uip, *norace; 693 694 MALLOC(uip, struct uidinfo *, sizeof(*uip), M_UIDINFO, M_NOWAIT); 695 if (uip == NULL) { 696 MALLOC(uip, struct uidinfo *, sizeof(*uip), M_UIDINFO, M_WAITOK); 697 /* 698 * if we M_WAITOK we must look afterwards or risk 699 * redundant entries 700 */ 701 norace = uilookup(uid); 702 if (norace != NULL) { 703 FREE(uip, M_UIDINFO); 704 return (norace); 705 } 706 } 707 LIST_INSERT_HEAD(UIHASH(uid), uip, ui_hash); 708 uip->ui_uid = uid; 709 uip->ui_proccnt = 0; 710 uip->ui_sbsize = 0; 711 uip->ui_ref = 0; 712 return (uip); 713 } 714 715 struct uidinfo * 716 uifind(uid) 717 uid_t uid; 718 { 719 struct uidinfo *uip; 720 721 uip = uilookup(uid); 722 if (uip == NULL) 723 uip = uicreate(uid); 724 uip->ui_ref++; 725 return (uip); 726 } 727 728 int 729 uifree(uip) 730 struct uidinfo *uip; 731 { 732 733 if (--uip->ui_ref == 0) { 734 if (uip->ui_sbsize != 0) 735 /* XXX no %qd in kernel. Truncate. */ 736 printf("freeing uidinfo: uid = %d, sbsize = %ld\n", 737 uip->ui_uid, (long)uip->ui_sbsize); 738 if (uip->ui_proccnt != 0) 739 printf("freeing uidinfo: uid = %d, proccnt = %ld\n", 740 uip->ui_uid, uip->ui_proccnt); 741 LIST_REMOVE(uip, ui_hash); 742 FREE(uip, M_UIDINFO); 743 return (1); 744 } 745 return (0); 746 } 747 748 /* 749 * Change the count associated with number of processes 750 * a given user is using. When 'max' is 0, don't enforce a limit 751 */ 752 int 753 chgproccnt(uip, diff, max) 754 struct uidinfo *uip; 755 int diff; 756 int max; 757 { 758 /* don't allow them to exceed max, but allow subtraction */ 759 if (diff > 0 && uip->ui_proccnt + diff > max && max != 0) 760 return (0); 761 uip->ui_proccnt += diff; 762 if (uip->ui_proccnt < 0) 763 printf("negative proccnt for uid = %d\n", uip->ui_uid); 764 return (1); 765 } 766 767 /* 768 * Change the total socket buffer size a user has used. 769 */ 770 int 771 chgsbsize(uip, hiwat, to, max) 772 struct uidinfo *uip; 773 u_long *hiwat; 774 u_long to; 775 rlim_t max; 776 { 777 rlim_t new; 778 int s; 779 780 s = splnet(); 781 new = uip->ui_sbsize + to - *hiwat; 782 /* don't allow them to exceed max, but allow subtraction */ 783 if (to > *hiwat && new > max) { 784 splx(s); 785 return (0); 786 } 787 uip->ui_sbsize = new; 788 *hiwat = to; 789 if (uip->ui_sbsize < 0) 790 printf("negative sbsize for uid = %d\n", uip->ui_uid); 791 splx(s); 792 return (1); 793 } 794