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