xref: /xnu-10063.141.1/tests/pac_exception_entitlement.c (revision d8b80295118ef25ac3a784134bcf95cd8e88109f)
1*d8b80295SApple OSS Distributions /*
2*d8b80295SApple OSS Distributions  * Copyright (c) 2023 Apple Computer, Inc. All rights reserved.
3*d8b80295SApple OSS Distributions  *
4*d8b80295SApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5*d8b80295SApple OSS Distributions  *
6*d8b80295SApple OSS Distributions  * This file contains Original Code and/or Modifications of Original Code
7*d8b80295SApple OSS Distributions  * as defined in and that are subject to the Apple Public Source License
8*d8b80295SApple OSS Distributions  * Version 2.0 (the 'License'). You may not use this file except in
9*d8b80295SApple OSS Distributions  * compliance with the License. The rights granted to you under the License
10*d8b80295SApple OSS Distributions  * may not be used to create, or enable the creation or redistribution of,
11*d8b80295SApple OSS Distributions  * unlawful or unlicensed copies of an Apple operating system, or to
12*d8b80295SApple OSS Distributions  * circumvent, violate, or enable the circumvention or violation of, any
13*d8b80295SApple OSS Distributions  * terms of an Apple operating system software license agreement.
14*d8b80295SApple OSS Distributions  *
15*d8b80295SApple OSS Distributions  * Please obtain a copy of the License at
16*d8b80295SApple OSS Distributions  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17*d8b80295SApple OSS Distributions  *
18*d8b80295SApple OSS Distributions  * The Original Code and all software distributed under the License are
19*d8b80295SApple OSS Distributions  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20*d8b80295SApple OSS Distributions  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21*d8b80295SApple OSS Distributions  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22*d8b80295SApple OSS Distributions  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23*d8b80295SApple OSS Distributions  * Please see the License for the specific language governing rights and
24*d8b80295SApple OSS Distributions  * limitations under the License.
25*d8b80295SApple OSS Distributions  *
26*d8b80295SApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27*d8b80295SApple OSS Distributions  */
28*d8b80295SApple OSS Distributions 
29*d8b80295SApple OSS Distributions #include <darwintest.h>
30*d8b80295SApple OSS Distributions #include <stdlib.h>
31*d8b80295SApple OSS Distributions #include <unistd.h>
32*d8b80295SApple OSS Distributions #include <mach/exception_types.h>
33*d8b80295SApple OSS Distributions #include <sys/wait.h>
34*d8b80295SApple OSS Distributions #include <sys/sysctl.h>
35*d8b80295SApple OSS Distributions #include <sys/code_signing.h>
36*d8b80295SApple OSS Distributions 
37*d8b80295SApple OSS Distributions #include "exc_helpers.h"
38*d8b80295SApple OSS Distributions #include "test_utils.h"
39*d8b80295SApple OSS Distributions 
40*d8b80295SApple OSS Distributions T_GLOBAL_META(
41*d8b80295SApple OSS Distributions 	T_META_NAMESPACE("xnu.arm"),
42*d8b80295SApple OSS Distributions 	T_META_RADAR_COMPONENT_NAME("xnu"),
43*d8b80295SApple OSS Distributions 	T_META_RADAR_COMPONENT_VERSION("arm"),
44*d8b80295SApple OSS Distributions 	T_META_OWNER("ghackmann"),
45*d8b80295SApple OSS Distributions 	T_META_REQUIRES_SYSCTL_EQ("hw.optional.ptrauth", 1),
46*d8b80295SApple OSS Distributions 	T_META_IGNORECRASHES(".*pac_exception_entitlement.*"),
47*d8b80295SApple OSS Distributions 	XNU_T_META_SOC_SPECIFIC
48*d8b80295SApple OSS Distributions 	);
49*d8b80295SApple OSS Distributions 
50*d8b80295SApple OSS Distributions #if __arm64e__
51*d8b80295SApple OSS Distributions static size_t
exception_handler(mach_port_t task __unused,mach_port_t thread __unused,exception_type_t type __unused,mach_exception_data_t codes __unused)52*d8b80295SApple OSS Distributions exception_handler(mach_port_t task __unused, mach_port_t thread __unused,
53*d8b80295SApple OSS Distributions     exception_type_t type __unused, mach_exception_data_t codes __unused)
54*d8b80295SApple OSS Distributions {
55*d8b80295SApple OSS Distributions 	T_ASSERT_FAIL("kernel ran exception handler instead of terminating process");
56*d8b80295SApple OSS Distributions }
57*d8b80295SApple OSS Distributions 
58*d8b80295SApple OSS Distributions /*
59*d8b80295SApple OSS Distributions  * Real-world software should use ptrauth.h when it needs to manually sign or
60*d8b80295SApple OSS Distributions  * auth pointers.  But for testing purposes we need clang to emit specific
61*d8b80295SApple OSS Distributions  * ptrauth instructions, so we use inline asm here instead.
62*d8b80295SApple OSS Distributions  *
63*d8b80295SApple OSS Distributions  * Likewise clang would normally combine the "naked" auth and brk testcases as
64*d8b80295SApple OSS Distributions  * part of a sequence like:
65*d8b80295SApple OSS Distributions  *
66*d8b80295SApple OSS Distributions  *     output = auth(...);
67*d8b80295SApple OSS Distributions  *     if (output is poisoned) {
68*d8b80295SApple OSS Distributions  *         brk(PTRAUTH_FAILURE_COMMENT);
69*d8b80295SApple OSS Distributions  *     }
70*d8b80295SApple OSS Distributions  *
71*d8b80295SApple OSS Distributions  * On auth failure, CPUs that implement FEAT_FPAC will trap immediately at the
72*d8b80295SApple OSS Distributions  * auth instruction, and CPUs without FEAT_FPAC will trap at the later brk
73*d8b80295SApple OSS Distributions  * instruction.  But again, for testing purposes we want these to be two
74*d8b80295SApple OSS Distributions  * discrete cases.  (On FPAC-enabled CPUs, the kernel should treat *both* traps
75*d8b80295SApple OSS Distributions  * as ptrauth failure, even if we don't expect the latter to be reachable in
76*d8b80295SApple OSS Distributions  * real-world software.)
77*d8b80295SApple OSS Distributions  */
78*d8b80295SApple OSS Distributions 
79*d8b80295SApple OSS Distributions static void
naked_auth(void)80*d8b80295SApple OSS Distributions naked_auth(void)
81*d8b80295SApple OSS Distributions {
82*d8b80295SApple OSS Distributions 	asm volatile (
83*d8b80295SApple OSS Distributions                 "mov	x0, #0"                 "\n"
84*d8b80295SApple OSS Distributions                 "paciza	x0"                     "\n"
85*d8b80295SApple OSS Distributions                 "eor	x0, x0, (1 << 63)"      "\n"
86*d8b80295SApple OSS Distributions                 "autiza	x0"
87*d8b80295SApple OSS Distributions                 :
88*d8b80295SApple OSS Distributions                 :
89*d8b80295SApple OSS Distributions                 : "x0"
90*d8b80295SApple OSS Distributions         );
91*d8b80295SApple OSS Distributions }
92*d8b80295SApple OSS Distributions 
93*d8b80295SApple OSS Distributions static void
ptrauth_brk(void)94*d8b80295SApple OSS Distributions ptrauth_brk(void)
95*d8b80295SApple OSS Distributions {
96*d8b80295SApple OSS Distributions 	asm volatile ("brk 0xc470");
97*d8b80295SApple OSS Distributions }
98*d8b80295SApple OSS Distributions 
99*d8b80295SApple OSS Distributions static void
combined_branch_auth(void)100*d8b80295SApple OSS Distributions combined_branch_auth(void)
101*d8b80295SApple OSS Distributions {
102*d8b80295SApple OSS Distributions 	asm volatile (
103*d8b80295SApple OSS Distributions                 "adr	x0, 1f"                 "\n"
104*d8b80295SApple OSS Distributions                 "paciza	x0"                     "\n"
105*d8b80295SApple OSS Distributions                 "eor	x0, x0, (1 << 63)"      "\n"
106*d8b80295SApple OSS Distributions                 "braaz	x0"                     "\n"
107*d8b80295SApple OSS Distributions         "1:"
108*d8b80295SApple OSS Distributions                 :
109*d8b80295SApple OSS Distributions                 :
110*d8b80295SApple OSS Distributions                 : "x0"
111*d8b80295SApple OSS Distributions         );
112*d8b80295SApple OSS Distributions }
113*d8b80295SApple OSS Distributions 
114*d8b80295SApple OSS Distributions static void
combined_load_auth(void)115*d8b80295SApple OSS Distributions combined_load_auth(void)
116*d8b80295SApple OSS Distributions {
117*d8b80295SApple OSS Distributions 	asm volatile (
118*d8b80295SApple OSS Distributions                 "mov	x0, sp"                 "\n"
119*d8b80295SApple OSS Distributions                 "pacdza	x0"                     "\n"
120*d8b80295SApple OSS Distributions                 "eor	x0, x0, (1 << 63)"      "\n"
121*d8b80295SApple OSS Distributions                 "ldraa	x0, [x0]"               "\n"
122*d8b80295SApple OSS Distributions                 :
123*d8b80295SApple OSS Distributions                 :
124*d8b80295SApple OSS Distributions                 : "x0"
125*d8b80295SApple OSS Distributions         );
126*d8b80295SApple OSS Distributions }
127*d8b80295SApple OSS Distributions 
128*d8b80295SApple OSS Distributions static void
run_pac_exception_test(void (* ptrauth_failure_fn)(void))129*d8b80295SApple OSS Distributions run_pac_exception_test(void (*ptrauth_failure_fn)(void))
130*d8b80295SApple OSS Distributions {
131*d8b80295SApple OSS Distributions 
132*d8b80295SApple OSS Distributions 	pid_t pid = fork();
133*d8b80295SApple OSS Distributions 	T_QUIET; T_ASSERT_POSIX_SUCCESS(pid, "fork");
134*d8b80295SApple OSS Distributions 
135*d8b80295SApple OSS Distributions 	if (pid == 0) {
136*d8b80295SApple OSS Distributions 		mach_port_t exc_port = create_exception_port(EXC_MASK_BAD_ACCESS | EXC_MASK_BREAKPOINT);
137*d8b80295SApple OSS Distributions 		run_exception_handler(exc_port, exception_handler);
138*d8b80295SApple OSS Distributions 
139*d8b80295SApple OSS Distributions 		ptrauth_failure_fn();
140*d8b80295SApple OSS Distributions 		/* ptrauth_failure_fn() should have raised an uncatchable exception */
141*d8b80295SApple OSS Distributions 		T_FAIL("child ran to completion");
142*d8b80295SApple OSS Distributions 	} else {
143*d8b80295SApple OSS Distributions 		int status;
144*d8b80295SApple OSS Distributions 		int err = waitpid(pid, &status, 0);
145*d8b80295SApple OSS Distributions 		T_QUIET; T_ASSERT_POSIX_SUCCESS(err, "waitpid");
146*d8b80295SApple OSS Distributions 
147*d8b80295SApple OSS Distributions 		T_EXPECT_TRUE(WIFSIGNALED(status), "child terminated due to signal");
148*d8b80295SApple OSS Distributions 		T_EXPECT_EQ(SIGKILL, WTERMSIG(status), "child terminated due to SIGKILL");
149*d8b80295SApple OSS Distributions 	}
150*d8b80295SApple OSS Distributions }
151*d8b80295SApple OSS Distributions #endif //__arm64e__
152*d8b80295SApple OSS Distributions 
153*d8b80295SApple OSS Distributions T_DECL(pac_exception_naked_auth,
154*d8b80295SApple OSS Distributions     "Test the com.apple.private.pac.exception entitlement (naked auth failure)",
155*d8b80295SApple OSS Distributions     T_META_REQUIRES_SYSCTL_EQ("hw.optional.arm.FEAT_FPAC", 1))
156*d8b80295SApple OSS Distributions {
157*d8b80295SApple OSS Distributions #if __arm64e__
158*d8b80295SApple OSS Distributions 	run_pac_exception_test(naked_auth);
159*d8b80295SApple OSS Distributions #else
160*d8b80295SApple OSS Distributions 	T_SKIP("Running on non-arm64e target, skipping...");
161*d8b80295SApple OSS Distributions #endif
162*d8b80295SApple OSS Distributions }
163*d8b80295SApple OSS Distributions 
164*d8b80295SApple OSS Distributions 
165*d8b80295SApple OSS Distributions T_DECL(pac_exception_ptrauth_brk,
166*d8b80295SApple OSS Distributions     "Test the com.apple.private.pac.exception entitlement (brk with comment indicating ptrauth failure)")
167*d8b80295SApple OSS Distributions {
168*d8b80295SApple OSS Distributions #if __arm64e__
169*d8b80295SApple OSS Distributions 	run_pac_exception_test(ptrauth_brk);
170*d8b80295SApple OSS Distributions #else
171*d8b80295SApple OSS Distributions 	T_SKIP("Running on non-arm64e target, skipping...");
172*d8b80295SApple OSS Distributions #endif
173*d8b80295SApple OSS Distributions }
174*d8b80295SApple OSS Distributions 
175*d8b80295SApple OSS Distributions T_DECL(pac_exception_combined_branch_auth,
176*d8b80295SApple OSS Distributions     "Test the com.apple.private.pac.exception entitlement (combined branch + auth failure)")
177*d8b80295SApple OSS Distributions {
178*d8b80295SApple OSS Distributions #if __arm64e__
179*d8b80295SApple OSS Distributions 	run_pac_exception_test(combined_branch_auth);
180*d8b80295SApple OSS Distributions #else
181*d8b80295SApple OSS Distributions 	T_SKIP("Running on non-arm64e target, skipping...");
182*d8b80295SApple OSS Distributions #endif
183*d8b80295SApple OSS Distributions }
184*d8b80295SApple OSS Distributions 
185*d8b80295SApple OSS Distributions T_DECL(pac_exception_combined_load_auth,
186*d8b80295SApple OSS Distributions     "Test the com.apple.private.pac.exception entitlement (combined branch + auth failure)")
187*d8b80295SApple OSS Distributions {
188*d8b80295SApple OSS Distributions #if __arm64e__
189*d8b80295SApple OSS Distributions 	run_pac_exception_test(combined_load_auth);
190*d8b80295SApple OSS Distributions #else
191*d8b80295SApple OSS Distributions 	T_SKIP("Running on non-arm64e target, skipping...");
192*d8b80295SApple OSS Distributions #endif
193*d8b80295SApple OSS Distributions }
194