1/* 2 * Copyright (c) 2013 Apple Computer, 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 29/* 30 * System Overrides syscall implementation 31 */ 32 33#include <sys/param.h> 34#include <sys/systm.h> 35#include <sys/kernel.h> 36#include <sys/malloc.h> 37#include <sys/proc_internal.h> 38#include <sys/proc.h> 39#include <sys/kauth.h> 40#include <sys/unistd.h> 41#include <sys/priv.h> 42#include <security/audit/audit.h> 43 44#include <mach/mach_types.h> 45#include <mach/vm_param.h> 46#include <kern/task.h> 47#include <kern/lock.h> 48#include <kern/assert.h> 49#include <kern/sched_prim.h> 50 51#include <sys/kern_overrides.h> 52#include <sys/bsdtask_info.h> 53#include <sys/kdebug.h> 54#include <sys/sysproto.h> 55#include <sys/msgbuf.h> 56 57/* Mutex for global system override state */ 58static lck_mtx_t sys_override_lock; 59static lck_grp_t *sys_override_mtx_grp; 60static lck_attr_t *sys_override_mtx_attr; 61static lck_grp_attr_t *sys_override_mtx_grp_attr; 62 63/* Assertion counts for system properties */ 64static int64_t io_throttle_assert_cnt; 65static int64_t cpu_throttle_assert_cnt; 66 67/* Wait Channel for system override */ 68static uint64_t sys_override_wait; 69 70/* Forward Declarations */ 71static void enable_system_override(uint64_t flags); 72static void disable_system_override(uint64_t flags); 73static __attribute__((noinline)) void PROCESS_OVERRIDING_SYSTEM_DEFAULTS(uint64_t timeout); 74 75/***************************** system_override ********************/ 76/* 77 * int system_override(uint64_t timeout, uint64_t flags); 78 */ 79 80void 81init_system_override() 82{ 83 sys_override_mtx_grp_attr = lck_grp_attr_alloc_init(); 84 sys_override_mtx_grp = lck_grp_alloc_init("system_override", sys_override_mtx_grp_attr); 85 sys_override_mtx_attr = lck_attr_alloc_init(); 86 lck_mtx_init(&sys_override_lock, sys_override_mtx_grp, sys_override_mtx_attr); 87 io_throttle_assert_cnt = cpu_throttle_assert_cnt = 0; 88} 89 90/* system call implementation */ 91int 92system_override(__unused struct proc *p, struct system_override_args * uap, __unused int32_t *retval) 93{ 94 uint64_t timeout = uap->timeout; 95 uint64_t flags = uap->flags; 96 int error = 0; 97 98 /* Check credentials for caller. Only entitled processes are allowed to make this call. */ 99 if ((error = priv_check_cred(kauth_cred_get(), PRIV_SYSTEM_OVERRIDE, 0))) { 100 goto out; 101 } 102 103 /* Check to see if some flags are specified. Zero flags are invalid. */ 104 if ((flags == 0) || ((flags & ~SYS_OVERRIDE_FLAGS_MASK) != 0)) { 105 error = EINVAL; 106 goto out; 107 } 108 109 lck_mtx_lock(&sys_override_lock); 110 111 enable_system_override(flags); 112 113 PROCESS_OVERRIDING_SYSTEM_DEFAULTS(timeout); 114 115 disable_system_override(flags); 116 117 lck_mtx_unlock(&sys_override_lock); 118 119out: 120 return error; 121} 122 123/* 124 * Call for enabling global system override. 125 * This should be called only with the sys_override_lock held. 126 */ 127static void 128enable_system_override(uint64_t flags) 129{ 130 131 if (flags & SYS_OVERRIDE_IO_THROTTLE) { 132 if (io_throttle_assert_cnt == 0) { 133 /* Disable I/O Throttling */ 134 printf("Process %s [%d] disabling system-wide I/O Throttling\n", current_proc()->p_comm, current_proc()->p_pid); 135 KERNEL_DEBUG_CONSTANT(FSDBG_CODE(DBG_THROTTLE, IO_THROTTLE_DISABLE) | DBG_FUNC_START, current_proc()->p_pid, 0, 0, 0, 0); 136 sys_override_io_throttle(THROTTLE_IO_DISABLE); 137 } 138 io_throttle_assert_cnt++; 139 } 140 141 if (flags & SYS_OVERRIDE_CPU_THROTTLE) { 142 if (cpu_throttle_assert_cnt == 0) { 143 /* Disable CPU Throttling */ 144 printf("Process %s [%d] disabling system-wide CPU Throttling\n", current_proc()->p_comm, current_proc()->p_pid); 145 KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_SCHED, MACH_CPU_THROTTLE_DISABLE) | DBG_FUNC_START, current_proc()->p_pid, 0, 0, 0, 0); 146 sys_override_cpu_throttle(CPU_THROTTLE_DISABLE); 147 } 148 cpu_throttle_assert_cnt++; 149 } 150 151} 152 153/* 154 * Call for disabling global system override. 155 * This should be called only with the sys_override_lock held. 156 */ 157static void 158disable_system_override(uint64_t flags) 159{ 160 161 if (flags & SYS_OVERRIDE_IO_THROTTLE) { 162 assert(io_throttle_assert_cnt > 0); 163 io_throttle_assert_cnt--; 164 if (io_throttle_assert_cnt == 0) { 165 /* Enable I/O Throttling */ 166 KERNEL_DEBUG_CONSTANT(FSDBG_CODE(DBG_THROTTLE, IO_THROTTLE_DISABLE) | DBG_FUNC_END, current_proc()->p_pid, 0, 0, 0, 0); 167 sys_override_io_throttle(THROTTLE_IO_ENABLE); 168 } 169 } 170 171 if (flags & SYS_OVERRIDE_CPU_THROTTLE) { 172 assert(cpu_throttle_assert_cnt > 0); 173 cpu_throttle_assert_cnt--; 174 if (cpu_throttle_assert_cnt == 0) { 175 /* Enable CPU Throttling */ 176 KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_SCHED, MACH_CPU_THROTTLE_DISABLE) | DBG_FUNC_END, current_proc()->p_pid, 0, 0, 0, 0); 177 sys_override_cpu_throttle(CPU_THROTTLE_ENABLE); 178 } 179 } 180} 181 182static __attribute__((noinline)) void 183PROCESS_OVERRIDING_SYSTEM_DEFAULTS(uint64_t timeout) 184{ 185 struct timespec ts; 186 ts.tv_sec = timeout / NSEC_PER_SEC; 187 ts.tv_nsec = timeout - ((long)ts.tv_sec * NSEC_PER_SEC); 188 msleep((caddr_t)&sys_override_wait, &sys_override_lock, PRIBIO | PCATCH, "system_override", &ts); 189} 190 191