1 /* $NetBSD: kern_resource.c,v 1.86 2004/10/01 16:30:54 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.86 2004/10/01 16:30:54 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/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 68 static struct uidinfo *getuidinfo(uid_t); 69 static void freeuidinfo(struct uidinfo *); 70 static struct uidinfo *allocuidinfo(uid_t); 71 72 /* 73 * Resource controls and accounting. 74 */ 75 76 int 77 sys_getpriority(l, v, retval) 78 struct lwp *l; 79 void *v; 80 register_t *retval; 81 { 82 struct sys_getpriority_args /* { 83 syscallarg(int) which; 84 syscallarg(id_t) who; 85 } */ *uap = v; 86 struct proc *curp = l->l_proc, *p; 87 int low = NZERO + PRIO_MAX + 1; 88 89 switch (SCARG(uap, which)) { 90 91 case PRIO_PROCESS: 92 if (SCARG(uap, who) == 0) 93 p = curp; 94 else 95 p = pfind(SCARG(uap, who)); 96 if (p == 0) 97 break; 98 low = p->p_nice; 99 break; 100 101 case PRIO_PGRP: { 102 struct pgrp *pg; 103 104 if (SCARG(uap, who) == 0) 105 pg = curp->p_pgrp; 106 else if ((pg = pgfind(SCARG(uap, who))) == NULL) 107 break; 108 LIST_FOREACH(p, &pg->pg_members, p_pglist) { 109 if (p->p_nice < low) 110 low = p->p_nice; 111 } 112 break; 113 } 114 115 case PRIO_USER: 116 if (SCARG(uap, who) == 0) 117 SCARG(uap, who) = curp->p_ucred->cr_uid; 118 proclist_lock_read(); 119 PROCLIST_FOREACH(p, &allproc) { 120 if (p->p_ucred->cr_uid == (uid_t) SCARG(uap, who) && 121 p->p_nice < low) 122 low = p->p_nice; 123 } 124 proclist_unlock_read(); 125 break; 126 127 default: 128 return (EINVAL); 129 } 130 if (low == NZERO + PRIO_MAX + 1) 131 return (ESRCH); 132 *retval = low - NZERO; 133 return (0); 134 } 135 136 /* ARGSUSED */ 137 int 138 sys_setpriority(l, v, retval) 139 struct lwp *l; 140 void *v; 141 register_t *retval; 142 { 143 struct sys_setpriority_args /* { 144 syscallarg(int) which; 145 syscallarg(id_t) who; 146 syscallarg(int) prio; 147 } */ *uap = v; 148 struct proc *curp = l->l_proc, *p; 149 int found = 0, error = 0; 150 151 switch (SCARG(uap, which)) { 152 153 case PRIO_PROCESS: 154 if (SCARG(uap, who) == 0) 155 p = curp; 156 else 157 p = pfind(SCARG(uap, who)); 158 if (p == 0) 159 break; 160 error = donice(curp, p, SCARG(uap, prio)); 161 found++; 162 break; 163 164 case PRIO_PGRP: { 165 struct pgrp *pg; 166 167 if (SCARG(uap, who) == 0) 168 pg = curp->p_pgrp; 169 else if ((pg = pgfind(SCARG(uap, who))) == NULL) 170 break; 171 LIST_FOREACH(p, &pg->pg_members, p_pglist) { 172 error = donice(curp, p, SCARG(uap, prio)); 173 found++; 174 } 175 break; 176 } 177 178 case PRIO_USER: 179 if (SCARG(uap, who) == 0) 180 SCARG(uap, who) = curp->p_ucred->cr_uid; 181 proclist_lock_read(); 182 PROCLIST_FOREACH(p, &allproc) { 183 if (p->p_ucred->cr_uid == (uid_t) SCARG(uap, who)) { 184 error = donice(curp, p, SCARG(uap, prio)); 185 found++; 186 } 187 } 188 proclist_unlock_read(); 189 break; 190 191 default: 192 return (EINVAL); 193 } 194 if (found == 0) 195 return (ESRCH); 196 return (error); 197 } 198 199 int 200 donice(curp, chgp, n) 201 struct proc *curp, *chgp; 202 int n; 203 { 204 struct pcred *pcred = curp->p_cred; 205 int s; 206 207 if (pcred->pc_ucred->cr_uid && pcred->p_ruid && 208 pcred->pc_ucred->cr_uid != chgp->p_ucred->cr_uid && 209 pcred->p_ruid != chgp->p_ucred->cr_uid) 210 return (EPERM); 211 if (n > PRIO_MAX) 212 n = PRIO_MAX; 213 if (n < PRIO_MIN) 214 n = PRIO_MIN; 215 n += NZERO; 216 if (n < chgp->p_nice && suser(pcred->pc_ucred, &curp->p_acflag)) 217 return (EACCES); 218 chgp->p_nice = n; 219 SCHED_LOCK(s); 220 (void)resetprocpriority(chgp); 221 SCHED_UNLOCK(s); 222 return (0); 223 } 224 225 /* ARGSUSED */ 226 int 227 sys_setrlimit(l, v, retval) 228 struct lwp *l; 229 void *v; 230 register_t *retval; 231 { 232 struct sys_setrlimit_args /* { 233 syscallarg(int) which; 234 syscallarg(const struct rlimit *) rlp; 235 } */ *uap = v; 236 struct proc *p = l->l_proc; 237 int which = SCARG(uap, which); 238 struct rlimit alim; 239 int error; 240 241 error = copyin(SCARG(uap, rlp), &alim, sizeof(struct rlimit)); 242 if (error) 243 return (error); 244 return (dosetrlimit(p, p->p_cred, which, &alim)); 245 } 246 247 int 248 dosetrlimit(p, cred, which, limp) 249 struct proc *p; 250 struct pcred *cred; 251 int which; 252 struct rlimit *limp; 253 { 254 struct rlimit *alimp; 255 struct plimit *oldplim; 256 int error; 257 258 if ((u_int)which >= RLIM_NLIMITS) 259 return (EINVAL); 260 261 if (limp->rlim_cur < 0 || limp->rlim_max < 0) 262 return (EINVAL); 263 264 alimp = &p->p_rlimit[which]; 265 /* if we don't change the value, no need to limcopy() */ 266 if (limp->rlim_cur == alimp->rlim_cur && 267 limp->rlim_max == alimp->rlim_max) 268 return 0; 269 270 if (limp->rlim_cur > limp->rlim_max) { 271 /* 272 * This is programming error. According to SUSv2, we should 273 * return error in this case. 274 */ 275 return (EINVAL); 276 } 277 if (limp->rlim_max > alimp->rlim_max 278 && (error = suser(cred->pc_ucred, &p->p_acflag)) != 0) 279 return (error); 280 281 if (p->p_limit->p_refcnt > 1 && 282 (p->p_limit->p_lflags & PL_SHAREMOD) == 0) { 283 p->p_limit = limcopy(oldplim = p->p_limit); 284 limfree(oldplim); 285 alimp = &p->p_rlimit[which]; 286 } 287 288 switch (which) { 289 290 case RLIMIT_DATA: 291 if (limp->rlim_cur > maxdmap) 292 limp->rlim_cur = maxdmap; 293 if (limp->rlim_max > maxdmap) 294 limp->rlim_max = maxdmap; 295 break; 296 297 case RLIMIT_STACK: 298 if (limp->rlim_cur > maxsmap) 299 limp->rlim_cur = maxsmap; 300 if (limp->rlim_max > maxsmap) 301 limp->rlim_max = maxsmap; 302 303 /* 304 * Return EINVAL if the new stack size limit is lower than 305 * current usage. Otherwise, the process would get SIGSEGV the 306 * moment it would try to access anything on it's current stack. 307 * This conforms to SUSv2. 308 */ 309 if (limp->rlim_cur < p->p_vmspace->vm_ssize * PAGE_SIZE 310 || limp->rlim_max < p->p_vmspace->vm_ssize * PAGE_SIZE) 311 return (EINVAL); 312 313 /* 314 * Stack is allocated to the max at exec time with 315 * only "rlim_cur" bytes accessible (In other words, 316 * allocates stack dividing two contiguous regions at 317 * "rlim_cur" bytes boundary). 318 * 319 * Since allocation is done in terms of page, roundup 320 * "rlim_cur" (otherwise, contiguous regions 321 * overlap). If stack limit is going up make more 322 * accessible, if going down make inaccessible. 323 */ 324 limp->rlim_cur = round_page(limp->rlim_cur); 325 if (limp->rlim_cur != alimp->rlim_cur) { 326 vaddr_t addr; 327 vsize_t size; 328 vm_prot_t prot; 329 330 if (limp->rlim_cur > alimp->rlim_cur) { 331 prot = VM_PROT_READ | VM_PROT_WRITE; 332 size = limp->rlim_cur - alimp->rlim_cur; 333 addr = USRSTACK - limp->rlim_cur; 334 } else { 335 prot = VM_PROT_NONE; 336 size = alimp->rlim_cur - limp->rlim_cur; 337 addr = USRSTACK - 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 static struct uidinfo * 895 getuidinfo(uid_t uid) 896 { 897 struct uidinfo *uip; 898 struct uihashhead *uipp; 899 900 uipp = UIHASH(uid); 901 902 LIST_FOREACH(uip, uipp, ui_hash) 903 if (uip->ui_uid == uid) 904 return uip; 905 return NULL; 906 } 907 908 static void 909 freeuidinfo(struct uidinfo *uip) 910 { 911 LIST_REMOVE(uip, ui_hash); 912 FREE(uip, M_PROC); 913 } 914 915 static struct uidinfo * 916 allocuidinfo(uid_t uid) 917 { 918 struct uidinfo *uip; 919 struct uihashhead *uipp; 920 921 uipp = UIHASH(uid); 922 MALLOC(uip, struct uidinfo *, sizeof(*uip), M_PROC, M_WAITOK); 923 LIST_INSERT_HEAD(uipp, uip, ui_hash); 924 uip->ui_uid = uid; 925 uip->ui_proccnt = 0; 926 uip->ui_sbsize = 0; 927 return uip; 928 } 929 930 /* 931 * Change the count associated with number of processes 932 * a given user is using. 933 */ 934 int 935 chgproccnt(uid_t uid, int diff) 936 { 937 struct uidinfo *uip; 938 939 if (diff == 0) 940 return 0; 941 942 if ((uip = getuidinfo(uid)) != NULL) { 943 uip->ui_proccnt += diff; 944 KASSERT(uip->ui_proccnt >= 0); 945 if (uip->ui_proccnt > 0) 946 return uip->ui_proccnt; 947 else { 948 if (uip->ui_sbsize == 0) 949 freeuidinfo(uip); 950 return 0; 951 } 952 } else { 953 if (diff < 0) 954 panic("chgproccnt: lost user %lu", (unsigned long)uid); 955 uip = allocuidinfo(uid); 956 uip->ui_proccnt = diff; 957 return uip->ui_proccnt; 958 } 959 } 960 961 int 962 chgsbsize(uid_t uid, u_long *hiwat, u_long to, rlim_t max) 963 { 964 *hiwat = to; 965 return 1; 966 #ifdef notyet 967 struct uidinfo *uip; 968 rlim_t nsb; 969 int rv = 0; 970 971 if ((uip = getuidinfo(uid)) == NULL) 972 uip = allocuidinfo(uid); 973 nsb = uip->ui_sbsize + to - *hiwat; 974 if (to > *hiwat && nsb > max) 975 goto done; 976 *hiwat = to; 977 uip->ui_sbsize = nsb; 978 rv = 1; 979 KASSERT(uip->ui_sbsize >= 0); 980 done: 981 if (uip->ui_sbsize == 0 && uip->ui_proccnt == 0) 982 freeuidinfo(uip); 983 return rv; 984 #endif 985 } 986