1/* 2 * Copyright (c) 2000-2008 Apple Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28/* Copyright (c) 1995, 1997 Apple Computer, Inc. All Rights Reserved */ 29/*- 30 * Copyright (c) 1982, 1986, 1991, 1993 31 * The Regents of the University of California. All rights reserved. 32 * (c) UNIX System Laboratories, Inc. 33 * All or some portions of this file are derived from material licensed 34 * to the University of California by American Telephone and Telegraph 35 * Co. or Unix System Laboratories, Inc. and are reproduced herein with 36 * the permission of UNIX System Laboratories, Inc. 37 * 38 * Redistribution and use in source and binary forms, with or without 39 * modification, are permitted provided that the following conditions 40 * are met: 41 * 1. Redistributions of source code must retain the above copyright 42 * notice, this list of conditions and the following disclaimer. 43 * 2. Redistributions in binary form must reproduce the above copyright 44 * notice, this list of conditions and the following disclaimer in the 45 * documentation and/or other materials provided with the distribution. 46 * 3. All advertising materials mentioning features or use of this software 47 * must display the following acknowledgement: 48 * This product includes software developed by the University of 49 * California, Berkeley and its contributors. 50 * 4. Neither the name of the University nor the names of its contributors 51 * may be used to endorse or promote products derived from this software 52 * without specific prior written permission. 53 * 54 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 55 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 56 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 57 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 58 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 59 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 60 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 61 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 62 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 63 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 64 * SUCH DAMAGE. 65 * 66 * @(#)kern_resource.c 8.5 (Berkeley) 1/21/94 67 */ 68/* 69 * NOTICE: This file was modified by SPARTA, Inc. in 2005 to introduce 70 * support for mandatory and extensible security protections. This notice 71 * is included in support of clause 2.2 (b) of the Apple Public License, 72 * Version 2.0. 73 */ 74 75#include <sys/param.h> 76#include <sys/systm.h> 77#include <sys/sysctl.h> 78#include <sys/kernel.h> 79#include <sys/file_internal.h> 80#include <sys/resourcevar.h> 81#include <sys/malloc.h> 82#include <sys/proc_internal.h> 83#include <sys/kauth.h> 84#include <machine/spl.h> 85 86#include <sys/mount_internal.h> 87#include <sys/sysproto.h> 88 89#include <security/audit/audit.h> 90 91#include <machine/vmparam.h> 92 93#include <mach/mach_types.h> 94#include <mach/time_value.h> 95#include <mach/task.h> 96#include <mach/task_info.h> 97#include <mach/vm_map.h> 98#include <mach/mach_vm.h> 99#include <mach/thread_act.h> /* for thread_policy_set( ) */ 100#include <kern/thread.h> 101 102#include <kern/task.h> 103#include <kern/clock.h> /* for absolutetime_to_microtime() */ 104#include <netinet/in.h> /* for TRAFFIC_MGT_SO_* */ 105#include <sys/socketvar.h> /* for struct socket */ 106 107#include <vm/vm_map.h> 108 109#include <kern/assert.h> 110#include <sys/resource.h> 111 112int donice(struct proc *curp, struct proc *chgp, int n); 113int dosetrlimit(struct proc *p, u_int which, struct rlimit *limp); 114int uthread_get_background_state(uthread_t); 115static void do_background_socket(struct proc *p, thread_t thread); 116static int do_background_thread(struct proc *curp, thread_t thread, int priority); 117static int do_background_proc(struct proc *curp, struct proc *targetp, int priority); 118static int set_gpudeny_proc(struct proc *curp, struct proc *targetp, int priority); 119static int proc_set_darwin_role(proc_t curp, proc_t targetp, int priority); 120static int proc_get_darwin_role(proc_t curp, proc_t targetp, int *priority); 121static int get_background_proc(struct proc *curp, struct proc *targetp, int *priority); 122void proc_apply_task_networkbg_internal(proc_t, thread_t); 123void proc_restore_task_networkbg_internal(proc_t, thread_t); 124int proc_pid_rusage(int pid, int flavor, user_addr_t buf, int32_t *retval); 125void gather_rusage_info(proc_t p, rusage_info_current *ru, int flavor); 126int fill_task_rusage(task_t task, rusage_info_current *ri); 127void fill_task_billed_usage(task_t task, rusage_info_current *ri); 128int fill_task_io_rusage(task_t task, rusage_info_current *ri); 129int fill_task_qos_rusage(task_t task, rusage_info_current *ri); 130static void rusage_info_conversion(rusage_info_t ri_info, rusage_info_current *ri_current, int flavor); 131 132int proc_get_rusage(proc_t p, int flavor, user_addr_t buffer, __unused int is_zombie); 133 134rlim_t maxdmap = MAXDSIZ; /* XXX */ 135rlim_t maxsmap = MAXSSIZ - PAGE_MAX_SIZE; /* XXX */ 136 137/* 138 * Limits on the number of open files per process, and the number 139 * of child processes per process. 140 * 141 * Note: would be in kern/subr_param.c in FreeBSD. 142 */ 143__private_extern__ int maxfilesperproc = OPEN_MAX; /* per-proc open files limit */ 144 145SYSCTL_INT(_kern, KERN_MAXPROCPERUID, maxprocperuid, CTLFLAG_RW | CTLFLAG_LOCKED, 146 &maxprocperuid, 0, "Maximum processes allowed per userid" ); 147 148SYSCTL_INT(_kern, KERN_MAXFILESPERPROC, maxfilesperproc, CTLFLAG_RW | CTLFLAG_LOCKED, 149 &maxfilesperproc, 0, "Maximum files allowed open per process" ); 150 151/* Args and fn for proc_iteration callback used in setpriority */ 152struct puser_nice_args { 153 proc_t curp; 154 int prio; 155 id_t who; 156 int * foundp; 157 int * errorp; 158}; 159static int puser_donice_callback(proc_t p, void * arg); 160 161 162/* Args and fn for proc_iteration callback used in setpriority */ 163struct ppgrp_nice_args { 164 proc_t curp; 165 int prio; 166 int * foundp; 167 int * errorp; 168}; 169static int ppgrp_donice_callback(proc_t p, void * arg); 170 171/* 172 * Resource controls and accounting. 173 */ 174int 175getpriority(struct proc *curp, struct getpriority_args *uap, int32_t *retval) 176{ 177 struct proc *p; 178 int low = PRIO_MAX + 1; 179 kauth_cred_t my_cred; 180 int refheld = 0; 181 int error = 0; 182 183 /* would also test (uap->who < 0), but id_t is unsigned */ 184 if (uap->who > 0x7fffffff) 185 return (EINVAL); 186 187 switch (uap->which) { 188 189 case PRIO_PROCESS: 190 if (uap->who == 0) { 191 p = curp; 192 low = p->p_nice; 193 } else { 194 p = proc_find(uap->who); 195 if (p == 0) 196 break; 197 low = p->p_nice; 198 proc_rele(p); 199 200 } 201 break; 202 203 case PRIO_PGRP: { 204 struct pgrp *pg = PGRP_NULL; 205 206 if (uap->who == 0) { 207 /* returns the pgrp to ref */ 208 pg = proc_pgrp(curp); 209 } else if ((pg = pgfind(uap->who)) == PGRP_NULL) { 210 break; 211 } 212 /* No need for iteration as it is a simple scan */ 213 pgrp_lock(pg); 214 for (p = pg->pg_members.lh_first; p != 0; p = p->p_pglist.le_next) { 215 if (p->p_nice < low) 216 low = p->p_nice; 217 } 218 pgrp_unlock(pg); 219 pg_rele(pg); 220 break; 221 } 222 223 case PRIO_USER: 224 if (uap->who == 0) 225 uap->who = kauth_cred_getuid(kauth_cred_get()); 226 227 proc_list_lock(); 228 229 for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) { 230 my_cred = kauth_cred_proc_ref(p); 231 if (kauth_cred_getuid(my_cred) == uap->who && 232 p->p_nice < low) 233 low = p->p_nice; 234 kauth_cred_unref(&my_cred); 235 } 236 237 proc_list_unlock(); 238 239 break; 240 241 case PRIO_DARWIN_THREAD: 242 /* we currently only support the current thread */ 243 if (uap->who != 0) 244 return (EINVAL); 245 246 low = proc_get_task_policy(current_task(), current_thread(), TASK_POLICY_INTERNAL, TASK_POLICY_DARWIN_BG); 247 248 break; 249 250 case PRIO_DARWIN_PROCESS: 251 if (uap->who == 0) { 252 p = curp; 253 } else { 254 p = proc_find(uap->who); 255 if (p == PROC_NULL) 256 break; 257 refheld = 1; 258 } 259 260 error = get_background_proc(curp, p, &low); 261 262 if (refheld) 263 proc_rele(p); 264 if (error) 265 return (error); 266 break; 267 268 case PRIO_DARWIN_ROLE: 269 if (uap->who == 0) { 270 p = curp; 271 } else { 272 p = proc_find(uap->who); 273 if (p == PROC_NULL) 274 break; 275 refheld = 1; 276 } 277 278 error = proc_get_darwin_role(curp, p, &low); 279 280 if (refheld) 281 proc_rele(p); 282 if (error) 283 return (error); 284 break; 285 286 default: 287 return (EINVAL); 288 } 289 if (low == PRIO_MAX + 1) 290 return (ESRCH); 291 *retval = low; 292 return (0); 293} 294 295/* call back function used for proc iteration in PRIO_USER */ 296static int 297puser_donice_callback(proc_t p, void * arg) 298{ 299 int error, n; 300 struct puser_nice_args * pun = (struct puser_nice_args *)arg; 301 kauth_cred_t my_cred; 302 303 my_cred = kauth_cred_proc_ref(p); 304 if (kauth_cred_getuid(my_cred) == pun->who) { 305 error = donice(pun->curp, p, pun->prio); 306 if (pun->errorp != NULL) 307 *pun->errorp = error; 308 if (pun->foundp != NULL) { 309 n = *pun->foundp; 310 *pun->foundp = n+1; 311 } 312 } 313 kauth_cred_unref(&my_cred); 314 315 return(PROC_RETURNED); 316} 317 318/* call back function used for proc iteration in PRIO_PGRP */ 319static int 320ppgrp_donice_callback(proc_t p, void * arg) 321{ 322 int error; 323 struct ppgrp_nice_args * pun = (struct ppgrp_nice_args *)arg; 324 int n; 325 326 error = donice(pun->curp, p, pun->prio); 327 if (pun->errorp != NULL) 328 *pun->errorp = error; 329 if (pun->foundp!= NULL) { 330 n = *pun->foundp; 331 *pun->foundp = n+1; 332 } 333 334 return(PROC_RETURNED); 335} 336 337/* 338 * Returns: 0 Success 339 * EINVAL 340 * ESRCH 341 * donice:EPERM 342 * donice:EACCES 343 */ 344/* ARGSUSED */ 345int 346setpriority(struct proc *curp, struct setpriority_args *uap, int32_t *retval) 347{ 348 struct proc *p; 349 int found = 0, error = 0; 350 int refheld = 0; 351 352 AUDIT_ARG(cmd, uap->which); 353 AUDIT_ARG(owner, uap->who, 0); 354 AUDIT_ARG(value32, uap->prio); 355 356 /* would also test (uap->who < 0), but id_t is unsigned */ 357 if (uap->who > 0x7fffffff) 358 return (EINVAL); 359 360 switch (uap->which) { 361 362 case PRIO_PROCESS: 363 if (uap->who == 0) 364 p = curp; 365 else { 366 p = proc_find(uap->who); 367 if (p == 0) 368 break; 369 refheld = 1; 370 } 371 error = donice(curp, p, uap->prio); 372 found++; 373 if (refheld != 0) 374 proc_rele(p); 375 break; 376 377 case PRIO_PGRP: { 378 struct pgrp *pg = PGRP_NULL; 379 struct ppgrp_nice_args ppgrp; 380 381 if (uap->who == 0) { 382 pg = proc_pgrp(curp); 383 } else if ((pg = pgfind(uap->who)) == PGRP_NULL) 384 break; 385 386 ppgrp.curp = curp; 387 ppgrp.prio = uap->prio; 388 ppgrp.foundp = &found; 389 ppgrp.errorp = &error; 390 391 /* PGRP_DROPREF drops the reference on process group */ 392 pgrp_iterate(pg, PGRP_DROPREF, ppgrp_donice_callback, (void *)&ppgrp, NULL, NULL); 393 394 break; 395 } 396 397 case PRIO_USER: { 398 struct puser_nice_args punice; 399 400 if (uap->who == 0) 401 uap->who = kauth_cred_getuid(kauth_cred_get()); 402 403 punice.curp = curp; 404 punice.prio = uap->prio; 405 punice.who = uap->who; 406 punice.foundp = &found; 407 error = 0; 408 punice.errorp = &error; 409 proc_iterate(PROC_ALLPROCLIST, puser_donice_callback, (void *)&punice, NULL, NULL); 410 411 break; 412 } 413 414 case PRIO_DARWIN_THREAD: { 415 /* we currently only support the current thread */ 416 if (uap->who != 0) 417 return (EINVAL); 418 419 error = do_background_thread(curp, current_thread(), uap->prio); 420 found++; 421 break; 422 } 423 424 case PRIO_DARWIN_PROCESS: { 425 if (uap->who == 0) 426 p = curp; 427 else { 428 p = proc_find(uap->who); 429 if (p == 0) 430 break; 431 refheld = 1; 432 } 433 434 error = do_background_proc(curp, p, uap->prio); 435 436 found++; 437 if (refheld != 0) 438 proc_rele(p); 439 break; 440 } 441 442 case PRIO_DARWIN_GPU: { 443 if (uap->who == 0) 444 return (EINVAL); 445 446 p = proc_find(uap->who); 447 if (p == PROC_NULL) 448 break; 449 450 error = set_gpudeny_proc(curp, p, uap->prio); 451 452 found++; 453 proc_rele(p); 454 break; 455 } 456 457 case PRIO_DARWIN_ROLE: { 458 if (uap->who == 0) { 459 p = curp; 460 } else { 461 p = proc_find(uap->who); 462 if (p == PROC_NULL) 463 break; 464 refheld = 1; 465 } 466 467 error = proc_set_darwin_role(curp, p, uap->prio); 468 469 found++; 470 if (refheld != 0) 471 proc_rele(p); 472 break; 473 } 474 475 default: 476 return (EINVAL); 477 } 478 if (found == 0) 479 return (ESRCH); 480 if (error == EIDRM) { 481 *retval = -2; 482 error = 0; 483 } 484 return (error); 485} 486 487 488/* 489 * Returns: 0 Success 490 * EPERM 491 * EACCES 492 * mac_check_proc_sched:??? 493 */ 494int 495donice(struct proc *curp, struct proc *chgp, int n) 496{ 497 int error = 0; 498 kauth_cred_t ucred; 499 kauth_cred_t my_cred; 500 501 ucred = kauth_cred_proc_ref(curp); 502 my_cred = kauth_cred_proc_ref(chgp); 503 504 if (suser(ucred, NULL) && kauth_cred_getruid(ucred) && 505 kauth_cred_getuid(ucred) != kauth_cred_getuid(my_cred) && 506 kauth_cred_getruid(ucred) != kauth_cred_getuid(my_cred)) { 507 error = EPERM; 508 goto out; 509 } 510 if (n > PRIO_MAX) 511 n = PRIO_MAX; 512 if (n < PRIO_MIN) 513 n = PRIO_MIN; 514 if (n < chgp->p_nice && suser(ucred, &curp->p_acflag)) { 515 error = EACCES; 516 goto out; 517 } 518#if CONFIG_MACF 519 error = mac_proc_check_sched(curp, chgp); 520 if (error) 521 goto out; 522#endif 523 proc_lock(chgp); 524 chgp->p_nice = n; 525 proc_unlock(chgp); 526 (void)resetpriority(chgp); 527out: 528 kauth_cred_unref(&ucred); 529 kauth_cred_unref(&my_cred); 530 return (error); 531} 532 533static int 534set_gpudeny_proc(struct proc *curp, struct proc *targetp, int priority) 535{ 536 int error = 0; 537 kauth_cred_t ucred; 538 kauth_cred_t target_cred; 539 540 ucred = kauth_cred_get(); 541 target_cred = kauth_cred_proc_ref(targetp); 542 543 /* TODO: Entitlement instead of uid check */ 544 545 if (!kauth_cred_issuser(ucred) && kauth_cred_getruid(ucred) && 546 kauth_cred_getuid(ucred) != kauth_cred_getuid(target_cred) && 547 kauth_cred_getruid(ucred) != kauth_cred_getuid(target_cred)) { 548 error = EPERM; 549 goto out; 550 } 551 552 if (curp == targetp) { 553 error = EPERM; 554 goto out; 555 } 556 557#if CONFIG_MACF 558 error = mac_proc_check_sched(curp, targetp); 559 if (error) 560 goto out; 561#endif 562 563 switch (priority) { 564 case PRIO_DARWIN_GPU_DENY: 565 task_set_gpu_denied(proc_task(targetp), TRUE); 566 break; 567 case PRIO_DARWIN_GPU_ALLOW: 568 task_set_gpu_denied(proc_task(targetp), FALSE); 569 break; 570 default: 571 error = EINVAL; 572 goto out; 573 } 574 575out: 576 kauth_cred_unref(&target_cred); 577 return (error); 578 579} 580 581static int 582proc_set_darwin_role(proc_t curp, proc_t targetp, int priority) 583{ 584 int error = 0; 585 uint32_t flagsp; 586 587 kauth_cred_t ucred, target_cred; 588 589 ucred = kauth_cred_get(); 590 target_cred = kauth_cred_proc_ref(targetp); 591 592 if (!kauth_cred_issuser(ucred) && kauth_cred_getruid(ucred) && 593 kauth_cred_getuid(ucred) != kauth_cred_getuid(target_cred) && 594 kauth_cred_getruid(ucred) != kauth_cred_getuid(target_cred)) { 595 error = EPERM; 596 goto out; 597 } 598 599 if (curp != targetp) { 600#if CONFIG_MACF 601 if ((error = mac_proc_check_sched(curp, targetp))) 602 goto out; 603#endif 604 } 605 606 proc_get_darwinbgstate(proc_task(targetp), &flagsp); 607 if ((flagsp & PROC_FLAG_APPLICATION) != PROC_FLAG_APPLICATION) { 608 error = ENOTSUP; 609 goto out; 610 } 611 612 integer_t role = 0; 613 614 switch (priority) { 615 case PRIO_DARWIN_ROLE_DEFAULT: 616 role = TASK_UNSPECIFIED; 617 break; 618 case PRIO_DARWIN_ROLE_UI_FOCAL: 619 role = TASK_FOREGROUND_APPLICATION; 620 break; 621 case PRIO_DARWIN_ROLE_UI: 622 role = TASK_BACKGROUND_APPLICATION; 623 break; 624 case PRIO_DARWIN_ROLE_NON_UI: 625 role = TASK_NONUI_APPLICATION; 626 break; 627 default: 628 error = EINVAL; 629 goto out; 630 } 631 632 proc_set_task_policy(proc_task(targetp), THREAD_NULL, 633 TASK_POLICY_ATTRIBUTE, TASK_POLICY_ROLE, role); 634 635out: 636 kauth_cred_unref(&target_cred); 637 return (error); 638} 639 640static int 641proc_get_darwin_role(proc_t curp, proc_t targetp, int *priority) 642{ 643 int error = 0; 644 int role = 0; 645 646 kauth_cred_t ucred, target_cred; 647 648 ucred = kauth_cred_get(); 649 target_cred = kauth_cred_proc_ref(targetp); 650 651 if (!kauth_cred_issuser(ucred) && kauth_cred_getruid(ucred) && 652 kauth_cred_getuid(ucred) != kauth_cred_getuid(target_cred) && 653 kauth_cred_getruid(ucred) != kauth_cred_getuid(target_cred)) { 654 error = EPERM; 655 goto out; 656 } 657 658 if (curp != targetp) { 659#if CONFIG_MACF 660 if ((error = mac_proc_check_sched(curp, targetp))) 661 goto out; 662#endif 663 } 664 665 role = proc_get_task_policy(proc_task(targetp), THREAD_NULL, 666 TASK_POLICY_ATTRIBUTE, TASK_POLICY_ROLE); 667 668 switch (role) { 669 case TASK_FOREGROUND_APPLICATION: 670 *priority = PRIO_DARWIN_ROLE_UI_FOCAL; 671 break; 672 case TASK_BACKGROUND_APPLICATION: 673 *priority = PRIO_DARWIN_ROLE_UI; 674 break; 675 case TASK_NONUI_APPLICATION: 676 *priority = PRIO_DARWIN_ROLE_NON_UI; 677 break; 678 case TASK_UNSPECIFIED: 679 default: 680 *priority = PRIO_DARWIN_ROLE_DEFAULT; 681 break; 682 } 683 684out: 685 kauth_cred_unref(&target_cred); 686 return (error); 687} 688 689 690static int 691get_background_proc(struct proc *curp, struct proc *targetp, int *priority) 692{ 693 int external = 0; 694 int error = 0; 695 kauth_cred_t ucred, target_cred; 696 697 ucred = kauth_cred_get(); 698 target_cred = kauth_cred_proc_ref(targetp); 699 700 if (!kauth_cred_issuser(ucred) && kauth_cred_getruid(ucred) && 701 kauth_cred_getuid(ucred) != kauth_cred_getuid(target_cred) && 702 kauth_cred_getruid(ucred) != kauth_cred_getuid(target_cred)) { 703 error = EPERM; 704 goto out; 705 } 706 707 external = (curp == targetp) ? TASK_POLICY_INTERNAL : TASK_POLICY_EXTERNAL; 708 709 *priority = proc_get_task_policy(current_task(), THREAD_NULL, external, TASK_POLICY_DARWIN_BG); 710 711out: 712 kauth_cred_unref(&target_cred); 713 return (error); 714} 715 716static int 717do_background_proc(struct proc *curp, struct proc *targetp, int priority) 718{ 719#if !CONFIG_MACF 720#pragma unused(curp) 721#endif 722 int error = 0; 723 kauth_cred_t ucred; 724 kauth_cred_t target_cred; 725 int external; 726 int enable; 727 728 ucred = kauth_cred_get(); 729 target_cred = kauth_cred_proc_ref(targetp); 730 731 if (!kauth_cred_issuser(ucred) && kauth_cred_getruid(ucred) && 732 kauth_cred_getuid(ucred) != kauth_cred_getuid(target_cred) && 733 kauth_cred_getruid(ucred) != kauth_cred_getuid(target_cred)) 734 { 735 error = EPERM; 736 goto out; 737 } 738 739#if CONFIG_MACF 740 error = mac_proc_check_sched(curp, targetp); 741 if (error) 742 goto out; 743#endif 744 745 external = (curp == targetp) ? TASK_POLICY_INTERNAL : TASK_POLICY_EXTERNAL; 746 747 switch (priority) { 748 case PRIO_DARWIN_BG: 749 enable = TASK_POLICY_ENABLE; 750 break; 751 case PRIO_DARWIN_NONUI: 752 /* ignored for compatibility */ 753 goto out; 754 default: 755 /* TODO: EINVAL if priority != 0 */ 756 enable = TASK_POLICY_DISABLE; 757 break; 758 } 759 760 proc_set_task_policy(proc_task(targetp), THREAD_NULL, external, TASK_POLICY_DARWIN_BG, enable); 761 762out: 763 kauth_cred_unref(&target_cred); 764 return (error); 765} 766 767static void 768do_background_socket(struct proc *p, thread_t thread) 769{ 770#if SOCKETS 771 struct filedesc *fdp; 772 struct fileproc *fp; 773 int i, background; 774 775 proc_fdlock(p); 776 777 if (thread != THREAD_NULL) 778 background = proc_get_effective_thread_policy(thread, TASK_POLICY_ALL_SOCKETS_BG); 779 else 780 background = proc_get_effective_task_policy(proc_task(p), TASK_POLICY_ALL_SOCKETS_BG); 781 782 if (background) { 783 /* 784 * For PRIO_DARWIN_PROCESS (thread is NULL), simply mark 785 * the sockets with the background flag. There's nothing 786 * to do here for the PRIO_DARWIN_THREAD case. 787 */ 788 if (thread == THREAD_NULL) { 789 fdp = p->p_fd; 790 791 for (i = 0; i < fdp->fd_nfiles; i++) { 792 struct socket *sockp; 793 794 fp = fdp->fd_ofiles[i]; 795 if (fp == NULL || (fdp->fd_ofileflags[i] & UF_RESERVED) != 0 || 796 FILEGLOB_DTYPE(fp->f_fglob) != DTYPE_SOCKET) { 797 continue; 798 } 799 sockp = (struct socket *)fp->f_fglob->fg_data; 800 socket_set_traffic_mgt_flags(sockp, TRAFFIC_MGT_SO_BACKGROUND); 801 sockp->so_background_thread = NULL; 802 } 803 } 804 } else { 805 /* disable networking IO throttle. 806 * NOTE - It is a known limitation of the current design that we 807 * could potentially clear TRAFFIC_MGT_SO_BACKGROUND bit for 808 * sockets created by other threads within this process. 809 */ 810 fdp = p->p_fd; 811 for ( i = 0; i < fdp->fd_nfiles; i++ ) { 812 struct socket *sockp; 813 814 fp = fdp->fd_ofiles[ i ]; 815 if ( fp == NULL || (fdp->fd_ofileflags[ i ] & UF_RESERVED) != 0 || 816 FILEGLOB_DTYPE(fp->f_fglob) != DTYPE_SOCKET ) { 817 continue; 818 } 819 sockp = (struct socket *)fp->f_fglob->fg_data; 820 /* skip if only clearing this thread's sockets */ 821 if ((thread) && (sockp->so_background_thread != thread)) { 822 continue; 823 } 824 socket_clear_traffic_mgt_flags(sockp, TRAFFIC_MGT_SO_BACKGROUND); 825 sockp->so_background_thread = NULL; 826 } 827 } 828 829 proc_fdunlock(p); 830#else 831#pragma unused(p, thread) 832#endif 833} 834 835 836/* 837 * do_background_thread 838 * Returns: 0 Success 839 * EPERM Tried to background while in vfork 840 * XXX - todo - does this need a MACF hook? 841 */ 842static int 843do_background_thread(struct proc *curp, thread_t thread, int priority) 844{ 845 struct uthread *ut; 846 int enable, external; 847 int rv = 0; 848 849 ut = get_bsdthread_info(thread); 850 851 /* Backgrounding is unsupported for threads in vfork */ 852 if ((ut->uu_flag & UT_VFORK) != 0) 853 return(EPERM); 854 855 if (thread_is_static_param(thread)) { 856 return(EPERM); 857 } 858 859 /* Not allowed to combine QoS and DARWIN_BG, doing so strips the QoS */ 860 if (thread_has_qos_policy(thread)) { 861 thread_remove_qos_policy(thread); 862 rv = EIDRM; 863 } 864 865 /* TODO: Fail if someone passes something besides 0 or PRIO_DARWIN_BG */ 866 enable = (priority == PRIO_DARWIN_BG) ? TASK_POLICY_ENABLE : TASK_POLICY_DISABLE; 867 external = (current_thread() == thread) ? TASK_POLICY_INTERNAL : TASK_POLICY_EXTERNAL; 868 869 proc_set_task_policy_thread(curp->task, thread_tid(thread), external, 870 TASK_POLICY_DARWIN_BG, enable); 871 872 return rv; 873} 874 875 876/* 877 * Returns: 0 Success 878 * copyin:EFAULT 879 * dosetrlimit: 880 */ 881/* ARGSUSED */ 882int 883setrlimit(struct proc *p, struct setrlimit_args *uap, __unused int32_t *retval) 884{ 885 struct rlimit alim; 886 int error; 887 888 if ((error = copyin(uap->rlp, (caddr_t)&alim, 889 sizeof (struct rlimit)))) 890 return (error); 891 892 return (dosetrlimit(p, uap->which, &alim)); 893} 894 895/* 896 * Returns: 0 Success 897 * EINVAL 898 * ENOMEM Cannot copy limit structure 899 * suser:EPERM 900 * 901 * Notes: EINVAL is returned both for invalid arguments, and in the 902 * case that the current usage (e.g. RLIMIT_STACK) is already 903 * in excess of the requested limit. 904 */ 905int 906dosetrlimit(struct proc *p, u_int which, struct rlimit *limp) 907{ 908 struct rlimit *alimp; 909 int error; 910 kern_return_t kr; 911 int posix = (which & _RLIMIT_POSIX_FLAG) ? 1 : 0; 912 913 /* Mask out POSIX flag, saved above */ 914 which &= ~_RLIMIT_POSIX_FLAG; 915 916 if (which >= RLIM_NLIMITS) 917 return (EINVAL); 918 919 alimp = &p->p_rlimit[which]; 920 if (limp->rlim_cur > limp->rlim_max) 921 return EINVAL; 922 923 if (limp->rlim_cur > alimp->rlim_max || 924 limp->rlim_max > alimp->rlim_max) 925 if ((error = suser(kauth_cred_get(), &p->p_acflag))) { 926 return (error); 927 } 928 929 proc_limitblock(p); 930 931 if ((error = proc_limitreplace(p)) != 0) { 932 proc_limitunblock(p); 933 return(error); 934 } 935 936 alimp = &p->p_rlimit[which]; 937 938 switch (which) { 939 940 case RLIMIT_CPU: 941 if (limp->rlim_cur == RLIM_INFINITY) { 942 task_vtimer_clear(p->task, TASK_VTIMER_RLIM); 943 timerclear(&p->p_rlim_cpu); 944 } 945 else { 946 task_absolutetime_info_data_t tinfo; 947 mach_msg_type_number_t count; 948 struct timeval ttv, tv; 949 clock_sec_t tv_sec; 950 clock_usec_t tv_usec; 951 952 count = TASK_ABSOLUTETIME_INFO_COUNT; 953 task_info(p->task, TASK_ABSOLUTETIME_INFO, 954 (task_info_t)&tinfo, &count); 955 absolutetime_to_microtime(tinfo.total_user + tinfo.total_system, 956 &tv_sec, &tv_usec); 957 ttv.tv_sec = tv_sec; 958 ttv.tv_usec = tv_usec; 959 960 tv.tv_sec = (limp->rlim_cur > __INT_MAX__ ? __INT_MAX__ : limp->rlim_cur); 961 tv.tv_usec = 0; 962 timersub(&tv, &ttv, &p->p_rlim_cpu); 963 964 timerclear(&tv); 965 if (timercmp(&p->p_rlim_cpu, &tv, >)) 966 task_vtimer_set(p->task, TASK_VTIMER_RLIM); 967 else { 968 task_vtimer_clear(p->task, TASK_VTIMER_RLIM); 969 970 timerclear(&p->p_rlim_cpu); 971 972 psignal(p, SIGXCPU); 973 } 974 } 975 break; 976 977 case RLIMIT_DATA: 978 if (limp->rlim_cur > maxdmap) 979 limp->rlim_cur = maxdmap; 980 if (limp->rlim_max > maxdmap) 981 limp->rlim_max = maxdmap; 982 break; 983 984 case RLIMIT_STACK: 985 /* Disallow illegal stack size instead of clipping */ 986 if (limp->rlim_cur > maxsmap || 987 limp->rlim_max > maxsmap) { 988 if (posix) { 989 error = EINVAL; 990 goto out; 991 } 992 else { 993 /* 994 * 4797860 - workaround poorly written installers by 995 * doing previous implementation (< 10.5) when caller 996 * is non-POSIX conforming. 997 */ 998 if (limp->rlim_cur > maxsmap) 999 limp->rlim_cur = maxsmap; 1000 if (limp->rlim_max > maxsmap) 1001 limp->rlim_max = maxsmap; 1002 } 1003 } 1004 1005 /* 1006 * Stack is allocated to the max at exec time with only 1007 * "rlim_cur" bytes accessible. If stack limit is going 1008 * up make more accessible, if going down make inaccessible. 1009 */ 1010 if (limp->rlim_cur > alimp->rlim_cur) { 1011 user_addr_t addr; 1012 user_size_t size; 1013 1014 /* grow stack */ 1015 size = round_page_64(limp->rlim_cur); 1016 size -= round_page_64(alimp->rlim_cur); 1017 1018 addr = p->user_stack - round_page_64(limp->rlim_cur); 1019 kr = mach_vm_protect(current_map(), 1020 addr, size, 1021 FALSE, VM_PROT_DEFAULT); 1022 if (kr != KERN_SUCCESS) { 1023 error = EINVAL; 1024 goto out; 1025 } 1026 } else if (limp->rlim_cur < alimp->rlim_cur) { 1027 user_addr_t addr; 1028 user_size_t size; 1029 user_addr_t cur_sp; 1030 1031 /* shrink stack */ 1032 1033 /* 1034 * First check if new stack limit would agree 1035 * with current stack usage. 1036 * Get the current thread's stack pointer... 1037 */ 1038 cur_sp = thread_adjuserstack(current_thread(), 1039 0); 1040 if (cur_sp <= p->user_stack && 1041 cur_sp > (p->user_stack - 1042 round_page_64(alimp->rlim_cur))) { 1043 /* stack pointer is in main stack */ 1044 if (cur_sp <= (p->user_stack - 1045 round_page_64(limp->rlim_cur))) { 1046 /* 1047 * New limit would cause 1048 * current usage to be invalid: 1049 * reject new limit. 1050 */ 1051 error = EINVAL; 1052 goto out; 1053 } 1054 } else { 1055 /* not on the main stack: reject */ 1056 error = EINVAL; 1057 goto out; 1058 } 1059 1060 size = round_page_64(alimp->rlim_cur); 1061 size -= round_page_64(limp->rlim_cur); 1062 1063 addr = p->user_stack - round_page_64(alimp->rlim_cur); 1064 1065 kr = mach_vm_protect(current_map(), 1066 addr, size, 1067 FALSE, VM_PROT_NONE); 1068 if (kr != KERN_SUCCESS) { 1069 error = EINVAL; 1070 goto out; 1071 } 1072 } else { 1073 /* no change ... */ 1074 } 1075 break; 1076 1077 case RLIMIT_NOFILE: 1078 /* 1079 * Only root can set the maxfiles limits, as it is 1080 * systemwide resource. If we are expecting POSIX behavior, 1081 * instead of clamping the value, return EINVAL. We do this 1082 * because historically, people have been able to attempt to 1083 * set RLIM_INFINITY to get "whatever the maximum is". 1084 */ 1085 if ( kauth_cred_issuser(kauth_cred_get()) ) { 1086 if (limp->rlim_cur != alimp->rlim_cur && 1087 limp->rlim_cur > (rlim_t)maxfiles) { 1088 if (posix) { 1089 error = EINVAL; 1090 goto out; 1091 } 1092 limp->rlim_cur = maxfiles; 1093 } 1094 if (limp->rlim_max != alimp->rlim_max && 1095 limp->rlim_max > (rlim_t)maxfiles) 1096 limp->rlim_max = maxfiles; 1097 } 1098 else { 1099 if (limp->rlim_cur != alimp->rlim_cur && 1100 limp->rlim_cur > (rlim_t)maxfilesperproc) { 1101 if (posix) { 1102 error = EINVAL; 1103 goto out; 1104 } 1105 limp->rlim_cur = maxfilesperproc; 1106 } 1107 if (limp->rlim_max != alimp->rlim_max && 1108 limp->rlim_max > (rlim_t)maxfilesperproc) 1109 limp->rlim_max = maxfilesperproc; 1110 } 1111 break; 1112 1113 case RLIMIT_NPROC: 1114 /* 1115 * Only root can set to the maxproc limits, as it is 1116 * systemwide resource; all others are limited to 1117 * maxprocperuid (presumably less than maxproc). 1118 */ 1119 if ( kauth_cred_issuser(kauth_cred_get()) ) { 1120 if (limp->rlim_cur > (rlim_t)maxproc) 1121 limp->rlim_cur = maxproc; 1122 if (limp->rlim_max > (rlim_t)maxproc) 1123 limp->rlim_max = maxproc; 1124 } 1125 else { 1126 if (limp->rlim_cur > (rlim_t)maxprocperuid) 1127 limp->rlim_cur = maxprocperuid; 1128 if (limp->rlim_max > (rlim_t)maxprocperuid) 1129 limp->rlim_max = maxprocperuid; 1130 } 1131 break; 1132 1133 case RLIMIT_MEMLOCK: 1134 /* 1135 * Tell the Mach VM layer about the new limit value. 1136 */ 1137 1138 vm_map_set_user_wire_limit(current_map(), limp->rlim_cur); 1139 break; 1140 1141 } /* switch... */ 1142 proc_lock(p); 1143 *alimp = *limp; 1144 proc_unlock(p); 1145 error = 0; 1146out: 1147 proc_limitunblock(p); 1148 return (error); 1149} 1150 1151/* ARGSUSED */ 1152int 1153getrlimit(struct proc *p, struct getrlimit_args *uap, __unused int32_t *retval) 1154{ 1155 struct rlimit lim; 1156 1157 /* 1158 * Take out flag now in case we need to use it to trigger variant 1159 * behaviour later. 1160 */ 1161 uap->which &= ~_RLIMIT_POSIX_FLAG; 1162 1163 if (uap->which >= RLIM_NLIMITS) 1164 return (EINVAL); 1165 proc_limitget(p, uap->which, &lim); 1166 return (copyout((caddr_t)&lim, 1167 uap->rlp, sizeof (struct rlimit))); 1168} 1169 1170/* 1171 * Transform the running time and tick information in proc p into user, 1172 * system, and interrupt time usage. 1173 */ 1174/* No lock on proc is held for this.. */ 1175void 1176calcru(struct proc *p, struct timeval *up, struct timeval *sp, struct timeval *ip) 1177{ 1178 task_t task; 1179 1180 timerclear(up); 1181 timerclear(sp); 1182 if (ip != NULL) 1183 timerclear(ip); 1184 1185 task = p->task; 1186 if (task) { 1187 mach_task_basic_info_data_t tinfo; 1188 task_thread_times_info_data_t ttimesinfo; 1189 task_events_info_data_t teventsinfo; 1190 mach_msg_type_number_t task_info_count, task_ttimes_count; 1191 mach_msg_type_number_t task_events_count; 1192 struct timeval ut,st; 1193 1194 task_info_count = MACH_TASK_BASIC_INFO_COUNT; 1195 task_info(task, MACH_TASK_BASIC_INFO, 1196 (task_info_t)&tinfo, &task_info_count); 1197 ut.tv_sec = tinfo.user_time.seconds; 1198 ut.tv_usec = tinfo.user_time.microseconds; 1199 st.tv_sec = tinfo.system_time.seconds; 1200 st.tv_usec = tinfo.system_time.microseconds; 1201 timeradd(&ut, up, up); 1202 timeradd(&st, sp, sp); 1203 1204 task_ttimes_count = TASK_THREAD_TIMES_INFO_COUNT; 1205 task_info(task, TASK_THREAD_TIMES_INFO, 1206 (task_info_t)&ttimesinfo, &task_ttimes_count); 1207 1208 ut.tv_sec = ttimesinfo.user_time.seconds; 1209 ut.tv_usec = ttimesinfo.user_time.microseconds; 1210 st.tv_sec = ttimesinfo.system_time.seconds; 1211 st.tv_usec = ttimesinfo.system_time.microseconds; 1212 timeradd(&ut, up, up); 1213 timeradd(&st, sp, sp); 1214 1215 task_events_count = TASK_EVENTS_INFO_COUNT; 1216 task_info(task, TASK_EVENTS_INFO, 1217 (task_info_t)&teventsinfo, &task_events_count); 1218 1219 /* 1220 * No need to lock "p": this does not need to be 1221 * completely consistent, right ? 1222 */ 1223 p->p_stats->p_ru.ru_minflt = (teventsinfo.faults - 1224 teventsinfo.pageins); 1225 p->p_stats->p_ru.ru_majflt = teventsinfo.pageins; 1226 p->p_stats->p_ru.ru_nivcsw = (teventsinfo.csw - 1227 p->p_stats->p_ru.ru_nvcsw); 1228 if (p->p_stats->p_ru.ru_nivcsw < 0) 1229 p->p_stats->p_ru.ru_nivcsw = 0; 1230 1231 p->p_stats->p_ru.ru_maxrss = tinfo.resident_size_max; 1232 } 1233} 1234 1235__private_extern__ void munge_user64_rusage(struct rusage *a_rusage_p, struct user64_rusage *a_user_rusage_p); 1236__private_extern__ void munge_user32_rusage(struct rusage *a_rusage_p, struct user32_rusage *a_user_rusage_p); 1237 1238/* ARGSUSED */ 1239int 1240getrusage(struct proc *p, struct getrusage_args *uap, __unused int32_t *retval) 1241{ 1242 struct rusage *rup, rubuf; 1243 struct user64_rusage rubuf64; 1244 struct user32_rusage rubuf32; 1245 size_t retsize = sizeof(rubuf); /* default: 32 bits */ 1246 caddr_t retbuf = (caddr_t)&rubuf; /* default: 32 bits */ 1247 struct timeval utime; 1248 struct timeval stime; 1249 1250 1251 switch (uap->who) { 1252 case RUSAGE_SELF: 1253 calcru(p, &utime, &stime, NULL); 1254 proc_lock(p); 1255 rup = &p->p_stats->p_ru; 1256 rup->ru_utime = utime; 1257 rup->ru_stime = stime; 1258 1259 rubuf = *rup; 1260 proc_unlock(p); 1261 1262 break; 1263 1264 case RUSAGE_CHILDREN: 1265 proc_lock(p); 1266 rup = &p->p_stats->p_cru; 1267 rubuf = *rup; 1268 proc_unlock(p); 1269 break; 1270 1271 default: 1272 return (EINVAL); 1273 } 1274 if (IS_64BIT_PROCESS(p)) { 1275 retsize = sizeof(rubuf64); 1276 retbuf = (caddr_t)&rubuf64; 1277 munge_user64_rusage(&rubuf, &rubuf64); 1278 } else { 1279 retsize = sizeof(rubuf32); 1280 retbuf = (caddr_t)&rubuf32; 1281 munge_user32_rusage(&rubuf, &rubuf32); 1282 } 1283 1284 return (copyout(retbuf, uap->rusage, retsize)); 1285} 1286 1287void 1288ruadd(struct rusage *ru, struct rusage *ru2) 1289{ 1290 long *ip, *ip2; 1291 long i; 1292 1293 timeradd(&ru->ru_utime, &ru2->ru_utime, &ru->ru_utime); 1294 timeradd(&ru->ru_stime, &ru2->ru_stime, &ru->ru_stime); 1295 if (ru->ru_maxrss < ru2->ru_maxrss) 1296 ru->ru_maxrss = ru2->ru_maxrss; 1297 ip = &ru->ru_first; ip2 = &ru2->ru_first; 1298 for (i = &ru->ru_last - &ru->ru_first; i >= 0; i--) 1299 *ip++ += *ip2++; 1300} 1301 1302/* 1303 * Add the rusage stats of child in parent. 1304 * 1305 * It adds rusage statistics of child process and statistics of all its 1306 * children to its parent. 1307 * 1308 * Note: proc lock of parent should be held while calling this function. 1309 */ 1310void 1311update_rusage_info_child(struct rusage_info_child *ri, rusage_info_current *ri_current) 1312{ 1313 ri->ri_child_user_time += (ri_current->ri_user_time + 1314 ri_current->ri_child_user_time); 1315 ri->ri_child_system_time += (ri_current->ri_system_time + 1316 ri_current->ri_child_system_time); 1317 ri->ri_child_pkg_idle_wkups += (ri_current->ri_pkg_idle_wkups + 1318 ri_current->ri_child_pkg_idle_wkups); 1319 ri->ri_child_interrupt_wkups += (ri_current->ri_interrupt_wkups + 1320 ri_current->ri_child_interrupt_wkups); 1321 ri->ri_child_pageins += (ri_current->ri_pageins + 1322 ri_current->ri_child_pageins); 1323 ri->ri_child_elapsed_abstime += ((ri_current->ri_proc_exit_abstime - 1324 ri_current->ri_proc_start_abstime) + ri_current->ri_child_elapsed_abstime); 1325} 1326 1327void 1328proc_limitget(proc_t p, int which, struct rlimit * limp) 1329{ 1330 proc_list_lock(); 1331 limp->rlim_cur = p->p_rlimit[which].rlim_cur; 1332 limp->rlim_max = p->p_rlimit[which].rlim_max; 1333 proc_list_unlock(); 1334} 1335 1336 1337void 1338proc_limitdrop(proc_t p, int exiting) 1339{ 1340 struct plimit * freelim = NULL; 1341 struct plimit * freeoldlim = NULL; 1342 1343 proc_list_lock(); 1344 1345 if (--p->p_limit->pl_refcnt == 0) { 1346 freelim = p->p_limit; 1347 p->p_limit = NULL; 1348 } 1349 if ((exiting != 0) && (p->p_olimit != NULL) && (--p->p_olimit->pl_refcnt == 0)) { 1350 freeoldlim = p->p_olimit; 1351 p->p_olimit = NULL; 1352 } 1353 1354 proc_list_unlock(); 1355 if (freelim != NULL) 1356 FREE_ZONE(freelim, sizeof *p->p_limit, M_PLIMIT); 1357 if (freeoldlim != NULL) 1358 FREE_ZONE(freeoldlim, sizeof *p->p_olimit, M_PLIMIT); 1359} 1360 1361 1362void 1363proc_limitfork(proc_t parent, proc_t child) 1364{ 1365 proc_list_lock(); 1366 child->p_limit = parent->p_limit; 1367 child->p_limit->pl_refcnt++; 1368 child->p_olimit = NULL; 1369 proc_list_unlock(); 1370} 1371 1372void 1373proc_limitblock(proc_t p) 1374{ 1375 proc_lock(p); 1376 while (p->p_lflag & P_LLIMCHANGE) { 1377 p->p_lflag |= P_LLIMWAIT; 1378 msleep(&p->p_olimit, &p->p_mlock, 0, "proc_limitblock", NULL); 1379 } 1380 p->p_lflag |= P_LLIMCHANGE; 1381 proc_unlock(p); 1382 1383} 1384 1385 1386void 1387proc_limitunblock(proc_t p) 1388{ 1389 proc_lock(p); 1390 p->p_lflag &= ~P_LLIMCHANGE; 1391 if (p->p_lflag & P_LLIMWAIT) { 1392 p->p_lflag &= ~P_LLIMWAIT; 1393 wakeup(&p->p_olimit); 1394 } 1395 proc_unlock(p); 1396} 1397 1398/* This is called behind serialization provided by proc_limitblock/unlbock */ 1399int 1400proc_limitreplace(proc_t p) 1401{ 1402 struct plimit *copy; 1403 1404 1405 proc_list_lock(); 1406 1407 if (p->p_limit->pl_refcnt == 1) { 1408 proc_list_unlock(); 1409 return(0); 1410 } 1411 1412 proc_list_unlock(); 1413 1414 MALLOC_ZONE(copy, struct plimit *, 1415 sizeof(struct plimit), M_PLIMIT, M_WAITOK); 1416 if (copy == NULL) { 1417 return(ENOMEM); 1418 } 1419 1420 proc_list_lock(); 1421 bcopy(p->p_limit->pl_rlimit, copy->pl_rlimit, 1422 sizeof(struct rlimit) * RLIM_NLIMITS); 1423 copy->pl_refcnt = 1; 1424 /* hang on to reference to old till process exits */ 1425 p->p_olimit = p->p_limit; 1426 p->p_limit = copy; 1427 proc_list_unlock(); 1428 1429 return(0); 1430} 1431 1432/* 1433 * iopolicysys 1434 * 1435 * Description: System call MUX for use in manipulating I/O policy attributes of the current process or thread 1436 * 1437 * Parameters: cmd Policy command 1438 * arg Pointer to policy arguments 1439 * 1440 * Returns: 0 Success 1441 * EINVAL Invalid command or invalid policy arguments 1442 * 1443 */ 1444 1445static int 1446iopolicysys_disk(struct proc *p, int cmd, int scope, int policy, struct _iopol_param_t *iop_param); 1447static int 1448iopolicysys_vfs(struct proc *p, int cmd, int scope, int policy, struct _iopol_param_t *iop_param); 1449 1450int 1451iopolicysys(struct proc *p, struct iopolicysys_args *uap, int32_t *retval) 1452{ 1453 int error = 0; 1454 struct _iopol_param_t iop_param; 1455 1456 if ((error = copyin(uap->arg, &iop_param, sizeof(iop_param))) != 0) 1457 goto out; 1458 1459 switch (iop_param.iop_iotype) { 1460 case IOPOL_TYPE_DISK: 1461 error = iopolicysys_disk(p, uap->cmd, iop_param.iop_scope, iop_param.iop_policy, &iop_param); 1462 if (error == EIDRM) { 1463 *retval = -2; 1464 error = 0; 1465 } 1466 if (error) 1467 goto out; 1468 break; 1469 case IOPOL_TYPE_VFS_HFS_CASE_SENSITIVITY: 1470 error = iopolicysys_vfs(p, uap->cmd, iop_param.iop_scope, iop_param.iop_policy, &iop_param); 1471 if (error) 1472 goto out; 1473 break; 1474 default: 1475 error = EINVAL; 1476 goto out; 1477 } 1478 1479 /* Individual iotype handlers are expected to update iop_param, if requested with a GET command */ 1480 if (uap->cmd == IOPOL_CMD_GET) { 1481 error = copyout((caddr_t)&iop_param, uap->arg, sizeof(iop_param)); 1482 if (error) 1483 goto out; 1484 } 1485 1486out: 1487 return (error); 1488} 1489 1490static int 1491iopolicysys_disk(struct proc *p __unused, int cmd, int scope, int policy, struct _iopol_param_t *iop_param) 1492{ 1493 int error = 0; 1494 thread_t thread; 1495 int policy_flavor; 1496 1497 /* Validate scope */ 1498 switch (scope) { 1499 case IOPOL_SCOPE_PROCESS: 1500 thread = THREAD_NULL; 1501 policy_flavor = TASK_POLICY_IOPOL; 1502 break; 1503 1504 case IOPOL_SCOPE_THREAD: 1505 thread = current_thread(); 1506 policy_flavor = TASK_POLICY_IOPOL; 1507 1508 /* Not allowed to combine QoS and (non-PASSIVE) IO policy, doing so strips the QoS */ 1509 if (cmd == IOPOL_CMD_SET && thread_has_qos_policy(thread)) { 1510 switch (policy) { 1511 case IOPOL_DEFAULT: 1512 case IOPOL_PASSIVE: 1513 break; 1514 case IOPOL_UTILITY: 1515 case IOPOL_THROTTLE: 1516 case IOPOL_IMPORTANT: 1517 case IOPOL_STANDARD: 1518 if (!thread_is_static_param(thread)) { 1519 thread_remove_qos_policy(thread); 1520 /* 1521 * This is not an error case, this is to return a marker to user-space that 1522 * we stripped the thread of its QoS class. 1523 */ 1524 error = EIDRM; 1525 break; 1526 } 1527 /* otherwise, fall through to the error case. */ 1528 default: 1529 error = EINVAL; 1530 goto out; 1531 } 1532 } 1533 break; 1534 1535 case IOPOL_SCOPE_DARWIN_BG: 1536 thread = THREAD_NULL; 1537 policy_flavor = TASK_POLICY_DARWIN_BG_IOPOL; 1538 break; 1539 1540 default: 1541 error = EINVAL; 1542 goto out; 1543 } 1544 1545 /* Validate policy */ 1546 if (cmd == IOPOL_CMD_SET) { 1547 switch (policy) { 1548 case IOPOL_DEFAULT: 1549 if (scope == IOPOL_SCOPE_DARWIN_BG) { 1550 /* the current default BG throttle level is UTILITY */ 1551 policy = IOPOL_UTILITY; 1552 } else { 1553 policy = IOPOL_IMPORTANT; 1554 } 1555 break; 1556 case IOPOL_UTILITY: 1557 /* fall-through */ 1558 case IOPOL_THROTTLE: 1559 /* These levels are OK */ 1560 break; 1561 case IOPOL_IMPORTANT: 1562 /* fall-through */ 1563 case IOPOL_STANDARD: 1564 /* fall-through */ 1565 case IOPOL_PASSIVE: 1566 if (scope == IOPOL_SCOPE_DARWIN_BG) { 1567 /* These levels are invalid for BG */ 1568 error = EINVAL; 1569 goto out; 1570 } else { 1571 /* OK for other scopes */ 1572 } 1573 break; 1574 default: 1575 error = EINVAL; 1576 goto out; 1577 } 1578 } 1579 1580 /* Perform command */ 1581 switch(cmd) { 1582 case IOPOL_CMD_SET: 1583 proc_set_task_policy(current_task(), thread, 1584 TASK_POLICY_INTERNAL, policy_flavor, 1585 policy); 1586 break; 1587 case IOPOL_CMD_GET: 1588 policy = proc_get_task_policy(current_task(), thread, 1589 TASK_POLICY_INTERNAL, policy_flavor); 1590 1591 iop_param->iop_policy = policy; 1592 break; 1593 default: 1594 error = EINVAL; /* unknown command */ 1595 break; 1596 } 1597 1598out: 1599 return (error); 1600} 1601 1602static int 1603iopolicysys_vfs(struct proc *p, int cmd, int scope, int policy, struct _iopol_param_t *iop_param) 1604{ 1605 int error = 0; 1606 1607 /* Validate scope */ 1608 switch (scope) { 1609 case IOPOL_SCOPE_PROCESS: 1610 /* Only process OK */ 1611 break; 1612 default: 1613 error = EINVAL; 1614 goto out; 1615 } 1616 1617 /* Validate policy */ 1618 if (cmd == IOPOL_CMD_SET) { 1619 switch (policy) { 1620 case IOPOL_VFS_HFS_CASE_SENSITIVITY_DEFAULT: 1621 /* fall-through */ 1622 case IOPOL_VFS_HFS_CASE_SENSITIVITY_FORCE_CASE_SENSITIVE: 1623 /* These policies are OK */ 1624 break; 1625 default: 1626 error = EINVAL; 1627 goto out; 1628 } 1629 } 1630 1631 /* Perform command */ 1632 switch(cmd) { 1633 case IOPOL_CMD_SET: 1634 if (0 == kauth_cred_issuser(kauth_cred_get())) { 1635 error = EPERM; 1636 goto out; 1637 } 1638 1639 switch (policy) { 1640 case IOPOL_VFS_HFS_CASE_SENSITIVITY_DEFAULT: 1641 OSBitAndAtomic16(~((uint32_t)P_VFS_IOPOLICY_FORCE_HFS_CASE_SENSITIVITY), &p->p_vfs_iopolicy); 1642 break; 1643 case IOPOL_VFS_HFS_CASE_SENSITIVITY_FORCE_CASE_SENSITIVE: 1644 OSBitOrAtomic16((uint32_t)P_VFS_IOPOLICY_FORCE_HFS_CASE_SENSITIVITY, &p->p_vfs_iopolicy); 1645 break; 1646 default: 1647 error = EINVAL; 1648 goto out; 1649 } 1650 1651 break; 1652 case IOPOL_CMD_GET: 1653 iop_param->iop_policy = (p->p_vfs_iopolicy & P_VFS_IOPOLICY_FORCE_HFS_CASE_SENSITIVITY) 1654 ? IOPOL_VFS_HFS_CASE_SENSITIVITY_FORCE_CASE_SENSITIVE 1655 : IOPOL_VFS_HFS_CASE_SENSITIVITY_DEFAULT; 1656 break; 1657 default: 1658 error = EINVAL; /* unknown command */ 1659 break; 1660 } 1661 1662out: 1663 return (error); 1664} 1665 1666/* BSD call back function for task_policy */ 1667void proc_apply_task_networkbg(void * bsd_info, thread_t thread); 1668 1669void 1670proc_apply_task_networkbg(void * bsd_info, thread_t thread) 1671{ 1672 assert(bsd_info != PROC_NULL); 1673 1674 pid_t pid = proc_pid((proc_t)bsd_info); 1675 1676 proc_t p = proc_find(pid); 1677 1678 if (p != PROC_NULL) { 1679 assert(p == (proc_t)bsd_info); 1680 1681 do_background_socket(p, thread); 1682 proc_rele(p); 1683 } 1684} 1685 1686void 1687gather_rusage_info(proc_t p, rusage_info_current *ru, int flavor) 1688{ 1689 struct rusage_info_child *ri_child; 1690 1691 assert(p->p_stats != NULL); 1692 switch(flavor) { 1693 1694 case RUSAGE_INFO_V3: 1695 fill_task_qos_rusage(p->task, ru); 1696 fill_task_billed_usage(p->task, ru); 1697 /* fall through */ 1698 1699 case RUSAGE_INFO_V2: 1700 fill_task_io_rusage(p->task, ru); 1701 /* fall through */ 1702 1703 case RUSAGE_INFO_V1: 1704 /* 1705 * p->p_stats->ri_child statistics are protected under proc lock. 1706 */ 1707 proc_lock(p); 1708 1709 ri_child = &(p->p_stats->ri_child); 1710 ru->ri_child_user_time = ri_child->ri_child_user_time; 1711 ru->ri_child_system_time = ri_child->ri_child_system_time; 1712 ru->ri_child_pkg_idle_wkups = ri_child->ri_child_pkg_idle_wkups; 1713 ru->ri_child_interrupt_wkups = ri_child->ri_child_interrupt_wkups; 1714 ru->ri_child_pageins = ri_child->ri_child_pageins; 1715 ru->ri_child_elapsed_abstime = ri_child->ri_child_elapsed_abstime; 1716 1717 proc_unlock(p); 1718 /* fall through */ 1719 1720 case RUSAGE_INFO_V0: 1721 proc_getexecutableuuid(p, (unsigned char *)&ru->ri_uuid, sizeof (ru->ri_uuid)); 1722 fill_task_rusage(p->task, ru); 1723 ru->ri_proc_start_abstime = p->p_stats->ps_start; 1724 } 1725} 1726 1727static void 1728rusage_info_conversion(rusage_info_t ri_info, rusage_info_current *ri_current, int flavor) 1729{ 1730 struct rusage_info_v0 *ri_v0; 1731 struct rusage_info_v1 *ri_v1; 1732 struct rusage_info_v2 *ri_v2; 1733 1734 switch (flavor) { 1735 1736 case RUSAGE_INFO_V2: 1737 ri_v2 = (struct rusage_info_v2 *)ri_info; 1738 ri_v2->ri_diskio_bytesread = ri_current->ri_diskio_bytesread; 1739 ri_v2->ri_diskio_byteswritten = ri_current->ri_diskio_byteswritten; 1740 /* fall through */ 1741 1742 case RUSAGE_INFO_V1: 1743 ri_v1 = (struct rusage_info_v1 *)ri_info; 1744 ri_v1->ri_child_user_time = ri_current->ri_child_user_time; 1745 ri_v1->ri_child_system_time = ri_current->ri_child_system_time; 1746 ri_v1->ri_child_pkg_idle_wkups = ri_current->ri_child_pkg_idle_wkups; 1747 ri_v1->ri_child_interrupt_wkups = ri_current->ri_child_interrupt_wkups; 1748 ri_v1->ri_child_pageins = ri_current->ri_child_pageins; 1749 ri_v1->ri_child_elapsed_abstime = ri_current->ri_child_elapsed_abstime; 1750 /* fall through */ 1751 1752 case RUSAGE_INFO_V0: 1753 ri_v0 = (struct rusage_info_v0 *)ri_info; 1754 memcpy(&ri_v0->ri_uuid[0], &ri_current->ri_uuid[0], sizeof(ri_v0->ri_uuid)); 1755 ri_v0->ri_user_time = ri_current->ri_user_time; 1756 ri_v0->ri_system_time = ri_current->ri_system_time; 1757 ri_v0->ri_pkg_idle_wkups = ri_current->ri_pkg_idle_wkups; 1758 ri_v0->ri_interrupt_wkups = ri_current->ri_interrupt_wkups; 1759 ri_v0->ri_pageins = ri_current->ri_pageins; 1760 ri_v0->ri_wired_size = ri_current->ri_wired_size; 1761 ri_v0->ri_resident_size = ri_current->ri_resident_size; 1762 ri_v0->ri_phys_footprint = ri_current->ri_phys_footprint; 1763 ri_v0->ri_proc_start_abstime = ri_current->ri_proc_start_abstime; 1764 ri_v0->ri_proc_exit_abstime = ri_current->ri_proc_exit_abstime; 1765 1766 break; 1767 1768 default: 1769 break; 1770 } 1771} 1772 1773 1774int 1775proc_get_rusage(proc_t p, int flavor, user_addr_t buffer, __unused int is_zombie) 1776{ 1777 struct rusage_info_v0 ri_v0; 1778 struct rusage_info_v1 ri_v1; 1779 struct rusage_info_v2 ri_v2; 1780 struct rusage_info_v3 ri_v3; 1781 1782 rusage_info_current ri_current; 1783 1784 int error = 0; 1785 1786 switch (flavor) { 1787 case RUSAGE_INFO_V0: 1788 /* 1789 * If task is still alive, collect info from the live task itself. 1790 * Otherwise, look to the cached info in the zombie proc. 1791 */ 1792 if (p->p_ru == NULL) { 1793 gather_rusage_info(p, &ri_current, flavor); 1794 ri_current.ri_proc_exit_abstime = 0; 1795 rusage_info_conversion(&ri_v0, &ri_current, flavor); 1796 } else { 1797 rusage_info_conversion(&ri_v0, &p->p_ru->ri, flavor); 1798 } 1799 error = copyout(&ri_v0, buffer, sizeof (ri_v0)); 1800 break; 1801 1802 case RUSAGE_INFO_V1: 1803 /* 1804 * If task is still alive, collect info from the live task itself. 1805 * Otherwise, look to the cached info in the zombie proc. 1806 */ 1807 if (p->p_ru == NULL) { 1808 gather_rusage_info(p, &ri_current, flavor); 1809 ri_current.ri_proc_exit_abstime = 0; 1810 rusage_info_conversion(&ri_v1, &ri_current, flavor); 1811 } else { 1812 rusage_info_conversion(&ri_v1, &p->p_ru->ri, flavor); 1813 } 1814 error = copyout(&ri_v1, buffer, sizeof (ri_v1)); 1815 break; 1816 1817 case RUSAGE_INFO_V2: 1818 /* 1819 * If task is still alive, collect info from the live task itself. 1820 * Otherwise, look to the cached info in the zombie proc. 1821 */ 1822 if (p->p_ru == NULL) { 1823 gather_rusage_info(p, &ri_current, flavor); 1824 ri_current.ri_proc_exit_abstime = 0; 1825 rusage_info_conversion(&ri_v2, &ri_current, flavor); 1826 } else { 1827 rusage_info_conversion(&ri_v2, &p->p_ru->ri, flavor); 1828 } 1829 error = copyout(&ri_v2, buffer, sizeof (ri_v2)); 1830 break; 1831 1832 case RUSAGE_INFO_V3: 1833 /* 1834 * If task is still alive, collect info from the live task itself. 1835 * Otherwise, look to the cached info in the zombie proc. 1836 */ 1837 if (p->p_ru == NULL) { 1838 gather_rusage_info(p, &ri_v3, flavor); 1839 ri_v3.ri_proc_exit_abstime = 0; 1840 } else { 1841 ri_v3 = p->p_ru->ri; 1842 } 1843 error = copyout(&ri_v3, buffer, sizeof (ri_v3)); 1844 break; 1845 1846 default: 1847 error = EINVAL; 1848 break; 1849 } 1850 1851 return (error); 1852} 1853 1854static int 1855mach_to_bsd_rv(int mach_rv) 1856{ 1857 int bsd_rv = 0; 1858 1859 switch (mach_rv) { 1860 case KERN_SUCCESS: 1861 bsd_rv = 0; 1862 break; 1863 case KERN_INVALID_ARGUMENT: 1864 bsd_rv = EINVAL; 1865 break; 1866 default: 1867 panic("unknown error %#x", mach_rv); 1868 } 1869 1870 return bsd_rv; 1871} 1872 1873/* 1874 * Resource limit controls 1875 * 1876 * uap->flavor available flavors: 1877 * 1878 * RLIMIT_WAKEUPS_MONITOR 1879 */ 1880int 1881proc_rlimit_control(__unused struct proc *p, struct proc_rlimit_control_args *uap, __unused int32_t *retval) 1882{ 1883 proc_t targetp; 1884 int error = 0; 1885 struct proc_rlimit_control_wakeupmon wakeupmon_args; 1886 uint32_t cpumon_flags; 1887 uint32_t cpulimits_flags; 1888 kauth_cred_t my_cred, target_cred; 1889 1890 /* -1 implicitly means our own process (perhaps even the current thread for per-thread attributes) */ 1891 if (uap->pid == -1) { 1892 targetp = proc_self(); 1893 } else { 1894 targetp = proc_find(uap->pid); 1895 } 1896 1897 /* proc_self() can return NULL for an exiting process */ 1898 if (targetp == PROC_NULL) { 1899 return (ESRCH); 1900 } 1901 1902 my_cred = kauth_cred_get(); 1903 target_cred = kauth_cred_proc_ref(targetp); 1904 1905 if (!kauth_cred_issuser(my_cred) && kauth_cred_getruid(my_cred) && 1906 kauth_cred_getuid(my_cred) != kauth_cred_getuid(target_cred) && 1907 kauth_cred_getruid(my_cred) != kauth_cred_getuid(target_cred)) { 1908 proc_rele(targetp); 1909 kauth_cred_unref(&target_cred); 1910 return (EACCES); 1911 } 1912 1913 switch (uap->flavor) { 1914 case RLIMIT_WAKEUPS_MONITOR: 1915 if ((error = copyin(uap->arg, &wakeupmon_args, sizeof (wakeupmon_args))) != 0) { 1916 break; 1917 } 1918 if ((error = mach_to_bsd_rv(task_wakeups_monitor_ctl(targetp->task, &wakeupmon_args.wm_flags, 1919 &wakeupmon_args.wm_rate))) != 0) { 1920 break; 1921 } 1922 error = copyout(&wakeupmon_args, uap->arg, sizeof (wakeupmon_args)); 1923 break; 1924 case RLIMIT_CPU_USAGE_MONITOR: 1925 cpumon_flags = uap->arg; // XXX temporarily stashing flags in argp (12592127) 1926 error = mach_to_bsd_rv(task_cpu_usage_monitor_ctl(targetp->task, &cpumon_flags)); 1927 break; 1928 case RLIMIT_THREAD_CPULIMITS: 1929 cpulimits_flags = (uint32_t)uap->arg; // only need a limited set of bits, pass in void * argument 1930 1931 if (uap->pid != -1) { 1932 error = EINVAL; 1933 break; 1934 } 1935 1936 uint8_t percent = 0; 1937 uint32_t ms_refill = 0; 1938 uint64_t ns_refill; 1939 1940 percent = (uint8_t)(cpulimits_flags & 0xffU); /* low 8 bits for percent */ 1941 ms_refill = (cpulimits_flags >> 8) & 0xffffff; /* next 24 bits represent ms refill value */ 1942 if (percent >= 100) { 1943 error = EINVAL; 1944 break; 1945 } 1946 1947 ns_refill = ((uint64_t)ms_refill) * NSEC_PER_MSEC; 1948 1949 error = mach_to_bsd_rv(thread_set_cpulimit(THREAD_CPULIMIT_BLOCK, percent, ns_refill)); 1950 break; 1951 default: 1952 error = EINVAL; 1953 break; 1954 } 1955 1956 proc_rele(targetp); 1957 kauth_cred_unref(&target_cred); 1958 1959 /* 1960 * Return value from this function becomes errno to userland caller. 1961 */ 1962 return (error); 1963} 1964 1965/* 1966 * Return the current amount of CPU consumed by this thread (in either user or kernel mode) 1967 */ 1968int thread_selfusage(struct proc *p __unused, struct thread_selfusage_args *uap __unused, uint64_t *retval) 1969{ 1970 uint64_t runtime; 1971 1972 runtime = thread_get_runtime_self(); 1973 *retval = runtime; 1974 1975 return (0); 1976} 1977