xref: /xnu-12377.81.4/tests/arm_mte_soft_mode_traced.c (revision 043036a2b3718f7f0be807e2870f8f47d3fa0796)
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