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