From eee3565979933af707c711411001ba11fe406a3c Mon Sep 17 00:00:00 2001 From: Apple Date: Thu, 19 Jan 2017 19:27:37 +0000 Subject: [PATCH] xnu-3789.41.3.tar.gz --- config/MasterVersion | 2 +- iokit/Kernel/IOPMrootDomain.cpp | 3 + iokit/Kernel/IOService.cpp | 11 ++- osfmk/ipc/mach_kernelrpc.c | 10 +-- osfmk/kern/ipc_host.c | 5 +- tools/tests/darwintests/voucher_traps.c | 112 ++++++++++++++++++++++++ 6 files changed, 133 insertions(+), 10 deletions(-) create mode 100644 tools/tests/darwintests/voucher_traps.c diff --git a/config/MasterVersion b/config/MasterVersion index 5c5f71e02..dec53ed76 100644 --- a/config/MasterVersion +++ b/config/MasterVersion @@ -1,4 +1,4 @@ -16.3.0 +16.4.0 # The first line of this file contains the master version number for the kernel. # All other instances of the kernel version in xnu are derived from this file. diff --git a/iokit/Kernel/IOPMrootDomain.cpp b/iokit/Kernel/IOPMrootDomain.cpp index e967cb33f..f2015f386 100644 --- a/iokit/Kernel/IOPMrootDomain.cpp +++ b/iokit/Kernel/IOPMrootDomain.cpp @@ -5021,6 +5021,9 @@ void IOPMrootDomain::handleOurPowerChangeStart( _systemMessageClientMask &= ~kSystemMessageClientLegacyApp; if ((_highestCapability & kIOPMSystemCapabilityGraphics) == 0) _systemMessageClientMask &= ~kSystemMessageClientKernel; +#if HIBERNATION + gIOHibernateState = 0; +#endif // Record the reason for dark wake back to sleep // System may not have ever achieved full wake diff --git a/iokit/Kernel/IOService.cpp b/iokit/Kernel/IOService.cpp index 440b5c589..57323e108 100644 --- a/iokit/Kernel/IOService.cpp +++ b/iokit/Kernel/IOService.cpp @@ -4984,6 +4984,8 @@ void IOService::updateConsoleUsers(OSArray * consoleUsers, IOMessage systemMessa bool publish; OSDictionary * user; static IOMessage sSystemPower; + clock_sec_t now = 0; + clock_usec_t microsecs; regEntry = IORegistryEntry::getRegistryRoot(); @@ -5040,6 +5042,9 @@ void IOService::updateConsoleUsers(OSArray * consoleUsers, IOMessage systemMessa } #if HIBERNATION if (!loginLocked) gIOConsoleBooterLockState = 0; + IOLog("IOConsoleUsers: time(%d) %ld->%d, lin %d, llk %d, \n", + (num != 0), gIOConsoleLockTime, (num ? num->unsigned32BitValue() : 0), + gIOConsoleLoggedIn, loginLocked); #endif /* HIBERNATION */ gIOConsoleLockTime = num ? num->unsigned32BitValue() : 0; } @@ -5058,9 +5063,6 @@ void IOService::updateConsoleUsers(OSArray * consoleUsers, IOMessage systemMessa #endif /* HIBERNATION */ else if (gIOConsoleLockTime) { - clock_sec_t now; - clock_usec_t microsecs; - clock_get_calendar_microtime(&now, µsecs); if (gIOConsoleLockTime > now) { @@ -5092,6 +5094,9 @@ void IOService::updateConsoleUsers(OSArray * consoleUsers, IOMessage systemMessa else if (gIOConsoleLockTime) gIOScreenLockState = kIOScreenLockUnlocked; else gIOScreenLockState = kIOScreenLockNoLock; gIOChosenEntry->setProperty(kIOScreenLockStateKey, &gIOScreenLockState, sizeof(gIOScreenLockState)); + + IOLog("IOConsoleUsers: gIOScreenLockState %d, hs %d, bs %d, now %ld, sm 0x%x\n", + gIOScreenLockState, gIOHibernateState, (gIOConsoleBooterLockState != 0), now, systemMessage); } #endif /* HIBERNATION */ diff --git a/osfmk/ipc/mach_kernelrpc.c b/osfmk/ipc/mach_kernelrpc.c index 1b50efbb7..b24f4d5dd 100644 --- a/osfmk/ipc/mach_kernelrpc.c +++ b/osfmk/ipc/mach_kernelrpc.c @@ -450,7 +450,7 @@ mach_voucher_extract_attr_recipe_trap(struct mach_voucher_extract_attr_recipe_ar if (voucher == IV_NULL) return MACH_SEND_INVALID_DEST; - mach_msg_type_number_t __assert_only max_sz = sz; + mach_msg_type_number_t max_sz = sz; if (sz < MACH_VOUCHER_TRAP_STACK_LIMIT) { /* keep small recipes on the stack for speed */ @@ -466,14 +466,14 @@ mach_voucher_extract_attr_recipe_trap(struct mach_voucher_extract_attr_recipe_ar if (kr == KERN_SUCCESS && sz > 0) kr = copyout(krecipe, (void *)args->recipe, sz); } else { - uint8_t *krecipe = kalloc((vm_size_t)sz); + uint8_t *krecipe = kalloc((vm_size_t)max_sz); if (!krecipe) { kr = KERN_RESOURCE_SHORTAGE; goto done; } - if (copyin(args->recipe, (void *)krecipe, args->recipe_size)) { - kfree(krecipe, (vm_size_t)sz); + if (copyin(args->recipe, (void *)krecipe, sz)) { + kfree(krecipe, (vm_size_t)max_sz); kr = KERN_MEMORY_ERROR; goto done; } @@ -484,7 +484,7 @@ mach_voucher_extract_attr_recipe_trap(struct mach_voucher_extract_attr_recipe_ar if (kr == KERN_SUCCESS && sz > 0) kr = copyout(krecipe, (void *)args->recipe, sz); - kfree(krecipe, (vm_size_t)sz); + kfree(krecipe, (vm_size_t)max_sz); } kr = copyout(&sz, args->recipe_size, sizeof(sz)); diff --git a/osfmk/kern/ipc_host.c b/osfmk/kern/ipc_host.c index b68bd0a09..8e61a5dfe 100644 --- a/osfmk/kern/ipc_host.c +++ b/osfmk/kern/ipc_host.c @@ -167,10 +167,13 @@ mach_port_name_t host_self_trap( __unused struct host_self_trap_args *args) { + task_t self = current_task(); ipc_port_t sright; mach_port_name_t name; - sright = ipc_port_copy_send(current_task()->itk_host); + itk_lock(self); + sright = ipc_port_copy_send(self->itk_host); + itk_unlock(self); name = ipc_port_copyout_send(sright, current_space()); return name; } diff --git a/tools/tests/darwintests/voucher_traps.c b/tools/tests/darwintests/voucher_traps.c new file mode 100644 index 000000000..f3e5a0a20 --- /dev/null +++ b/tools/tests/darwintests/voucher_traps.c @@ -0,0 +1,112 @@ +/* + * Test voucher trap APIs. + * There was an unfortunate bug in the trap interface that used the user space + * _address_ of a trap parameter as a copyin size. This test validates there + * are no other kernel panics in the voucher create and voucher attribute + * extraction mach traps. + * + * clang -o voucher_traps voucher_traps.c -ldarwintest -Weverything -Wno-gnu-flexible-array-initializer + * + * + */ + +#include +#include +#include +#include +#include + +#include + +#include + + +static mach_port_t get_atm_voucher(void) +{ + mach_voucher_attr_recipe_data_t r = { + .key = MACH_VOUCHER_ATTR_KEY_ATM, + .command = MACH_VOUCHER_ATTR_ATM_CREATE + }; + mach_port_t port = MACH_PORT_NULL; + kern_return_t kr = host_create_mach_voucher(mach_host_self(), + (mach_voucher_attr_raw_recipe_array_t)&r, + sizeof(r), &port); + T_ASSERT_MACH_SUCCESS(kr, "Create ATM voucher: 0x%x", (unsigned int)port); + + return port; +} + + +T_DECL(voucher_extract_attr_recipe, "voucher_extract_attr_recipe") +{ + kern_return_t kr; + mach_vm_size_t alloc_sz; + mach_port_t port; + mach_vm_address_t alloc_addr; + + /* map at least a page of memory at some arbitrary location */ + alloc_sz = (mach_vm_size_t)round_page(MACH_VOUCHER_TRAP_STACK_LIMIT + 1); + + /* + * We could theoretically ask for a fixed location, but this is more + * reliable, and we're not actually trying to exploit anything - a + * kernel panic on failure should suffice :-) + */ + alloc_addr = (mach_vm_address_t)round_page(MACH_VOUCHER_ATTR_MAX_RAW_RECIPE_ARRAY_SIZE + 1); + kr = mach_vm_allocate(mach_task_self(), &alloc_addr, + alloc_sz, VM_FLAGS_ANYWHERE); + + /* + * Make sure that the address of the allocation is larger than the + * maximum recipe size: this will test for the bug that was fixed in + * . + */ + T_ASSERT_GT_ULLONG((uint64_t)alloc_addr, + (uint64_t)MACH_VOUCHER_ATTR_MAX_RAW_RECIPE_ARRAY_SIZE, + "Recipe addr (%llu bytes): 0x%llx > max recipe sz: %llu", + (uint64_t)alloc_sz, (uint64_t)alloc_addr, + (uint64_t)MACH_VOUCHER_ATTR_MAX_RAW_RECIPE_ARRAY_SIZE); + + /* make the allocation look like a pointer to an int */ + mach_msg_type_number_t *recipe_size; + recipe_size = (mach_msg_type_number_t *)((uintptr_t)alloc_addr); + bzero(recipe_size, (unsigned long)alloc_sz); + if (alloc_sz > MACH_VOUCHER_ATTR_MAX_RAW_RECIPE_ARRAY_SIZE) + *recipe_size = MACH_VOUCHER_ATTR_MAX_RAW_RECIPE_ARRAY_SIZE; + else + *recipe_size = (mach_msg_type_number_t)alloc_sz; + + /* recipe buffer on the heap: memset it so panics show up loudly */ + size_t size = (size_t)(10 * 1024 * 1024); + void *recipe = malloc(size); + memset(recipe, 0x41, size); + + port = get_atm_voucher(); + + /* + * This should try to extract the ATM attribute using a buffer on the + * kernel heap (probably zone memory). + */ + kr = mach_voucher_extract_attr_recipe_trap(port, MACH_VOUCHER_ATTR_KEY_ATM, + recipe, recipe_size); + T_ASSERT_MACH_SUCCESS(kr, "Extract attribute data with recipe: heap"); + + /* reset the recipe memory */ + memset(recipe, 0x41, size); + /* reduce the size to get an allocation on the kernel stack */ + *recipe_size = MACH_VOUCHER_TRAP_STACK_LIMIT - 1; + + /* + * This should try to extract the ATM attribute using a buffer on the + * kernel stack. + */ + kr = mach_voucher_extract_attr_recipe_trap(port, MACH_VOUCHER_ATTR_KEY_ATM, + recipe, recipe_size); + T_ASSERT_MACH_SUCCESS(kr, "Extract attribute data with recipe: stack"); + + /* cleanup */ + + free(recipe); + kr = mach_vm_deallocate(mach_task_self(), alloc_addr, alloc_sz); + T_ASSERT_MACH_SUCCESS(kr, "Deallocate recipe buffers"); +} -- 2.45.2