1 /* $NetBSD: kern_resource.c,v 1.93 2005/03/29 18:18:06 christos Exp $ */ 2 3 /*- 4 * Copyright (c) 1982, 1986, 1991, 1993 5 * The Regents of the University of California. All rights reserved. 6 * (c) UNIX System Laboratories, Inc. 7 * All or some portions of this file are derived from material licensed 8 * to the University of California by American Telephone and Telegraph 9 * Co. or Unix System Laboratories, Inc. and are reproduced herein with 10 * the permission of UNIX System Laboratories, Inc. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 3. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 * 36 * @(#)kern_resource.c 8.8 (Berkeley) 2/14/95 37 */ 38 39 #include <sys/cdefs.h> 40 __KERNEL_RCSID(0, "$NetBSD: kern_resource.c,v 1.93 2005/03/29 18:18:06 christos Exp $"); 41 42 #include <sys/param.h> 43 #include <sys/systm.h> 44 #include <sys/kernel.h> 45 #include <sys/file.h> 46 #include <sys/resourcevar.h> 47 #include <sys/malloc.h> 48 #include <sys/pool.h> 49 #include <sys/proc.h> 50 #include <sys/sysctl.h> 51 52 #include <sys/mount.h> 53 #include <sys/sa.h> 54 #include <sys/syscallargs.h> 55 56 #include <uvm/uvm_extern.h> 57 58 /* 59 * Maximum process data and stack limits. 60 * They are variables so they are patchable. 61 */ 62 rlim_t maxdmap = MAXDSIZ; 63 rlim_t maxsmap = MAXSSIZ; 64 65 struct uihashhead *uihashtbl; 66 u_long uihash; /* size of hash table - 1 */ 67 struct simplelock uihashtbl_slock = SIMPLELOCK_INITIALIZER; 68 69 70 /* 71 * Resource controls and accounting. 72 */ 73 74 int 75 sys_getpriority(l, v, retval) 76 struct lwp *l; 77 void *v; 78 register_t *retval; 79 { 80 struct sys_getpriority_args /* { 81 syscallarg(int) which; 82 syscallarg(id_t) who; 83 } */ *uap = v; 84 struct proc *curp = l->l_proc, *p; 85 int low = NZERO + PRIO_MAX + 1; 86 87 switch (SCARG(uap, which)) { 88 89 case PRIO_PROCESS: 90 if (SCARG(uap, who) == 0) 91 p = curp; 92 else 93 p = pfind(SCARG(uap, who)); 94 if (p == 0) 95 break; 96 low = p->p_nice; 97 break; 98 99 case PRIO_PGRP: { 100 struct pgrp *pg; 101 102 if (SCARG(uap, who) == 0) 103 pg = curp->p_pgrp; 104 else if ((pg = pgfind(SCARG(uap, who))) == NULL) 105 break; 106 LIST_FOREACH(p, &pg->pg_members, p_pglist) { 107 if (p->p_nice < low) 108 low = p->p_nice; 109 } 110 break; 111 } 112 113 case PRIO_USER: 114 if (SCARG(uap, who) == 0) 115 SCARG(uap, who) = curp->p_ucred->cr_uid; 116 proclist_lock_read(); 117 PROCLIST_FOREACH(p, &allproc) { 118 if (p->p_ucred->cr_uid == (uid_t) SCARG(uap, who) && 119 p->p_nice < low) 120 low = p->p_nice; 121 } 122 proclist_unlock_read(); 123 break; 124 125 default: 126 return (EINVAL); 127 } 128 if (low == NZERO + PRIO_MAX + 1) 129 return (ESRCH); 130 *retval = low - NZERO; 131 return (0); 132 } 133 134 /* ARGSUSED */ 135 int 136 sys_setpriority(l, v, retval) 137 struct lwp *l; 138 void *v; 139 register_t *retval; 140 { 141 struct sys_setpriority_args /* { 142 syscallarg(int) which; 143 syscallarg(id_t) who; 144 syscallarg(int) prio; 145 } */ *uap = v; 146 struct proc *curp = l->l_proc, *p; 147 int found = 0, error = 0; 148 149 switch (SCARG(uap, which)) { 150 151 case PRIO_PROCESS: 152 if (SCARG(uap, who) == 0) 153 p = curp; 154 else 155 p = pfind(SCARG(uap, who)); 156 if (p == 0) 157 break; 158 error = donice(curp, p, SCARG(uap, prio)); 159 found++; 160 break; 161 162 case PRIO_PGRP: { 163 struct pgrp *pg; 164 165 if (SCARG(uap, who) == 0) 166 pg = curp->p_pgrp; 167 else if ((pg = pgfind(SCARG(uap, who))) == NULL) 168 break; 169 LIST_FOREACH(p, &pg->pg_members, p_pglist) { 170 error = donice(curp, p, SCARG(uap, prio)); 171 found++; 172 } 173 break; 174 } 175 176 case PRIO_USER: 177 if (SCARG(uap, who) == 0) 178 SCARG(uap, who) = curp->p_ucred->cr_uid; 179 proclist_lock_read(); 180 PROCLIST_FOREACH(p, &allproc) { 181 if (p->p_ucred->cr_uid == (uid_t) SCARG(uap, who)) { 182 error = donice(curp, p, SCARG(uap, prio)); 183 found++; 184 } 185 } 186 proclist_unlock_read(); 187 break; 188 189 default: 190 return (EINVAL); 191 } 192 if (found == 0) 193 return (ESRCH); 194 return (error); 195 } 196 197 int 198 donice(curp, chgp, n) 199 struct proc *curp, *chgp; 200 int n; 201 { 202 struct pcred *pcred = curp->p_cred; 203 int s; 204 205 if (pcred->pc_ucred->cr_uid && pcred->p_ruid && 206 pcred->pc_ucred->cr_uid != chgp->p_ucred->cr_uid && 207 pcred->p_ruid != chgp->p_ucred->cr_uid) 208 return (EPERM); 209 if (n > PRIO_MAX) 210 n = PRIO_MAX; 211 if (n < PRIO_MIN) 212 n = PRIO_MIN; 213 n += NZERO; 214 if (n < chgp->p_nice && suser(pcred->pc_ucred, &curp->p_acflag)) 215 return (EACCES); 216 chgp->p_nice = n; 217 SCHED_LOCK(s); 218 (void)resetprocpriority(chgp); 219 SCHED_UNLOCK(s); 220 return (0); 221 } 222 223 /* ARGSUSED */ 224 int 225 sys_setrlimit(l, v, retval) 226 struct lwp *l; 227 void *v; 228 register_t *retval; 229 { 230 struct sys_setrlimit_args /* { 231 syscallarg(int) which; 232 syscallarg(const struct rlimit *) rlp; 233 } */ *uap = v; 234 struct proc *p = l->l_proc; 235 int which = SCARG(uap, which); 236 struct rlimit alim; 237 int error; 238 239 error = copyin(SCARG(uap, rlp), &alim, sizeof(struct rlimit)); 240 if (error) 241 return (error); 242 return (dosetrlimit(p, p->p_cred, which, &alim)); 243 } 244 245 int 246 dosetrlimit(p, cred, which, limp) 247 struct proc *p; 248 struct pcred *cred; 249 int which; 250 struct rlimit *limp; 251 { 252 struct rlimit *alimp; 253 struct plimit *oldplim; 254 int error; 255 256 if ((u_int)which >= RLIM_NLIMITS) 257 return (EINVAL); 258 259 if (limp->rlim_cur < 0 || limp->rlim_max < 0) 260 return (EINVAL); 261 262 alimp = &p->p_rlimit[which]; 263 /* if we don't change the value, no need to limcopy() */ 264 if (limp->rlim_cur == alimp->rlim_cur && 265 limp->rlim_max == alimp->rlim_max) 266 return 0; 267 268 if (limp->rlim_cur > limp->rlim_max) { 269 /* 270 * This is programming error. According to SUSv2, we should 271 * return error in this case. 272 */ 273 return (EINVAL); 274 } 275 if (limp->rlim_max > alimp->rlim_max 276 && (error = suser(cred->pc_ucred, &p->p_acflag)) != 0) 277 return (error); 278 279 if (p->p_limit->p_refcnt > 1 && 280 (p->p_limit->p_lflags & PL_SHAREMOD) == 0) { 281 p->p_limit = limcopy(oldplim = p->p_limit); 282 limfree(oldplim); 283 alimp = &p->p_rlimit[which]; 284 } 285 286 switch (which) { 287 288 case RLIMIT_DATA: 289 if (limp->rlim_cur > maxdmap) 290 limp->rlim_cur = maxdmap; 291 if (limp->rlim_max > maxdmap) 292 limp->rlim_max = maxdmap; 293 break; 294 295 case RLIMIT_STACK: 296 if (limp->rlim_cur > maxsmap) 297 limp->rlim_cur = maxsmap; 298 if (limp->rlim_max > maxsmap) 299 limp->rlim_max = maxsmap; 300 301 /* 302 * Return EINVAL if the new stack size limit is lower than 303 * current usage. Otherwise, the process would get SIGSEGV the 304 * moment it would try to access anything on it's current stack. 305 * This conforms to SUSv2. 306 */ 307 if (limp->rlim_cur < p->p_vmspace->vm_ssize * PAGE_SIZE 308 || limp->rlim_max < p->p_vmspace->vm_ssize * PAGE_SIZE) 309 return (EINVAL); 310 311 /* 312 * Stack is allocated to the max at exec time with 313 * only "rlim_cur" bytes accessible (In other words, 314 * allocates stack dividing two contiguous regions at 315 * "rlim_cur" bytes boundary). 316 * 317 * Since allocation is done in terms of page, roundup 318 * "rlim_cur" (otherwise, contiguous regions 319 * overlap). If stack limit is going up make more 320 * accessible, if going down make inaccessible. 321 */ 322 limp->rlim_cur = round_page(limp->rlim_cur); 323 if (limp->rlim_cur != alimp->rlim_cur) { 324 vaddr_t addr; 325 vsize_t size; 326 vm_prot_t prot; 327 328 if (limp->rlim_cur > alimp->rlim_cur) { 329 prot = VM_PROT_READ | VM_PROT_WRITE; 330 size = limp->rlim_cur - alimp->rlim_cur; 331 addr = (vaddr_t)p->p_vmspace->vm_minsaddr - 332 limp->rlim_cur; 333 } else { 334 prot = VM_PROT_NONE; 335 size = alimp->rlim_cur - limp->rlim_cur; 336 addr = (vaddr_t)p->p_vmspace->vm_minsaddr - 337 alimp->rlim_cur; 338 } 339 (void) uvm_map_protect(&p->p_vmspace->vm_map, 340 addr, addr+size, prot, FALSE); 341 } 342 break; 343 344 case RLIMIT_NOFILE: 345 if (limp->rlim_cur > maxfiles) 346 limp->rlim_cur = maxfiles; 347 if (limp->rlim_max > maxfiles) 348 limp->rlim_max = maxfiles; 349 break; 350 351 case RLIMIT_NPROC: 352 if (limp->rlim_cur > maxproc) 353 limp->rlim_cur = maxproc; 354 if (limp->rlim_max > maxproc) 355 limp->rlim_max = maxproc; 356 break; 357 } 358 *alimp = *limp; 359 return (0); 360 } 361 362 /* ARGSUSED */ 363 int 364 sys_getrlimit(l, v, retval) 365 struct lwp *l; 366 void *v; 367 register_t *retval; 368 { 369 struct sys_getrlimit_args /* { 370 syscallarg(int) which; 371 syscallarg(struct rlimit *) rlp; 372 } */ *uap = v; 373 struct proc *p = l->l_proc; 374 int which = SCARG(uap, which); 375 376 if ((u_int)which >= RLIM_NLIMITS) 377 return (EINVAL); 378 return (copyout(&p->p_rlimit[which], SCARG(uap, rlp), 379 sizeof(struct rlimit))); 380 } 381 382 /* 383 * Transform the running time and tick information in proc p into user, 384 * system, and interrupt time usage. 385 */ 386 void 387 calcru(p, up, sp, ip) 388 struct proc *p; 389 struct timeval *up; 390 struct timeval *sp; 391 struct timeval *ip; 392 { 393 u_quad_t u, st, ut, it, tot; 394 unsigned long sec; 395 long usec; 396 int s; 397 struct timeval tv; 398 struct lwp *l; 399 400 s = splstatclock(); 401 st = p->p_sticks; 402 ut = p->p_uticks; 403 it = p->p_iticks; 404 splx(s); 405 406 sec = p->p_rtime.tv_sec; 407 usec = p->p_rtime.tv_usec; 408 LIST_FOREACH(l, &p->p_lwps, l_sibling) { 409 if (l->l_stat == LSONPROC) { 410 struct schedstate_percpu *spc; 411 412 KDASSERT(l->l_cpu != NULL); 413 spc = &l->l_cpu->ci_schedstate; 414 415 /* 416 * Adjust for the current time slice. This is 417 * actually fairly important since the error 418 * here is on the order of a time quantum, 419 * which is much greater than the sampling 420 * error. 421 */ 422 microtime(&tv); 423 sec += tv.tv_sec - spc->spc_runtime.tv_sec; 424 usec += tv.tv_usec - spc->spc_runtime.tv_usec; 425 } 426 } 427 428 tot = st + ut + it; 429 u = sec * 1000000ull + usec; 430 431 if (tot == 0) { 432 /* No ticks, so can't use to share time out, split 50-50 */ 433 st = ut = u / 2; 434 } else { 435 st = (u * st) / tot; 436 ut = (u * ut) / tot; 437 } 438 sp->tv_sec = st / 1000000; 439 sp->tv_usec = st % 1000000; 440 up->tv_sec = ut / 1000000; 441 up->tv_usec = ut % 1000000; 442 if (ip != NULL) { 443 if (it != 0) 444 it = (u * it) / tot; 445 ip->tv_sec = it / 1000000; 446 ip->tv_usec = it % 1000000; 447 } 448 } 449 450 /* ARGSUSED */ 451 int 452 sys_getrusage(l, v, retval) 453 struct lwp *l; 454 void *v; 455 register_t *retval; 456 { 457 struct sys_getrusage_args /* { 458 syscallarg(int) who; 459 syscallarg(struct rusage *) rusage; 460 } */ *uap = v; 461 struct rusage *rup; 462 struct proc *p = l->l_proc; 463 464 switch (SCARG(uap, who)) { 465 466 case RUSAGE_SELF: 467 rup = &p->p_stats->p_ru; 468 calcru(p, &rup->ru_utime, &rup->ru_stime, NULL); 469 break; 470 471 case RUSAGE_CHILDREN: 472 rup = &p->p_stats->p_cru; 473 break; 474 475 default: 476 return (EINVAL); 477 } 478 return (copyout(rup, SCARG(uap, rusage), sizeof(struct rusage))); 479 } 480 481 void 482 ruadd(ru, ru2) 483 struct rusage *ru, *ru2; 484 { 485 long *ip, *ip2; 486 int i; 487 488 timeradd(&ru->ru_utime, &ru2->ru_utime, &ru->ru_utime); 489 timeradd(&ru->ru_stime, &ru2->ru_stime, &ru->ru_stime); 490 if (ru->ru_maxrss < ru2->ru_maxrss) 491 ru->ru_maxrss = ru2->ru_maxrss; 492 ip = &ru->ru_first; ip2 = &ru2->ru_first; 493 for (i = &ru->ru_last - &ru->ru_first; i >= 0; i--) 494 *ip++ += *ip2++; 495 } 496 497 /* 498 * Make a copy of the plimit structure. 499 * We share these structures copy-on-write after fork, 500 * and copy when a limit is changed. 501 */ 502 struct plimit * 503 limcopy(lim) 504 struct plimit *lim; 505 { 506 struct plimit *newlim; 507 size_t l = 0; 508 509 simple_lock(&lim->p_slock); 510 if (lim->pl_corename != defcorename) 511 l = strlen(lim->pl_corename) + 1; 512 simple_unlock(&lim->p_slock); 513 514 newlim = pool_get(&plimit_pool, PR_WAITOK); 515 simple_lock_init(&newlim->p_slock); 516 newlim->p_lflags = 0; 517 newlim->p_refcnt = 1; 518 newlim->pl_corename = (l != 0) 519 ? malloc(l, M_TEMP, M_WAITOK) 520 : defcorename; 521 522 simple_lock(&lim->p_slock); 523 memcpy(newlim->pl_rlimit, lim->pl_rlimit, 524 sizeof(struct rlimit) * RLIM_NLIMITS); 525 526 if (l != 0) 527 strlcpy(newlim->pl_corename, lim->pl_corename, l); 528 simple_unlock(&lim->p_slock); 529 530 return (newlim); 531 } 532 533 void 534 limfree(lim) 535 struct plimit *lim; 536 { 537 int n; 538 539 simple_lock(&lim->p_slock); 540 n = --lim->p_refcnt; 541 simple_unlock(&lim->p_slock); 542 if (n > 0) 543 return; 544 #ifdef DIAGNOSTIC 545 if (n < 0) 546 panic("limfree"); 547 #endif 548 if (lim->pl_corename != defcorename) 549 free(lim->pl_corename, M_TEMP); 550 pool_put(&plimit_pool, lim); 551 } 552 553 struct pstats * 554 pstatscopy(ps) 555 struct pstats *ps; 556 { 557 558 struct pstats *newps; 559 560 newps = pool_get(&pstats_pool, PR_WAITOK); 561 562 memset(&newps->pstat_startzero, 0, 563 (unsigned) ((caddr_t)&newps->pstat_endzero - 564 (caddr_t)&newps->pstat_startzero)); 565 memcpy(&newps->pstat_startcopy, &ps->pstat_startcopy, 566 ((caddr_t)&newps->pstat_endcopy - 567 (caddr_t)&newps->pstat_startcopy)); 568 569 return (newps); 570 571 } 572 573 void 574 pstatsfree(ps) 575 struct pstats *ps; 576 { 577 578 pool_put(&pstats_pool, ps); 579 } 580 581 /* 582 * sysctl interface in five parts 583 */ 584 585 /* 586 * a routine for sysctl proc subtree helpers that need to pick a valid 587 * process by pid. 588 */ 589 static int 590 sysctl_proc_findproc(struct proc *p, struct proc **p2, pid_t pid) 591 { 592 struct proc *ptmp; 593 int i, error = 0; 594 595 if (pid == PROC_CURPROC) 596 ptmp = p; 597 else if ((ptmp = pfind(pid)) == NULL) 598 error = ESRCH; 599 else { 600 /* 601 * suid proc of ours or proc not ours 602 */ 603 if (p->p_cred->p_ruid != ptmp->p_cred->p_ruid || 604 p->p_cred->p_ruid != ptmp->p_cred->p_svuid) 605 error = suser(p->p_ucred, &p->p_acflag); 606 607 /* 608 * sgid proc has sgid back to us temporarily 609 */ 610 else if (ptmp->p_cred->p_rgid != ptmp->p_cred->p_svgid) 611 error = suser(p->p_ucred, &p->p_acflag); 612 613 /* 614 * our rgid must be in target's group list (ie, 615 * sub-processes started by a sgid process) 616 */ 617 else { 618 for (i = 0; i < p->p_ucred->cr_ngroups; i++) { 619 if (p->p_ucred->cr_groups[i] == 620 ptmp->p_cred->p_rgid) 621 break; 622 } 623 if (i == p->p_ucred->cr_ngroups) 624 error = suser(p->p_ucred, &p->p_acflag); 625 } 626 } 627 628 *p2 = ptmp; 629 return (error); 630 } 631 632 /* 633 * sysctl helper routine for setting a process's specific corefile 634 * name. picks the process based on the given pid and checks the 635 * correctness of the new value. 636 */ 637 static int 638 sysctl_proc_corename(SYSCTLFN_ARGS) 639 { 640 struct proc *ptmp, *p; 641 struct plimit *lim; 642 int error = 0, len; 643 char cname[MAXPATHLEN], *tmp; 644 struct sysctlnode node; 645 646 /* 647 * is this all correct? 648 */ 649 if (namelen != 0) 650 return (EINVAL); 651 if (name[-1] != PROC_PID_CORENAME) 652 return (EINVAL); 653 654 /* 655 * whom are we tweaking? 656 */ 657 p = l->l_proc; 658 error = sysctl_proc_findproc(p, &ptmp, (pid_t)name[-2]); 659 if (error) 660 return (error); 661 662 /* 663 * let them modify a temporary copy of the core name 664 */ 665 node = *rnode; 666 strlcpy(cname, ptmp->p_limit->pl_corename, sizeof(cname)); 667 node.sysctl_data = cname; 668 error = sysctl_lookup(SYSCTLFN_CALL(&node)); 669 670 /* 671 * if that failed, or they have nothing new to say, or we've 672 * heard it before... 673 */ 674 if (error || newp == NULL || 675 strcmp(cname, ptmp->p_limit->pl_corename) == 0) 676 return (error); 677 678 /* 679 * no error yet and cname now has the new core name in it. 680 * let's see if it looks acceptable. it must be either "core" 681 * or end in ".core" or "/core". 682 */ 683 len = strlen(cname); 684 if (len < 4) 685 return (EINVAL); 686 if (strcmp(cname + len - 4, "core") != 0) 687 return (EINVAL); 688 if (len > 4 && cname[len - 5] != '/' && cname[len - 5] != '.') 689 return (EINVAL); 690 691 /* 692 * hmm...looks good. now...where do we put it? 693 */ 694 tmp = malloc(len + 1, M_TEMP, M_WAITOK|M_CANFAIL); 695 if (tmp == NULL) 696 return (ENOMEM); 697 strlcpy(tmp, cname, len + 1); 698 699 lim = ptmp->p_limit; 700 if (lim->p_refcnt > 1 && (lim->p_lflags & PL_SHAREMOD) == 0) { 701 ptmp->p_limit = limcopy(lim); 702 limfree(lim); 703 lim = ptmp->p_limit; 704 } 705 if (lim->pl_corename != defcorename) 706 free(lim->pl_corename, M_TEMP); 707 lim->pl_corename = tmp; 708 709 return (error); 710 } 711 712 /* 713 * sysctl helper routine for checking/setting a process's stop flags, 714 * one for fork and one for exec. 715 */ 716 static int 717 sysctl_proc_stop(SYSCTLFN_ARGS) 718 { 719 struct proc *p, *ptmp; 720 int i, f, error = 0; 721 struct sysctlnode node; 722 723 if (namelen != 0) 724 return (EINVAL); 725 726 p = l->l_proc; 727 error = sysctl_proc_findproc(p, &ptmp, (pid_t)name[-2]); 728 if (error) 729 return (error); 730 731 switch (rnode->sysctl_num) { 732 case PROC_PID_STOPFORK: 733 f = P_STOPFORK; 734 break; 735 case PROC_PID_STOPEXEC: 736 f = P_STOPEXEC; 737 break; 738 case PROC_PID_STOPEXIT: 739 f = P_STOPEXIT; 740 break; 741 default: 742 return (EINVAL); 743 } 744 745 i = (ptmp->p_flag & f) ? 1 : 0; 746 node = *rnode; 747 node.sysctl_data = &i; 748 error = sysctl_lookup(SYSCTLFN_CALL(&node)); 749 if (error || newp == NULL) 750 return (error); 751 752 if (i) 753 ptmp->p_flag |= f; 754 else 755 ptmp->p_flag &= ~f; 756 757 return (0); 758 } 759 760 /* 761 * sysctl helper routine for a process's rlimits as exposed by sysctl. 762 */ 763 static int 764 sysctl_proc_plimit(SYSCTLFN_ARGS) 765 { 766 struct proc *ptmp, *p; 767 u_int limitno; 768 int which, error = 0; 769 struct rlimit alim; 770 struct sysctlnode node; 771 772 if (namelen != 0) 773 return (EINVAL); 774 775 which = name[-1]; 776 if (which != PROC_PID_LIMIT_TYPE_SOFT && 777 which != PROC_PID_LIMIT_TYPE_HARD) 778 return (EINVAL); 779 780 limitno = name[-2] - 1; 781 if (limitno >= RLIM_NLIMITS) 782 return (EINVAL); 783 784 if (name[-3] != PROC_PID_LIMIT) 785 return (EINVAL); 786 787 p = l->l_proc; 788 error = sysctl_proc_findproc(p, &ptmp, (pid_t)name[-4]); 789 if (error) 790 return (error); 791 792 node = *rnode; 793 memcpy(&alim, &ptmp->p_rlimit[limitno], sizeof(alim)); 794 if (which == PROC_PID_LIMIT_TYPE_HARD) 795 node.sysctl_data = &alim.rlim_max; 796 else 797 node.sysctl_data = &alim.rlim_cur; 798 799 error = sysctl_lookup(SYSCTLFN_CALL(&node)); 800 if (error || newp == NULL) 801 return (error); 802 803 return (dosetrlimit(ptmp, p->p_cred, limitno, &alim)); 804 } 805 806 /* 807 * and finally, the actually glue that sticks it to the tree 808 */ 809 SYSCTL_SETUP(sysctl_proc_setup, "sysctl proc subtree setup") 810 { 811 812 sysctl_createv(clog, 0, NULL, NULL, 813 CTLFLAG_PERMANENT, 814 CTLTYPE_NODE, "proc", NULL, 815 NULL, 0, NULL, 0, 816 CTL_PROC, CTL_EOL); 817 sysctl_createv(clog, 0, NULL, NULL, 818 CTLFLAG_PERMANENT|CTLFLAG_ANYNUMBER, 819 CTLTYPE_NODE, "curproc", 820 SYSCTL_DESCR("Per-process settings"), 821 NULL, 0, NULL, 0, 822 CTL_PROC, PROC_CURPROC, CTL_EOL); 823 824 sysctl_createv(clog, 0, NULL, NULL, 825 CTLFLAG_PERMANENT|CTLFLAG_READONLY2|CTLFLAG_ANYWRITE, 826 CTLTYPE_STRING, "corename", 827 SYSCTL_DESCR("Core file name"), 828 sysctl_proc_corename, 0, NULL, MAXPATHLEN, 829 CTL_PROC, PROC_CURPROC, PROC_PID_CORENAME, CTL_EOL); 830 sysctl_createv(clog, 0, NULL, NULL, 831 CTLFLAG_PERMANENT, 832 CTLTYPE_NODE, "rlimit", 833 SYSCTL_DESCR("Process limits"), 834 NULL, 0, NULL, 0, 835 CTL_PROC, PROC_CURPROC, PROC_PID_LIMIT, CTL_EOL); 836 837 #define create_proc_plimit(s, n) do { \ 838 sysctl_createv(clog, 0, NULL, NULL, \ 839 CTLFLAG_PERMANENT, \ 840 CTLTYPE_NODE, s, \ 841 SYSCTL_DESCR("Process " s " limits"), \ 842 NULL, 0, NULL, 0, \ 843 CTL_PROC, PROC_CURPROC, PROC_PID_LIMIT, n, \ 844 CTL_EOL); \ 845 sysctl_createv(clog, 0, NULL, NULL, \ 846 CTLFLAG_PERMANENT|CTLFLAG_READWRITE|CTLFLAG_ANYWRITE, \ 847 CTLTYPE_QUAD, "soft", \ 848 SYSCTL_DESCR("Process soft " s " limit"), \ 849 sysctl_proc_plimit, 0, NULL, 0, \ 850 CTL_PROC, PROC_CURPROC, PROC_PID_LIMIT, n, \ 851 PROC_PID_LIMIT_TYPE_SOFT, CTL_EOL); \ 852 sysctl_createv(clog, 0, NULL, NULL, \ 853 CTLFLAG_PERMANENT|CTLFLAG_READWRITE|CTLFLAG_ANYWRITE, \ 854 CTLTYPE_QUAD, "hard", \ 855 SYSCTL_DESCR("Process hard " s " limit"), \ 856 sysctl_proc_plimit, 0, NULL, 0, \ 857 CTL_PROC, PROC_CURPROC, PROC_PID_LIMIT, n, \ 858 PROC_PID_LIMIT_TYPE_HARD, CTL_EOL); \ 859 } while (0/*CONSTCOND*/) 860 861 create_proc_plimit("cputime", PROC_PID_LIMIT_CPU); 862 create_proc_plimit("filesize", PROC_PID_LIMIT_FSIZE); 863 create_proc_plimit("datasize", PROC_PID_LIMIT_DATA); 864 create_proc_plimit("stacksize", PROC_PID_LIMIT_STACK); 865 create_proc_plimit("coredumpsize", PROC_PID_LIMIT_CORE); 866 create_proc_plimit("memoryuse", PROC_PID_LIMIT_RSS); 867 create_proc_plimit("memorylocked", PROC_PID_LIMIT_MEMLOCK); 868 create_proc_plimit("maxproc", PROC_PID_LIMIT_NPROC); 869 create_proc_plimit("descriptors", PROC_PID_LIMIT_NOFILE); 870 create_proc_plimit("sbsize", PROC_PID_LIMIT_SBSIZE); 871 872 #undef create_proc_plimit 873 874 sysctl_createv(clog, 0, NULL, NULL, 875 CTLFLAG_PERMANENT|CTLFLAG_READWRITE|CTLFLAG_ANYWRITE, 876 CTLTYPE_INT, "stopfork", 877 SYSCTL_DESCR("Stop process at fork(2)"), 878 sysctl_proc_stop, 0, NULL, 0, 879 CTL_PROC, PROC_CURPROC, PROC_PID_STOPFORK, CTL_EOL); 880 sysctl_createv(clog, 0, NULL, NULL, 881 CTLFLAG_PERMANENT|CTLFLAG_READWRITE|CTLFLAG_ANYWRITE, 882 CTLTYPE_INT, "stopexec", 883 SYSCTL_DESCR("Stop process at execve(2)"), 884 sysctl_proc_stop, 0, NULL, 0, 885 CTL_PROC, PROC_CURPROC, PROC_PID_STOPEXEC, CTL_EOL); 886 sysctl_createv(clog, 0, NULL, NULL, 887 CTLFLAG_PERMANENT|CTLFLAG_READWRITE|CTLFLAG_ANYWRITE, 888 CTLTYPE_INT, "stopexit", 889 SYSCTL_DESCR("Stop process before completing exit"), 890 sysctl_proc_stop, 0, NULL, 0, 891 CTL_PROC, PROC_CURPROC, PROC_PID_STOPEXIT, CTL_EOL); 892 } 893 894 struct uidinfo * 895 uid_find(uid_t uid) 896 { 897 struct uidinfo *uip; 898 struct uidinfo *newuip = NULL; 899 struct uihashhead *uipp; 900 901 uipp = UIHASH(uid); 902 903 again: 904 simple_lock(&uihashtbl_slock); 905 LIST_FOREACH(uip, uipp, ui_hash) 906 if (uip->ui_uid == uid) { 907 simple_unlock(&uihashtbl_slock); 908 if (newuip) 909 free(newuip, M_PROC); 910 return uip; 911 } 912 913 if (newuip == NULL) { 914 simple_unlock(&uihashtbl_slock); 915 newuip = malloc(sizeof(*uip), M_PROC, M_WAITOK | M_ZERO); 916 goto again; 917 } 918 uip = newuip; 919 920 LIST_INSERT_HEAD(uipp, uip, ui_hash); 921 uip->ui_uid = uid; 922 simple_unlock(&uihashtbl_slock); 923 924 return uip; 925 } 926 927 /* 928 * Change the count associated with number of processes 929 * a given user is using. 930 */ 931 int 932 chgproccnt(uid_t uid, int diff) 933 { 934 struct uidinfo *uip; 935 936 if (diff == 0) 937 return 0; 938 939 uip = uid_find(uid); 940 uip->ui_proccnt += diff; 941 KASSERT(uip->ui_proccnt >= 0); 942 return uip->ui_proccnt; 943 } 944 945 int 946 chgsbsize(uid_t uid, u_long *hiwat, u_long to, rlim_t max) 947 { 948 struct uidinfo *uip; 949 rlim_t nsb; 950 951 uip = uid_find(uid); 952 nsb = uip->ui_sbsize + to - *hiwat; 953 if (to > *hiwat && nsb > max) 954 return 0; 955 *hiwat = to; 956 uip->ui_sbsize = nsb; 957 KASSERT(uip->ui_sbsize >= 0); 958 return 1; 959 } 960