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