1 /* $NetBSD: kern_resource.c,v 1.162 2011/05/01 02:46:19 christos Exp $ */ 2 3 /*- 4 * Copyright (c) 1982, 1986, 1991, 1993 5 * The Regents of the University of California. All rights reserved. 6 * (c) UNIX System Laboratories, Inc. 7 * All or some portions of this file are derived from material licensed 8 * to the University of California by American Telephone and Telegraph 9 * Co. or Unix System Laboratories, Inc. and are reproduced herein with 10 * the permission of UNIX System Laboratories, Inc. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 3. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 * 36 * @(#)kern_resource.c 8.8 (Berkeley) 2/14/95 37 */ 38 39 #include <sys/cdefs.h> 40 __KERNEL_RCSID(0, "$NetBSD: kern_resource.c,v 1.162 2011/05/01 02:46:19 christos Exp $"); 41 42 #include <sys/param.h> 43 #include <sys/systm.h> 44 #include <sys/kernel.h> 45 #include <sys/file.h> 46 #include <sys/resourcevar.h> 47 #include <sys/malloc.h> 48 #include <sys/kmem.h> 49 #include <sys/namei.h> 50 #include <sys/pool.h> 51 #include <sys/proc.h> 52 #include <sys/sysctl.h> 53 #include <sys/timevar.h> 54 #include <sys/kauth.h> 55 #include <sys/atomic.h> 56 #include <sys/mount.h> 57 #include <sys/syscallargs.h> 58 #include <sys/atomic.h> 59 60 #include <uvm/uvm_extern.h> 61 62 /* 63 * Maximum process data and stack limits. 64 * They are variables so they are patchable. 65 */ 66 rlim_t maxdmap = MAXDSIZ; 67 rlim_t maxsmap = MAXSSIZ; 68 69 static pool_cache_t plimit_cache; 70 static pool_cache_t pstats_cache; 71 72 static kauth_listener_t resource_listener; 73 74 static void sysctl_proc_setup(void); 75 76 static int 77 resource_listener_cb(kauth_cred_t cred, kauth_action_t action, void *cookie, 78 void *arg0, void *arg1, void *arg2, void *arg3) 79 { 80 struct proc *p; 81 int result; 82 83 result = KAUTH_RESULT_DEFER; 84 p = arg0; 85 86 switch (action) { 87 case KAUTH_PROCESS_NICE: 88 if (kauth_cred_geteuid(cred) != kauth_cred_geteuid(p->p_cred) && 89 kauth_cred_getuid(cred) != kauth_cred_geteuid(p->p_cred)) { 90 break; 91 } 92 93 if ((u_long)arg1 >= p->p_nice) 94 result = KAUTH_RESULT_ALLOW; 95 96 break; 97 98 case KAUTH_PROCESS_RLIMIT: { 99 enum kauth_process_req req; 100 101 req = (enum kauth_process_req)(unsigned long)arg1; 102 103 switch (req) { 104 case KAUTH_REQ_PROCESS_RLIMIT_GET: 105 result = KAUTH_RESULT_ALLOW; 106 break; 107 108 case KAUTH_REQ_PROCESS_RLIMIT_SET: { 109 struct rlimit *new_rlimit; 110 u_long which; 111 112 if ((p != curlwp->l_proc) && 113 (proc_uidmatch(cred, p->p_cred) != 0)) 114 break; 115 116 new_rlimit = arg2; 117 which = (u_long)arg3; 118 119 if (new_rlimit->rlim_max <= p->p_rlimit[which].rlim_max) 120 result = KAUTH_RESULT_ALLOW; 121 122 break; 123 } 124 125 default: 126 break; 127 } 128 129 break; 130 } 131 132 default: 133 break; 134 } 135 136 return result; 137 } 138 139 void 140 resource_init(void) 141 { 142 143 plimit_cache = pool_cache_init(sizeof(struct plimit), 0, 0, 0, 144 "plimitpl", NULL, IPL_NONE, NULL, NULL, NULL); 145 pstats_cache = pool_cache_init(sizeof(struct pstats), 0, 0, 0, 146 "pstatspl", NULL, IPL_NONE, NULL, NULL, NULL); 147 148 resource_listener = kauth_listen_scope(KAUTH_SCOPE_PROCESS, 149 resource_listener_cb, NULL); 150 151 sysctl_proc_setup(); 152 } 153 154 /* 155 * Resource controls and accounting. 156 */ 157 158 int 159 sys_getpriority(struct lwp *l, const struct sys_getpriority_args *uap, 160 register_t *retval) 161 { 162 /* { 163 syscallarg(int) which; 164 syscallarg(id_t) who; 165 } */ 166 struct proc *curp = l->l_proc, *p; 167 int low = NZERO + PRIO_MAX + 1; 168 int who = SCARG(uap, who); 169 170 mutex_enter(proc_lock); 171 switch (SCARG(uap, which)) { 172 case PRIO_PROCESS: 173 p = who ? proc_find(who) : curp;; 174 if (p != NULL) 175 low = p->p_nice; 176 break; 177 178 case PRIO_PGRP: { 179 struct pgrp *pg; 180 181 if (who == 0) 182 pg = curp->p_pgrp; 183 else if ((pg = pgrp_find(who)) == NULL) 184 break; 185 LIST_FOREACH(p, &pg->pg_members, p_pglist) { 186 if (p->p_nice < low) 187 low = p->p_nice; 188 } 189 break; 190 } 191 192 case PRIO_USER: 193 if (who == 0) 194 who = (int)kauth_cred_geteuid(l->l_cred); 195 PROCLIST_FOREACH(p, &allproc) { 196 mutex_enter(p->p_lock); 197 if (kauth_cred_geteuid(p->p_cred) == 198 (uid_t)who && p->p_nice < low) 199 low = p->p_nice; 200 mutex_exit(p->p_lock); 201 } 202 break; 203 204 default: 205 mutex_exit(proc_lock); 206 return (EINVAL); 207 } 208 mutex_exit(proc_lock); 209 210 if (low == NZERO + PRIO_MAX + 1) 211 return (ESRCH); 212 *retval = low - NZERO; 213 return (0); 214 } 215 216 /* ARGSUSED */ 217 int 218 sys_setpriority(struct lwp *l, const struct sys_setpriority_args *uap, 219 register_t *retval) 220 { 221 /* { 222 syscallarg(int) which; 223 syscallarg(id_t) who; 224 syscallarg(int) prio; 225 } */ 226 struct proc *curp = l->l_proc, *p; 227 int found = 0, error = 0; 228 int who = SCARG(uap, who); 229 230 mutex_enter(proc_lock); 231 switch (SCARG(uap, which)) { 232 case PRIO_PROCESS: 233 p = who ? proc_find(who) : curp; 234 if (p != NULL) { 235 mutex_enter(p->p_lock); 236 found++; 237 error = donice(l, p, SCARG(uap, prio)); 238 mutex_exit(p->p_lock); 239 } 240 break; 241 242 case PRIO_PGRP: { 243 struct pgrp *pg; 244 245 if (who == 0) 246 pg = curp->p_pgrp; 247 else if ((pg = pgrp_find(who)) == NULL) 248 break; 249 LIST_FOREACH(p, &pg->pg_members, p_pglist) { 250 mutex_enter(p->p_lock); 251 found++; 252 error = donice(l, p, SCARG(uap, prio)); 253 mutex_exit(p->p_lock); 254 if (error) 255 break; 256 } 257 break; 258 } 259 260 case PRIO_USER: 261 if (who == 0) 262 who = (int)kauth_cred_geteuid(l->l_cred); 263 PROCLIST_FOREACH(p, &allproc) { 264 mutex_enter(p->p_lock); 265 if (kauth_cred_geteuid(p->p_cred) == 266 (uid_t)SCARG(uap, who)) { 267 found++; 268 error = donice(l, p, SCARG(uap, prio)); 269 } 270 mutex_exit(p->p_lock); 271 if (error) 272 break; 273 } 274 break; 275 276 default: 277 mutex_exit(proc_lock); 278 return EINVAL; 279 } 280 mutex_exit(proc_lock); 281 if (found == 0) 282 return ESRCH; 283 return error; 284 } 285 286 /* 287 * Renice a process. 288 * 289 * Call with the target process' credentials locked. 290 */ 291 int 292 donice(struct lwp *l, struct proc *chgp, int n) 293 { 294 kauth_cred_t cred = l->l_cred; 295 296 KASSERT(mutex_owned(chgp->p_lock)); 297 298 if (kauth_cred_geteuid(cred) && kauth_cred_getuid(cred) && 299 kauth_cred_geteuid(cred) != kauth_cred_geteuid(chgp->p_cred) && 300 kauth_cred_getuid(cred) != kauth_cred_geteuid(chgp->p_cred)) 301 return (EPERM); 302 303 if (n > PRIO_MAX) 304 n = PRIO_MAX; 305 if (n < PRIO_MIN) 306 n = PRIO_MIN; 307 n += NZERO; 308 if (kauth_authorize_process(cred, KAUTH_PROCESS_NICE, chgp, 309 KAUTH_ARG(n), NULL, NULL)) 310 return (EACCES); 311 sched_nice(chgp, n); 312 return (0); 313 } 314 315 /* ARGSUSED */ 316 int 317 sys_setrlimit(struct lwp *l, const struct sys_setrlimit_args *uap, 318 register_t *retval) 319 { 320 /* { 321 syscallarg(int) which; 322 syscallarg(const struct rlimit *) rlp; 323 } */ 324 int which = SCARG(uap, which); 325 struct rlimit alim; 326 int error; 327 328 error = copyin(SCARG(uap, rlp), &alim, sizeof(struct rlimit)); 329 if (error) 330 return (error); 331 return (dosetrlimit(l, l->l_proc, which, &alim)); 332 } 333 334 int 335 dosetrlimit(struct lwp *l, struct proc *p, int which, struct rlimit *limp) 336 { 337 struct rlimit *alimp; 338 int error; 339 340 if ((u_int)which >= RLIM_NLIMITS) 341 return (EINVAL); 342 343 if (limp->rlim_cur > limp->rlim_max) { 344 /* 345 * This is programming error. According to SUSv2, we should 346 * return error in this case. 347 */ 348 return (EINVAL); 349 } 350 351 alimp = &p->p_rlimit[which]; 352 /* if we don't change the value, no need to limcopy() */ 353 if (limp->rlim_cur == alimp->rlim_cur && 354 limp->rlim_max == alimp->rlim_max) 355 return 0; 356 357 error = kauth_authorize_process(l->l_cred, KAUTH_PROCESS_RLIMIT, 358 p, KAUTH_ARG(KAUTH_REQ_PROCESS_RLIMIT_SET), limp, KAUTH_ARG(which)); 359 if (error) 360 return (error); 361 362 lim_privatise(p); 363 /* p->p_limit is now unchangeable */ 364 alimp = &p->p_rlimit[which]; 365 366 switch (which) { 367 368 case RLIMIT_DATA: 369 if (limp->rlim_cur > maxdmap) 370 limp->rlim_cur = maxdmap; 371 if (limp->rlim_max > maxdmap) 372 limp->rlim_max = maxdmap; 373 break; 374 375 case RLIMIT_STACK: 376 if (limp->rlim_cur > maxsmap) 377 limp->rlim_cur = maxsmap; 378 if (limp->rlim_max > maxsmap) 379 limp->rlim_max = maxsmap; 380 381 /* 382 * Return EINVAL if the new stack size limit is lower than 383 * current usage. Otherwise, the process would get SIGSEGV the 384 * moment it would try to access anything on it's current stack. 385 * This conforms to SUSv2. 386 */ 387 if (limp->rlim_cur < p->p_vmspace->vm_ssize * PAGE_SIZE 388 || limp->rlim_max < p->p_vmspace->vm_ssize * PAGE_SIZE) { 389 return (EINVAL); 390 } 391 392 /* 393 * Stack is allocated to the max at exec time with 394 * only "rlim_cur" bytes accessible (In other words, 395 * allocates stack dividing two contiguous regions at 396 * "rlim_cur" bytes boundary). 397 * 398 * Since allocation is done in terms of page, roundup 399 * "rlim_cur" (otherwise, contiguous regions 400 * overlap). If stack limit is going up make more 401 * accessible, if going down make inaccessible. 402 */ 403 limp->rlim_cur = round_page(limp->rlim_cur); 404 if (limp->rlim_cur != alimp->rlim_cur) { 405 vaddr_t addr; 406 vsize_t size; 407 vm_prot_t prot; 408 409 if (limp->rlim_cur > alimp->rlim_cur) { 410 prot = VM_PROT_READ | VM_PROT_WRITE; 411 size = limp->rlim_cur - alimp->rlim_cur; 412 addr = (vaddr_t)p->p_vmspace->vm_minsaddr - 413 limp->rlim_cur; 414 } else { 415 prot = VM_PROT_NONE; 416 size = alimp->rlim_cur - limp->rlim_cur; 417 addr = (vaddr_t)p->p_vmspace->vm_minsaddr - 418 alimp->rlim_cur; 419 } 420 (void) uvm_map_protect(&p->p_vmspace->vm_map, 421 addr, addr+size, prot, false); 422 } 423 break; 424 425 case RLIMIT_NOFILE: 426 if (limp->rlim_cur > maxfiles) 427 limp->rlim_cur = maxfiles; 428 if (limp->rlim_max > maxfiles) 429 limp->rlim_max = maxfiles; 430 break; 431 432 case RLIMIT_NPROC: 433 if (limp->rlim_cur > maxproc) 434 limp->rlim_cur = maxproc; 435 if (limp->rlim_max > maxproc) 436 limp->rlim_max = maxproc; 437 break; 438 } 439 440 mutex_enter(&p->p_limit->pl_lock); 441 *alimp = *limp; 442 mutex_exit(&p->p_limit->pl_lock); 443 return (0); 444 } 445 446 /* ARGSUSED */ 447 int 448 sys_getrlimit(struct lwp *l, const struct sys_getrlimit_args *uap, 449 register_t *retval) 450 { 451 /* { 452 syscallarg(int) which; 453 syscallarg(struct rlimit *) rlp; 454 } */ 455 struct proc *p = l->l_proc; 456 int which = SCARG(uap, which); 457 struct rlimit rl; 458 459 if ((u_int)which >= RLIM_NLIMITS) 460 return (EINVAL); 461 462 mutex_enter(p->p_lock); 463 memcpy(&rl, &p->p_rlimit[which], sizeof(rl)); 464 mutex_exit(p->p_lock); 465 466 return copyout(&rl, SCARG(uap, rlp), sizeof(rl)); 467 } 468 469 /* 470 * Transform the running time and tick information in proc p into user, 471 * system, and interrupt time usage. 472 * 473 * Should be called with p->p_lock held unless called from exit1(). 474 */ 475 void 476 calcru(struct proc *p, struct timeval *up, struct timeval *sp, 477 struct timeval *ip, struct timeval *rp) 478 { 479 uint64_t u, st, ut, it, tot; 480 struct lwp *l; 481 struct bintime tm; 482 struct timeval tv; 483 484 mutex_spin_enter(&p->p_stmutex); 485 st = p->p_sticks; 486 ut = p->p_uticks; 487 it = p->p_iticks; 488 mutex_spin_exit(&p->p_stmutex); 489 490 tm = p->p_rtime; 491 492 LIST_FOREACH(l, &p->p_lwps, l_sibling) { 493 lwp_lock(l); 494 bintime_add(&tm, &l->l_rtime); 495 if ((l->l_pflag & LP_RUNNING) != 0) { 496 struct bintime diff; 497 /* 498 * Adjust for the current time slice. This is 499 * actually fairly important since the error 500 * here is on the order of a time quantum, 501 * which is much greater than the sampling 502 * error. 503 */ 504 binuptime(&diff); 505 bintime_sub(&diff, &l->l_stime); 506 bintime_add(&tm, &diff); 507 } 508 lwp_unlock(l); 509 } 510 511 tot = st + ut + it; 512 bintime2timeval(&tm, &tv); 513 u = (uint64_t)tv.tv_sec * 1000000ul + tv.tv_usec; 514 515 if (tot == 0) { 516 /* No ticks, so can't use to share time out, split 50-50 */ 517 st = ut = u / 2; 518 } else { 519 st = (u * st) / tot; 520 ut = (u * ut) / tot; 521 } 522 if (sp != NULL) { 523 sp->tv_sec = st / 1000000; 524 sp->tv_usec = st % 1000000; 525 } 526 if (up != NULL) { 527 up->tv_sec = ut / 1000000; 528 up->tv_usec = ut % 1000000; 529 } 530 if (ip != NULL) { 531 if (it != 0) 532 it = (u * it) / tot; 533 ip->tv_sec = it / 1000000; 534 ip->tv_usec = it % 1000000; 535 } 536 if (rp != NULL) { 537 *rp = tv; 538 } 539 } 540 541 /* ARGSUSED */ 542 int 543 sys___getrusage50(struct lwp *l, const struct sys___getrusage50_args *uap, 544 register_t *retval) 545 { 546 /* { 547 syscallarg(int) who; 548 syscallarg(struct rusage *) rusage; 549 } */ 550 struct rusage ru; 551 struct proc *p = l->l_proc; 552 553 switch (SCARG(uap, who)) { 554 case RUSAGE_SELF: 555 mutex_enter(p->p_lock); 556 memcpy(&ru, &p->p_stats->p_ru, sizeof(ru)); 557 calcru(p, &ru.ru_utime, &ru.ru_stime, NULL, NULL); 558 rulwps(p, &ru); 559 mutex_exit(p->p_lock); 560 break; 561 562 case RUSAGE_CHILDREN: 563 mutex_enter(p->p_lock); 564 memcpy(&ru, &p->p_stats->p_cru, sizeof(ru)); 565 mutex_exit(p->p_lock); 566 break; 567 568 default: 569 return EINVAL; 570 } 571 572 return copyout(&ru, SCARG(uap, rusage), sizeof(ru)); 573 } 574 575 void 576 ruadd(struct rusage *ru, struct rusage *ru2) 577 { 578 long *ip, *ip2; 579 int i; 580 581 timeradd(&ru->ru_utime, &ru2->ru_utime, &ru->ru_utime); 582 timeradd(&ru->ru_stime, &ru2->ru_stime, &ru->ru_stime); 583 if (ru->ru_maxrss < ru2->ru_maxrss) 584 ru->ru_maxrss = ru2->ru_maxrss; 585 ip = &ru->ru_first; ip2 = &ru2->ru_first; 586 for (i = &ru->ru_last - &ru->ru_first; i >= 0; i--) 587 *ip++ += *ip2++; 588 } 589 590 void 591 rulwps(proc_t *p, struct rusage *ru) 592 { 593 lwp_t *l; 594 595 KASSERT(mutex_owned(p->p_lock)); 596 597 LIST_FOREACH(l, &p->p_lwps, l_sibling) { 598 ruadd(ru, &l->l_ru); 599 ru->ru_nvcsw += (l->l_ncsw - l->l_nivcsw); 600 ru->ru_nivcsw += l->l_nivcsw; 601 } 602 } 603 604 /* 605 * lim_copy: make a copy of the plimit structure. 606 * 607 * We use copy-on-write after fork, and copy when a limit is changed. 608 */ 609 struct plimit * 610 lim_copy(struct plimit *lim) 611 { 612 struct plimit *newlim; 613 char *corename; 614 size_t alen, len; 615 616 newlim = pool_cache_get(plimit_cache, PR_WAITOK); 617 mutex_init(&newlim->pl_lock, MUTEX_DEFAULT, IPL_NONE); 618 newlim->pl_writeable = false; 619 newlim->pl_refcnt = 1; 620 newlim->pl_sv_limit = NULL; 621 622 mutex_enter(&lim->pl_lock); 623 memcpy(newlim->pl_rlimit, lim->pl_rlimit, 624 sizeof(struct rlimit) * RLIM_NLIMITS); 625 626 /* 627 * Note: the common case is a use of default core name. 628 */ 629 alen = 0; 630 corename = NULL; 631 for (;;) { 632 if (lim->pl_corename == defcorename) { 633 newlim->pl_corename = defcorename; 634 newlim->pl_cnlen = 0; 635 break; 636 } 637 len = lim->pl_cnlen; 638 if (len == alen) { 639 newlim->pl_corename = corename; 640 newlim->pl_cnlen = len; 641 memcpy(corename, lim->pl_corename, len); 642 corename = NULL; 643 break; 644 } 645 mutex_exit(&lim->pl_lock); 646 if (corename) { 647 kmem_free(corename, alen); 648 } 649 alen = len; 650 corename = kmem_alloc(alen, KM_SLEEP); 651 mutex_enter(&lim->pl_lock); 652 } 653 mutex_exit(&lim->pl_lock); 654 655 if (corename) { 656 kmem_free(corename, alen); 657 } 658 return newlim; 659 } 660 661 void 662 lim_addref(struct plimit *lim) 663 { 664 atomic_inc_uint(&lim->pl_refcnt); 665 } 666 667 /* 668 * lim_privatise: give a process its own private plimit structure. 669 */ 670 void 671 lim_privatise(proc_t *p) 672 { 673 struct plimit *lim = p->p_limit, *newlim; 674 675 if (lim->pl_writeable) { 676 return; 677 } 678 679 newlim = lim_copy(lim); 680 681 mutex_enter(p->p_lock); 682 if (p->p_limit->pl_writeable) { 683 /* Other thread won the race. */ 684 mutex_exit(p->p_lock); 685 lim_free(newlim); 686 return; 687 } 688 689 /* 690 * Since p->p_limit can be accessed without locked held, 691 * old limit structure must not be deleted yet. 692 */ 693 newlim->pl_sv_limit = p->p_limit; 694 newlim->pl_writeable = true; 695 p->p_limit = newlim; 696 mutex_exit(p->p_lock); 697 } 698 699 void 700 lim_setcorename(proc_t *p, char *name, size_t len) 701 { 702 struct plimit *lim; 703 char *oname; 704 size_t olen; 705 706 lim_privatise(p); 707 lim = p->p_limit; 708 709 mutex_enter(&lim->pl_lock); 710 oname = lim->pl_corename; 711 olen = lim->pl_cnlen; 712 lim->pl_corename = name; 713 lim->pl_cnlen = len; 714 mutex_exit(&lim->pl_lock); 715 716 if (oname != defcorename) { 717 kmem_free(oname, olen); 718 } 719 } 720 721 void 722 lim_free(struct plimit *lim) 723 { 724 struct plimit *sv_lim; 725 726 do { 727 if (atomic_dec_uint_nv(&lim->pl_refcnt) > 0) { 728 return; 729 } 730 if (lim->pl_corename != defcorename) { 731 kmem_free(lim->pl_corename, lim->pl_cnlen); 732 } 733 sv_lim = lim->pl_sv_limit; 734 mutex_destroy(&lim->pl_lock); 735 pool_cache_put(plimit_cache, lim); 736 } while ((lim = sv_lim) != NULL); 737 } 738 739 struct pstats * 740 pstatscopy(struct pstats *ps) 741 { 742 743 struct pstats *newps; 744 745 newps = pool_cache_get(pstats_cache, PR_WAITOK); 746 747 memset(&newps->pstat_startzero, 0, 748 (unsigned) ((char *)&newps->pstat_endzero - 749 (char *)&newps->pstat_startzero)); 750 memcpy(&newps->pstat_startcopy, &ps->pstat_startcopy, 751 ((char *)&newps->pstat_endcopy - 752 (char *)&newps->pstat_startcopy)); 753 754 return (newps); 755 756 } 757 758 void 759 pstatsfree(struct pstats *ps) 760 { 761 762 pool_cache_put(pstats_cache, ps); 763 } 764 765 /* 766 * sysctl interface in five parts 767 */ 768 769 /* 770 * sysctl_proc_findproc: a routine for sysctl proc subtree helpers that 771 * need to pick a valid process by PID. 772 * 773 * => Hold a reference on the process, on success. 774 */ 775 static int 776 sysctl_proc_findproc(lwp_t *l, pid_t pid, proc_t **p2) 777 { 778 proc_t *p; 779 int error; 780 781 if (pid == PROC_CURPROC) { 782 p = l->l_proc; 783 } else { 784 mutex_enter(proc_lock); 785 p = proc_find(pid); 786 if (p == NULL) { 787 mutex_exit(proc_lock); 788 return ESRCH; 789 } 790 } 791 error = rw_tryenter(&p->p_reflock, RW_READER) ? 0 : EBUSY; 792 if (pid != PROC_CURPROC) { 793 mutex_exit(proc_lock); 794 } 795 *p2 = p; 796 return error; 797 } 798 799 /* 800 * sysctl_proc_corename: helper routine to get or set the core file name 801 * for a process specified by PID. 802 */ 803 static int 804 sysctl_proc_corename(SYSCTLFN_ARGS) 805 { 806 struct proc *p; 807 struct plimit *lim; 808 char *cnbuf, *cname; 809 struct sysctlnode node; 810 size_t len; 811 int error; 812 813 /* First, validate the request. */ 814 if (namelen != 0 || name[-1] != PROC_PID_CORENAME) 815 return EINVAL; 816 817 /* Find the process. Hold a reference (p_reflock), if found. */ 818 error = sysctl_proc_findproc(l, (pid_t)name[-2], &p); 819 if (error) 820 return error; 821 822 /* XXX-elad */ 823 error = kauth_authorize_process(l->l_cred, KAUTH_PROCESS_CANSEE, p, 824 KAUTH_ARG(KAUTH_REQ_PROCESS_CANSEE_ENTRY), NULL, NULL); 825 if (error) { 826 rw_exit(&p->p_reflock); 827 return error; 828 } 829 830 cnbuf = PNBUF_GET(); 831 832 if (newp == NULL) { 833 /* Get case: copy the core name into the buffer. */ 834 error = kauth_authorize_process(l->l_cred, 835 KAUTH_PROCESS_CORENAME, p, 836 KAUTH_ARG(KAUTH_REQ_PROCESS_CORENAME_GET), NULL, NULL); 837 if (error) { 838 goto done; 839 } 840 lim = p->p_limit; 841 mutex_enter(&lim->pl_lock); 842 strlcpy(cnbuf, lim->pl_corename, MAXPATHLEN); 843 mutex_exit(&lim->pl_lock); 844 } else { 845 /* Set case: just use the temporary buffer. */ 846 error = kauth_authorize_process(l->l_cred, 847 KAUTH_PROCESS_CORENAME, p, 848 KAUTH_ARG(KAUTH_REQ_PROCESS_CORENAME_SET), cnbuf, NULL); 849 if (error) { 850 goto done; 851 } 852 } 853 854 node = *rnode; 855 node.sysctl_data = cnbuf; 856 error = sysctl_lookup(SYSCTLFN_CALL(&node)); 857 858 /* Return if error, or if we are only retrieving the core name. */ 859 if (error || newp == NULL) { 860 goto done; 861 } 862 863 /* 864 * Validate new core name. It must be either "core", "/core", 865 * or end in ".core". 866 */ 867 len = strlen(cnbuf); 868 if ((len < 4 || strcmp(cnbuf + len - 4, "core") != 0) || 869 (len > 4 && cnbuf[len - 5] != '/' && cnbuf[len - 5] != '.')) { 870 error = EINVAL; 871 goto done; 872 } 873 874 /* Allocate, copy and set the new core name for plimit structure. */ 875 cname = kmem_alloc(++len, KM_NOSLEEP); 876 if (cname == NULL) { 877 error = ENOMEM; 878 goto done; 879 } 880 memcpy(cname, cnbuf, len); 881 lim_setcorename(p, cname, len); 882 done: 883 rw_exit(&p->p_reflock); 884 PNBUF_PUT(cnbuf); 885 return error; 886 } 887 888 /* 889 * sysctl helper routine for checking/setting a process's stop flags, 890 * one for fork and one for exec. 891 */ 892 static int 893 sysctl_proc_stop(SYSCTLFN_ARGS) 894 { 895 struct proc *ptmp; 896 int i, f, error = 0; 897 struct sysctlnode node; 898 899 if (namelen != 0) 900 return (EINVAL); 901 902 /* Find the process. Hold a reference (p_reflock), if found. */ 903 error = sysctl_proc_findproc(l, (pid_t)name[-2], &ptmp); 904 if (error) 905 return error; 906 907 /* XXX-elad */ 908 error = kauth_authorize_process(l->l_cred, KAUTH_PROCESS_CANSEE, ptmp, 909 KAUTH_ARG(KAUTH_REQ_PROCESS_CANSEE_ENTRY), NULL, NULL); 910 if (error) 911 goto out; 912 913 switch (rnode->sysctl_num) { 914 case PROC_PID_STOPFORK: 915 f = PS_STOPFORK; 916 break; 917 case PROC_PID_STOPEXEC: 918 f = PS_STOPEXEC; 919 break; 920 case PROC_PID_STOPEXIT: 921 f = PS_STOPEXIT; 922 break; 923 default: 924 error = EINVAL; 925 goto out; 926 } 927 928 i = (ptmp->p_flag & f) ? 1 : 0; 929 node = *rnode; 930 node.sysctl_data = &i; 931 error = sysctl_lookup(SYSCTLFN_CALL(&node)); 932 if (error || newp == NULL) 933 goto out; 934 935 mutex_enter(ptmp->p_lock); 936 error = kauth_authorize_process(l->l_cred, KAUTH_PROCESS_STOPFLAG, 937 ptmp, KAUTH_ARG(f), NULL, NULL); 938 if (!error) { 939 if (i) { 940 ptmp->p_sflag |= f; 941 } else { 942 ptmp->p_sflag &= ~f; 943 } 944 } 945 mutex_exit(ptmp->p_lock); 946 out: 947 rw_exit(&ptmp->p_reflock); 948 return error; 949 } 950 951 /* 952 * sysctl helper routine for a process's rlimits as exposed by sysctl. 953 */ 954 static int 955 sysctl_proc_plimit(SYSCTLFN_ARGS) 956 { 957 struct proc *ptmp; 958 u_int limitno; 959 int which, error = 0; 960 struct rlimit alim; 961 struct sysctlnode node; 962 963 if (namelen != 0) 964 return (EINVAL); 965 966 which = name[-1]; 967 if (which != PROC_PID_LIMIT_TYPE_SOFT && 968 which != PROC_PID_LIMIT_TYPE_HARD) 969 return (EINVAL); 970 971 limitno = name[-2] - 1; 972 if (limitno >= RLIM_NLIMITS) 973 return (EINVAL); 974 975 if (name[-3] != PROC_PID_LIMIT) 976 return (EINVAL); 977 978 /* Find the process. Hold a reference (p_reflock), if found. */ 979 error = sysctl_proc_findproc(l, (pid_t)name[-4], &ptmp); 980 if (error) 981 return error; 982 983 /* XXX-elad */ 984 error = kauth_authorize_process(l->l_cred, KAUTH_PROCESS_CANSEE, ptmp, 985 KAUTH_ARG(KAUTH_REQ_PROCESS_CANSEE_ENTRY), NULL, NULL); 986 if (error) 987 goto out; 988 989 /* Check if we can view limits. */ 990 if (newp == NULL) { 991 error = kauth_authorize_process(l->l_cred, KAUTH_PROCESS_RLIMIT, 992 ptmp, KAUTH_ARG(KAUTH_REQ_PROCESS_RLIMIT_GET), &alim, 993 KAUTH_ARG(which)); 994 if (error) 995 goto out; 996 } 997 998 node = *rnode; 999 memcpy(&alim, &ptmp->p_rlimit[limitno], sizeof(alim)); 1000 if (which == PROC_PID_LIMIT_TYPE_HARD) 1001 node.sysctl_data = &alim.rlim_max; 1002 else 1003 node.sysctl_data = &alim.rlim_cur; 1004 1005 error = sysctl_lookup(SYSCTLFN_CALL(&node)); 1006 if (error || newp == NULL) { 1007 goto out; 1008 } 1009 error = dosetrlimit(l, ptmp, limitno, &alim); 1010 out: 1011 rw_exit(&ptmp->p_reflock); 1012 return error; 1013 } 1014 1015 static struct sysctllog *proc_sysctllog; 1016 1017 /* 1018 * and finally, the actually glue that sticks it to the tree 1019 */ 1020 static void 1021 sysctl_proc_setup() 1022 { 1023 1024 sysctl_createv(&proc_sysctllog, 0, NULL, NULL, 1025 CTLFLAG_PERMANENT, 1026 CTLTYPE_NODE, "proc", NULL, 1027 NULL, 0, NULL, 0, 1028 CTL_PROC, CTL_EOL); 1029 sysctl_createv(&proc_sysctllog, 0, NULL, NULL, 1030 CTLFLAG_PERMANENT|CTLFLAG_ANYNUMBER, 1031 CTLTYPE_NODE, "curproc", 1032 SYSCTL_DESCR("Per-process settings"), 1033 NULL, 0, NULL, 0, 1034 CTL_PROC, PROC_CURPROC, CTL_EOL); 1035 1036 sysctl_createv(&proc_sysctllog, 0, NULL, NULL, 1037 CTLFLAG_PERMANENT|CTLFLAG_READWRITE|CTLFLAG_ANYWRITE, 1038 CTLTYPE_STRING, "corename", 1039 SYSCTL_DESCR("Core file name"), 1040 sysctl_proc_corename, 0, NULL, MAXPATHLEN, 1041 CTL_PROC, PROC_CURPROC, PROC_PID_CORENAME, CTL_EOL); 1042 sysctl_createv(&proc_sysctllog, 0, NULL, NULL, 1043 CTLFLAG_PERMANENT, 1044 CTLTYPE_NODE, "rlimit", 1045 SYSCTL_DESCR("Process limits"), 1046 NULL, 0, NULL, 0, 1047 CTL_PROC, PROC_CURPROC, PROC_PID_LIMIT, CTL_EOL); 1048 1049 #define create_proc_plimit(s, n) do { \ 1050 sysctl_createv(&proc_sysctllog, 0, NULL, NULL, \ 1051 CTLFLAG_PERMANENT, \ 1052 CTLTYPE_NODE, s, \ 1053 SYSCTL_DESCR("Process " s " limits"), \ 1054 NULL, 0, NULL, 0, \ 1055 CTL_PROC, PROC_CURPROC, PROC_PID_LIMIT, n, \ 1056 CTL_EOL); \ 1057 sysctl_createv(&proc_sysctllog, 0, NULL, NULL, \ 1058 CTLFLAG_PERMANENT|CTLFLAG_READWRITE|CTLFLAG_ANYWRITE, \ 1059 CTLTYPE_QUAD, "soft", \ 1060 SYSCTL_DESCR("Process soft " s " limit"), \ 1061 sysctl_proc_plimit, 0, NULL, 0, \ 1062 CTL_PROC, PROC_CURPROC, PROC_PID_LIMIT, n, \ 1063 PROC_PID_LIMIT_TYPE_SOFT, CTL_EOL); \ 1064 sysctl_createv(&proc_sysctllog, 0, NULL, NULL, \ 1065 CTLFLAG_PERMANENT|CTLFLAG_READWRITE|CTLFLAG_ANYWRITE, \ 1066 CTLTYPE_QUAD, "hard", \ 1067 SYSCTL_DESCR("Process hard " s " limit"), \ 1068 sysctl_proc_plimit, 0, NULL, 0, \ 1069 CTL_PROC, PROC_CURPROC, PROC_PID_LIMIT, n, \ 1070 PROC_PID_LIMIT_TYPE_HARD, CTL_EOL); \ 1071 } while (0/*CONSTCOND*/) 1072 1073 create_proc_plimit("cputime", PROC_PID_LIMIT_CPU); 1074 create_proc_plimit("filesize", PROC_PID_LIMIT_FSIZE); 1075 create_proc_plimit("datasize", PROC_PID_LIMIT_DATA); 1076 create_proc_plimit("stacksize", PROC_PID_LIMIT_STACK); 1077 create_proc_plimit("coredumpsize", PROC_PID_LIMIT_CORE); 1078 create_proc_plimit("memoryuse", PROC_PID_LIMIT_RSS); 1079 create_proc_plimit("memorylocked", PROC_PID_LIMIT_MEMLOCK); 1080 create_proc_plimit("maxproc", PROC_PID_LIMIT_NPROC); 1081 create_proc_plimit("descriptors", PROC_PID_LIMIT_NOFILE); 1082 create_proc_plimit("sbsize", PROC_PID_LIMIT_SBSIZE); 1083 create_proc_plimit("vmemoryuse", PROC_PID_LIMIT_AS); 1084 1085 #undef create_proc_plimit 1086 1087 sysctl_createv(&proc_sysctllog, 0, NULL, NULL, 1088 CTLFLAG_PERMANENT|CTLFLAG_READWRITE|CTLFLAG_ANYWRITE, 1089 CTLTYPE_INT, "stopfork", 1090 SYSCTL_DESCR("Stop process at fork(2)"), 1091 sysctl_proc_stop, 0, NULL, 0, 1092 CTL_PROC, PROC_CURPROC, PROC_PID_STOPFORK, CTL_EOL); 1093 sysctl_createv(&proc_sysctllog, 0, NULL, NULL, 1094 CTLFLAG_PERMANENT|CTLFLAG_READWRITE|CTLFLAG_ANYWRITE, 1095 CTLTYPE_INT, "stopexec", 1096 SYSCTL_DESCR("Stop process at execve(2)"), 1097 sysctl_proc_stop, 0, NULL, 0, 1098 CTL_PROC, PROC_CURPROC, PROC_PID_STOPEXEC, CTL_EOL); 1099 sysctl_createv(&proc_sysctllog, 0, NULL, NULL, 1100 CTLFLAG_PERMANENT|CTLFLAG_READWRITE|CTLFLAG_ANYWRITE, 1101 CTLTYPE_INT, "stopexit", 1102 SYSCTL_DESCR("Stop process before completing exit"), 1103 sysctl_proc_stop, 0, NULL, 0, 1104 CTL_PROC, PROC_CURPROC, PROC_PID_STOPEXIT, CTL_EOL); 1105 } 1106