1*043036a2SApple OSS Distributions /* 2*043036a2SApple OSS Distributions * Copyright (c) 2024 Apple Computer, Inc. All rights reserved. 3*043036a2SApple OSS Distributions * 4*043036a2SApple OSS Distributions * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5*043036a2SApple OSS Distributions * 6*043036a2SApple OSS Distributions * This file contains Original Code and/or Modifications of Original Code 7*043036a2SApple OSS Distributions * as defined in and that are subject to the Apple Public Source License 8*043036a2SApple OSS Distributions * Version 2.0 (the 'License'). You may not use this file except in 9*043036a2SApple OSS Distributions * compliance with the License. The rights granted to you under the License 10*043036a2SApple OSS Distributions * may not be used to create, or enable the creation or redistribution of, 11*043036a2SApple OSS Distributions * unlawful or unlicensed copies of an Apple operating system, or to 12*043036a2SApple OSS Distributions * circumvent, violate, or enable the circumvention or violation of, any 13*043036a2SApple OSS Distributions * terms of an Apple operating system software license agreement. 14*043036a2SApple OSS Distributions * 15*043036a2SApple OSS Distributions * Please obtain a copy of the License at 16*043036a2SApple OSS Distributions * http://www.opensource.apple.com/apsl/ and read it before using this file. 17*043036a2SApple OSS Distributions * 18*043036a2SApple OSS Distributions * The Original Code and all software distributed under the License are 19*043036a2SApple OSS Distributions * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20*043036a2SApple OSS Distributions * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21*043036a2SApple OSS Distributions * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22*043036a2SApple OSS Distributions * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23*043036a2SApple OSS Distributions * Please see the License for the specific language governing rights and 24*043036a2SApple OSS Distributions * limitations under the License. 25*043036a2SApple OSS Distributions * 26*043036a2SApple OSS Distributions * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27*043036a2SApple OSS Distributions */ 28*043036a2SApple OSS Distributions 29*043036a2SApple OSS Distributions #if __arm64__ 30*043036a2SApple OSS Distributions #include <arm_acle.h> 31*043036a2SApple OSS Distributions #include <darwintest.h> 32*043036a2SApple OSS Distributions #include <fcntl.h> 33*043036a2SApple OSS Distributions #include <libproc.h> 34*043036a2SApple OSS Distributions #include <mach/mach.h> 35*043036a2SApple OSS Distributions #include <mach/mach_vm.h> 36*043036a2SApple OSS Distributions #include <mach/vm_map.h> 37*043036a2SApple OSS Distributions #include <signal.h> 38*043036a2SApple OSS Distributions #include <spawn.h> 39*043036a2SApple OSS Distributions #include <spawn_private.h> 40*043036a2SApple OSS Distributions #include <sys/mman.h> 41*043036a2SApple OSS Distributions 42*043036a2SApple OSS Distributions #include "arm_mte_utilities.h" 43*043036a2SApple OSS Distributions #include "test_utils.h" 44*043036a2SApple OSS Distributions 45*043036a2SApple OSS Distributions T_DECL(mte_alloc_from_unentitled, 46*043036a2SApple OSS Distributions "Attempt to allocate tagged memory from MTE-disabled process", 47*043036a2SApple OSS Distributions T_META_REQUIRES_SYSCTL_EQ("hw.optional.arm.FEAT_MTE2", 1), 48*043036a2SApple OSS Distributions XNU_T_META_SOC_SPECIFIC) 49*043036a2SApple OSS Distributions { 50*043036a2SApple OSS Distributions vm_address_t address = 0; 51*043036a2SApple OSS Distributions vm_size_t alloc_size = 16 * 1024; 52*043036a2SApple OSS Distributions 53*043036a2SApple OSS Distributions kern_return_t kr = vm_allocate(mach_task_self(), &address, alloc_size, VM_FLAGS_ANYWHERE | VM_FLAGS_MTE); 54*043036a2SApple OSS Distributions T_EXPECT_MACH_ERROR_(kr, KERN_INVALID_ARGUMENT, "allocate tagged memory in unentitled process"); 55*043036a2SApple OSS Distributions 56*043036a2SApple OSS Distributions if (kr == KERN_SUCCESS) { 57*043036a2SApple OSS Distributions // cleanup if the test failed 58*043036a2SApple OSS Distributions kr = vm_deallocate(mach_task_self(), address, alloc_size); 59*043036a2SApple OSS Distributions T_ASSERT_MACH_SUCCESS(kr, "test cleanup"); 60*043036a2SApple OSS Distributions } 61*043036a2SApple OSS Distributions } 62*043036a2SApple OSS Distributions 63*043036a2SApple OSS Distributions /* Here, "debugger" means an MTE-disabled process with access to tagged memory */ 64*043036a2SApple OSS Distributions T_DECL(mte_debugger_untagged_copyio, 65*043036a2SApple OSS Distributions "Test that debugger processes can do copyio operations without tag checks", 66*043036a2SApple OSS Distributions T_META_REQUIRES_SYSCTL_EQ("hw.optional.arm.FEAT_MTE2", 1), 67*043036a2SApple OSS Distributions XNU_T_META_SOC_SPECIFIC, 68*043036a2SApple OSS Distributions /* Allow ourselves to act as a debugger */ 69*043036a2SApple OSS Distributions T_META_BOOTARGS_SET("amfi_unrestrict_task_for_pid=1"), 70*043036a2SApple OSS Distributions T_META_ASROOT(true)) 71*043036a2SApple OSS Distributions { 72*043036a2SApple OSS Distributions __block kern_return_t kr; 73*043036a2SApple OSS Distributions /* This is the debugger process (MTE disabled) */ 74*043036a2SApple OSS Distributions 75*043036a2SApple OSS Distributions T_SETUPBEGIN; 76*043036a2SApple OSS Distributions char *shm_name = "mte_debugger_untagged_copyio"; 77*043036a2SApple OSS Distributions const mach_vm_size_t ALLOC_SIZE = PAGE_SIZE; 78*043036a2SApple OSS Distributions 79*043036a2SApple OSS Distributions /* create shared memory descriptor for sending address */ 80*043036a2SApple OSS Distributions shm_unlink(shm_name); 81*043036a2SApple OSS Distributions int fd = shm_open(shm_name, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); 82*043036a2SApple OSS Distributions T_ASSERT_POSIX_SUCCESS(fd, "shm_open"); 83*043036a2SApple OSS Distributions 84*043036a2SApple OSS Distributions int ret = ftruncate(fd, sizeof(vm_address_t)); 85*043036a2SApple OSS Distributions T_ASSERT_POSIX_SUCCESS(ret, "ftruncate"); 86*043036a2SApple OSS Distributions 87*043036a2SApple OSS Distributions volatile vm_address_t *shm = mmap(NULL, sizeof(vm_address_t), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 88*043036a2SApple OSS Distributions T_ASSERT_NE(shm, MAP_FAILED, "mmap"); 89*043036a2SApple OSS Distributions /* tell the process being "debugged" how much memory to allocate */ 90*043036a2SApple OSS Distributions *shm = ALLOC_SIZE; 91*043036a2SApple OSS Distributions T_SETUPEND; 92*043036a2SApple OSS Distributions 93*043036a2SApple OSS Distributions /* Launch the to-be-debugged process, which has the MTE code-signing entitlement */ 94*043036a2SApple OSS Distributions char *new_argv[] = { "arm_mte_debugger_helper", shm_name, NULL }; 95*043036a2SApple OSS Distributions pid_t child_pid; 96*043036a2SApple OSS Distributions ret = posix_spawn(&child_pid, new_argv[0], NULL, NULL, new_argv, NULL); 97*043036a2SApple OSS Distributions T_ASSERT_POSIX_ZERO(ret, "posix_spawn"); 98*043036a2SApple OSS Distributions T_ASSERT_NE(child_pid, 0, "posix_spawn child_pid"); 99*043036a2SApple OSS Distributions 100*043036a2SApple OSS Distributions /* Wait for the process to send the allocated address over */ 101*043036a2SApple OSS Distributions while (*shm == ALLOC_SIZE) { 102*043036a2SApple OSS Distributions /* check that the process is still alive */ 103*043036a2SApple OSS Distributions ret = kill(child_pid, 0); // note: signal 0 does not affect the child 104*043036a2SApple OSS Distributions 105*043036a2SApple OSS Distributions /* fails with errno = ESRCH if the child process is dead */ 106*043036a2SApple OSS Distributions T_QUIET; T_ASSERT_POSIX_SUCCESS(ret, "kill"); 107*043036a2SApple OSS Distributions } 108*043036a2SApple OSS Distributions 109*043036a2SApple OSS Distributions vm_address_t child_addr = *shm; 110*043036a2SApple OSS Distributions T_ASSERT_EQ(child_addr & MTE_TAG_MASK, 0ULL, "received untagged pointer"); 111*043036a2SApple OSS Distributions 112*043036a2SApple OSS Distributions mach_port_t child_task; 113*043036a2SApple OSS Distributions kr = task_for_pid(mach_task_self(), child_pid, &child_task); 114*043036a2SApple OSS Distributions T_ASSERT_MACH_SUCCESS(kr, "fetch task_for_pid(child)"); 115*043036a2SApple OSS Distributions 116*043036a2SApple OSS Distributions vm_address_t dest_addr = 0; 117*043036a2SApple OSS Distributions vm_prot_t cur_prot = VM_PROT_DEFAULT, max_prot = VM_PROT_DEFAULT; 118*043036a2SApple OSS Distributions /* remap the process' tagged memory into the debugger's address space */ 119*043036a2SApple OSS Distributions kr = vm_remap(mach_task_self(), &dest_addr, ALLOC_SIZE, 120*043036a2SApple OSS Distributions /* mask = */ 0, VM_FLAGS_ANYWHERE, child_task, child_addr, 121*043036a2SApple OSS Distributions /* copy = */ false, &cur_prot, &max_prot, VM_INHERIT_DEFAULT); 122*043036a2SApple OSS Distributions T_ASSERT_MACH_SUCCESS(kr, "remapped process' tagged memory into debugger"); 123*043036a2SApple OSS Distributions 124*043036a2SApple OSS Distributions /* create a source region for copyio */ 125*043036a2SApple OSS Distributions vm_address_t src_addr = 0; 126*043036a2SApple OSS Distributions kr = vm_allocate(mach_task_self(), &src_addr, ALLOC_SIZE, VM_FLAGS_ANYWHERE); 127*043036a2SApple OSS Distributions T_ASSERT_MACH_SUCCESS(kr, "vm_allocate source region"); 128*043036a2SApple OSS Distributions memset((void*) src_addr, 'A', ALLOC_SIZE); 129*043036a2SApple OSS Distributions 130*043036a2SApple OSS Distributions /* make sure the debugger can copyio the tagged memory with its untagged pointer */ 131*043036a2SApple OSS Distributions expect_normal_exit(^{ 132*043036a2SApple OSS Distributions kr = mach_vm_copy(mach_task_self(), src_addr, ALLOC_SIZE, dest_addr); 133*043036a2SApple OSS Distributions T_EXPECT_MACH_SUCCESS(kr, "copyio using untagged pointer from debugger"); 134*043036a2SApple OSS Distributions }, "copyio tagged memory from debugger"); 135*043036a2SApple OSS Distributions 136*043036a2SApple OSS Distributions /* cleanup */ 137*043036a2SApple OSS Distributions T_SETUPBEGIN; 138*043036a2SApple OSS Distributions ret = close(fd); 139*043036a2SApple OSS Distributions T_QUIET; T_ASSERT_POSIX_SUCCESS(ret, "close"); 140*043036a2SApple OSS Distributions ret = shm_unlink(shm_name); 141*043036a2SApple OSS Distributions T_QUIET; T_ASSERT_POSIX_SUCCESS(ret, "shm_unlink"); 142*043036a2SApple OSS Distributions kr = mach_vm_deallocate(mach_task_self(), dest_addr, ALLOC_SIZE); 143*043036a2SApple OSS Distributions T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "deallocate remapped memory"); 144*043036a2SApple OSS Distributions kr = mach_vm_deallocate(mach_task_self(), src_addr, ALLOC_SIZE); 145*043036a2SApple OSS Distributions T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "deallocate source region"); 146*043036a2SApple OSS Distributions kr = mach_port_deallocate(mach_task_self(), child_task); 147*043036a2SApple OSS Distributions T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "deallocate child task port"); 148*043036a2SApple OSS Distributions T_SETUPEND; 149*043036a2SApple OSS Distributions } 150*043036a2SApple OSS Distributions #endif /* __arm64__ */ 151