1 /* 2 * Copyright (c) 2025 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 29 #if __arm64__ 30 #include <arm_acle.h> 31 #include <darwintest.h> 32 #include <mach/mach.h> 33 #include <mach/vm_map.h> 34 #include <sys/ptrace.h> 35 #include <sys/wait.h> 36 #include <stdlib.h> 37 38 #include "arm_mte_utilities.h" 39 #include "test_utils.h" 40 41 /* 42 * This binary is code signed with the signing ID com.apple.internal.arm_mte_soft_mode_test 43 * and includes ptrace entitlements. 44 * On internal builds, AMFI contains this ID on the MTE soft mode list. 45 * 46 * Test that soft mode is disabled when a process becomes traced (rdar://156025403). 47 */ 48 T_DECL(mte_soft_mode_disabled_when_trace_me, 49 "Test that soft mode is disabled when process is traced", 50 T_META_REQUIRES_SYSCTL_EQ("hw.optional.arm.FEAT_MTE2", 1), 51 XNU_T_META_REQUIRES_DEVELOPMENT_KERNEL, 52 XNU_T_META_SOC_SPECIFIC, 53 T_META_ASROOT(true), 54 T_META_ENABLED(false) /* rdar://142784868 */) 55 { 56 int ret; 57 58 pid_t child_pid = fork(); 59 T_ASSERT_NE(child_pid, -1, "fork"); 60 61 if (child_pid == 0) { 62 /* Child */ 63 validate_proc_pidinfo_mte_soft_mode_status(getpid(), true); 64 ret = ptrace(PT_TRACE_ME, 0, NULL, 0); 65 T_ASSERT_POSIX_SUCCESS(ret, "ptrace(PT_TRACE_ME)"); 66 validate_proc_pidinfo_mte_soft_mode_status(getpid(), false); 67 68 /* Allocate tagged memory */ 69 vm_size_t alloc_size = 16 * 1024; 70 vm_address_t address = allocate_and_tag_range(alloc_size, TAG_RANDOM); 71 72 T_LOG("Child %d triggering MTE fault (should crash in hard mode)", getpid()); 73 char *incorrectly_tagged_ptr = __arm_mte_increment_tag((char *)address, 1); 74 *incorrectly_tagged_ptr = 'X'; 75 76 T_FAIL("Survived TCF -- soft mode didn't work"); 77 exit(1); 78 } else { 79 /* Parent */ 80 int status = 0; 81 pid_t waited_pid = waitpid(child_pid, &status, 0); 82 T_ASSERT_EQ(waited_pid, child_pid, "waitpid()"); 83 84 /* Since we're ptrace'd, the process should be stopped. */ 85 T_ASSERT_TRUE(WIFSTOPPED(status), "WIFSTOPPED(status)"); 86 87 int sig = WSTOPSIG(status); 88 T_LOG("Child stopped with %s (%d)", strsignal(sig), sig); 89 T_ASSERT_EQ(sig, SIGBUS, "Child stopped with SIGBUS"); 90 } 91 } 92 93 /* 94 * Test that soft mode is disabled when a process is attached via PT_ATTACH (rdar://156025403). 95 */ 96 T_DECL(mte_soft_mode_disabled_when_attached, 97 "Test that soft mode is disabled when process is attached via PT_ATTACH", 98 T_META_REQUIRES_SYSCTL_EQ("hw.optional.arm.FEAT_MTE2", 1), 99 XNU_T_META_REQUIRES_DEVELOPMENT_KERNEL, 100 XNU_T_META_SOC_SPECIFIC, 101 T_META_ASROOT(true), 102 T_META_ENABLED(false) /* rdar://142784868 */) 103 { 104 int ret; 105 106 pid_t child_pid = fork(); 107 T_ASSERT_NE(child_pid, -1, "fork"); 108 109 if (child_pid == 0) { 110 /* Child */ 111 validate_proc_pidinfo_mte_soft_mode_status(getpid(), true); 112 T_LOG("Child %d sleeping to allow attach", getpid()); 113 sleep(5); /* Hack: give the parent a moment to attach */ 114 validate_proc_pidinfo_mte_soft_mode_status(getpid(), false); 115 116 /* Allocate tagged memory */ 117 vm_size_t alloc_size = 16 * 1024; 118 vm_address_t address = allocate_and_tag_range(alloc_size, TAG_RANDOM); 119 120 T_LOG("Child %d triggering MTE fault (should crash in hard mode)", getpid()); 121 char *incorrectly_tagged_ptr = __arm_mte_increment_tag((char *)address, 1); 122 *incorrectly_tagged_ptr = 'X'; 123 124 T_FAIL("Survived TCF -- soft mode didn't work"); 125 exit(1); 126 } else { 127 /* Parent */ 128 int status = 0; 129 130 /* Hack: give the child a moment to come up */ 131 usleep(100000); 132 133 /* Attach to the child */ 134 T_LOG("Parent attaching to child %d", child_pid); 135 ret = ptrace(PT_ATTACH, child_pid, NULL, 0); 136 T_ASSERT_POSIX_SUCCESS(ret, "ptrace(PT_ATTACH)"); 137 138 pid_t waited_pid = waitpid(child_pid, &status, 0); 139 T_ASSERT_EQ(waited_pid, child_pid, "waitpid() for attach"); 140 T_ASSERT_TRUE(WIFSTOPPED(status), "Child stopped after attach"); 141 142 /* Continue the child so it can check soft mode status and trigger the fault */ 143 T_LOG("Parent continuing child"); 144 ret = ptrace(PT_CONTINUE, child_pid, (caddr_t)1, 0); 145 T_ASSERT_POSIX_SUCCESS(ret, "ptrace(PT_CONTINUE)"); 146 147 /* Wait for the child to crash */ 148 waited_pid = waitpid(child_pid, &status, 0); 149 T_ASSERT_EQ(waited_pid, child_pid, "waitpid() for crash"); 150 T_ASSERT_TRUE(WIFSTOPPED(status), "WIFSTOPPED(status)"); 151 152 int sig = WSTOPSIG(status); 153 T_LOG("Child stopped with %s (%d)", strsignal(sig), sig); 154 T_ASSERT_EQ(sig, SIGBUS, "Child stopped with SIGBUS"); 155 } 156 } 157 #endif /* __arm64__ */ 158