1*4d495c6eSApple OSS Distributions #include <darwintest.h>
2*4d495c6eSApple OSS Distributions #include <darwintest_utils.h>
3*4d495c6eSApple OSS Distributions
4*4d495c6eSApple OSS Distributions #include <errno.h>
5*4d495c6eSApple OSS Distributions #include <stdio.h>
6*4d495c6eSApple OSS Distributions #include <stdlib.h>
7*4d495c6eSApple OSS Distributions #include <string.h>
8*4d495c6eSApple OSS Distributions #include <unistd.h>
9*4d495c6eSApple OSS Distributions #include <libgen.h>
10*4d495c6eSApple OSS Distributions
11*4d495c6eSApple OSS Distributions #include <sys/stat.h>
12*4d495c6eSApple OSS Distributions
13*4d495c6eSApple OSS Distributions #include <mach/mach_init.h>
14*4d495c6eSApple OSS Distributions #include <mach/mach_vm.h>
15*4d495c6eSApple OSS Distributions #include <mach-o/dyld.h>
16*4d495c6eSApple OSS Distributions
17*4d495c6eSApple OSS Distributions T_GLOBAL_META(
18*4d495c6eSApple OSS Distributions T_META_NAMESPACE("xnu.vm"),
19*4d495c6eSApple OSS Distributions T_META_RADAR_COMPONENT_NAME("xnu"),
20*4d495c6eSApple OSS Distributions T_META_RADAR_COMPONENT_VERSION("VM"));
21*4d495c6eSApple OSS Distributions
22*4d495c6eSApple OSS Distributions static int expected_code = 0;
23*4d495c6eSApple OSS Distributions static int panic_on_unsigned_orig = 0;
24*4d495c6eSApple OSS Distributions
25*4d495c6eSApple OSS Distributions static void *
get_sysctl_value_byname(const char * name,size_t * len)26*4d495c6eSApple OSS Distributions get_sysctl_value_byname(const char *name, size_t *len)
27*4d495c6eSApple OSS Distributions {
28*4d495c6eSApple OSS Distributions int rc = -1;
29*4d495c6eSApple OSS Distributions char *val = NULL;
30*4d495c6eSApple OSS Distributions size_t val_len = 0;
31*4d495c6eSApple OSS Distributions
32*4d495c6eSApple OSS Distributions rc = sysctlbyname(name, NULL, &val_len, NULL, 0);
33*4d495c6eSApple OSS Distributions T_QUIET;
34*4d495c6eSApple OSS Distributions T_EXPECT_POSIX_SUCCESS(rc, "retrieve sysctl length");
35*4d495c6eSApple OSS Distributions if (T_RESULT == T_RESULT_FAIL) {
36*4d495c6eSApple OSS Distributions return NULL;
37*4d495c6eSApple OSS Distributions }
38*4d495c6eSApple OSS Distributions
39*4d495c6eSApple OSS Distributions T_WITH_ERRNO;
40*4d495c6eSApple OSS Distributions val = malloc(val_len);
41*4d495c6eSApple OSS Distributions T_QUIET;
42*4d495c6eSApple OSS Distributions T_EXPECT_NOTNULL(val, "malloc fail for sysctl value");
43*4d495c6eSApple OSS Distributions if (T_RESULT == T_RESULT_FAIL) {
44*4d495c6eSApple OSS Distributions return NULL;
45*4d495c6eSApple OSS Distributions }
46*4d495c6eSApple OSS Distributions
47*4d495c6eSApple OSS Distributions rc = sysctlbyname(name, (void *)val, &val_len, NULL, 0);
48*4d495c6eSApple OSS Distributions T_QUIET;
49*4d495c6eSApple OSS Distributions T_EXPECT_POSIX_SUCCESS(rc, "retrieve sysctl byname");
50*4d495c6eSApple OSS Distributions if (T_RESULT == T_RESULT_FAIL) {
51*4d495c6eSApple OSS Distributions return NULL;
52*4d495c6eSApple OSS Distributions } else {
53*4d495c6eSApple OSS Distributions *len = val_len;
54*4d495c6eSApple OSS Distributions return (void *)val;
55*4d495c6eSApple OSS Distributions }
56*4d495c6eSApple OSS Distributions }
57*4d495c6eSApple OSS Distributions
58*4d495c6eSApple OSS Distributions static bool
cs_enforcement_disabled(void)59*4d495c6eSApple OSS Distributions cs_enforcement_disabled(void)
60*4d495c6eSApple OSS Distributions {
61*4d495c6eSApple OSS Distributions int *cs_enforcement = NULL;
62*4d495c6eSApple OSS Distributions size_t sysctl_val_len = 0;
63*4d495c6eSApple OSS Distributions bool cs_enforcement_disable = false;
64*4d495c6eSApple OSS Distributions
65*4d495c6eSApple OSS Distributions cs_enforcement = (int *)get_sysctl_value_byname("vm.cs_process_enforcement", &sysctl_val_len);
66*4d495c6eSApple OSS Distributions T_EXPECT_NOTNULL(cs_enforcement, "sysctl vm.cs_process_enforcement");
67*4d495c6eSApple OSS Distributions if (T_RESULT == T_RESULT_FAIL) {
68*4d495c6eSApple OSS Distributions goto bail;
69*4d495c6eSApple OSS Distributions }
70*4d495c6eSApple OSS Distributions
71*4d495c6eSApple OSS Distributions cs_enforcement_disable = (*cs_enforcement == 0);
72*4d495c6eSApple OSS Distributions
73*4d495c6eSApple OSS Distributions bail:
74*4d495c6eSApple OSS Distributions if (cs_enforcement) {
75*4d495c6eSApple OSS Distributions free(cs_enforcement);
76*4d495c6eSApple OSS Distributions }
77*4d495c6eSApple OSS Distributions
78*4d495c6eSApple OSS Distributions return cs_enforcement_disable;
79*4d495c6eSApple OSS Distributions }
80*4d495c6eSApple OSS Distributions
81*4d495c6eSApple OSS Distributions static bool
pmap_cs_enabled(void)82*4d495c6eSApple OSS Distributions pmap_cs_enabled(void)
83*4d495c6eSApple OSS Distributions {
84*4d495c6eSApple OSS Distributions const char *unavailable_reason = "<unknown>";
85*4d495c6eSApple OSS Distributions char *kern_version = NULL;
86*4d495c6eSApple OSS Distributions char *bootargs = NULL;
87*4d495c6eSApple OSS Distributions bool platform_arm64 = false;
88*4d495c6eSApple OSS Distributions bool platform_macos = false;
89*4d495c6eSApple OSS Distributions bool pmap_cs_enabled = false;
90*4d495c6eSApple OSS Distributions size_t sysctl_val_len = 0;
91*4d495c6eSApple OSS Distributions unsigned long i;
92*4d495c6eSApple OSS Distributions
93*4d495c6eSApple OSS Distributions #if TARGET_CPU_ARM64
94*4d495c6eSApple OSS Distributions platform_arm64 = true;
95*4d495c6eSApple OSS Distributions #endif
96*4d495c6eSApple OSS Distributions
97*4d495c6eSApple OSS Distributions if (platform_arm64 == false) {
98*4d495c6eSApple OSS Distributions unavailable_reason = "not supported on Intel platform";
99*4d495c6eSApple OSS Distributions goto exit;
100*4d495c6eSApple OSS Distributions }
101*4d495c6eSApple OSS Distributions
102*4d495c6eSApple OSS Distributions #if TARGET_OS_OSX
103*4d495c6eSApple OSS Distributions platform_macos = true;
104*4d495c6eSApple OSS Distributions #endif
105*4d495c6eSApple OSS Distributions
106*4d495c6eSApple OSS Distributions if (platform_macos == true) {
107*4d495c6eSApple OSS Distributions unavailable_reason = "not supported on macOS";
108*4d495c6eSApple OSS Distributions goto exit;
109*4d495c6eSApple OSS Distributions }
110*4d495c6eSApple OSS Distributions
111*4d495c6eSApple OSS Distributions /* PMAP_CS technology is not present on below SoCs */
112*4d495c6eSApple OSS Distributions const char *pmap_cs_absent_platforms[] = {"T7000", "T7001", "S8000", "S8001", "S8003", "T8002", "T8004"};
113*4d495c6eSApple OSS Distributions
114*4d495c6eSApple OSS Distributions kern_version = (char *)get_sysctl_value_byname("kern.version", &sysctl_val_len);
115*4d495c6eSApple OSS Distributions T_EXPECT_NOTNULL(kern_version, "sysctl kern.version(%s)", kern_version);
116*4d495c6eSApple OSS Distributions if (T_RESULT == T_RESULT_FAIL) {
117*4d495c6eSApple OSS Distributions unavailable_reason = "unable to query sysctl kern.version";
118*4d495c6eSApple OSS Distributions goto exit;
119*4d495c6eSApple OSS Distributions }
120*4d495c6eSApple OSS Distributions
121*4d495c6eSApple OSS Distributions for (i = 0; i < sizeof(pmap_cs_absent_platforms) / sizeof(pmap_cs_absent_platforms[0]); i++) {
122*4d495c6eSApple OSS Distributions if (strstr(kern_version, pmap_cs_absent_platforms[i])) {
123*4d495c6eSApple OSS Distributions unavailable_reason = "not supported on this SoC platform";
124*4d495c6eSApple OSS Distributions goto exit;
125*4d495c6eSApple OSS Distributions }
126*4d495c6eSApple OSS Distributions }
127*4d495c6eSApple OSS Distributions
128*4d495c6eSApple OSS Distributions /*
129*4d495c6eSApple OSS Distributions * If we reach this point, it means the platform kernel has PMAP_CS code present. However
130*4d495c6eSApple OSS Distributions * the code is disabled by default on certain SoCs. Moreover, the code can be disabled
131*4d495c6eSApple OSS Distributions * through an explicit boot-arg as well.
132*4d495c6eSApple OSS Distributions */
133*4d495c6eSApple OSS Distributions
134*4d495c6eSApple OSS Distributions bootargs = (char *)get_sysctl_value_byname("kern.bootargs", &sysctl_val_len);
135*4d495c6eSApple OSS Distributions T_EXPECT_NOTNULL(bootargs, "sysctl kern.bootargs(%s)", bootargs);
136*4d495c6eSApple OSS Distributions if (T_RESULT == T_RESULT_FAIL) {
137*4d495c6eSApple OSS Distributions unavailable_reason = "unable to query sysctl kern.bootargs";
138*4d495c6eSApple OSS Distributions goto exit;
139*4d495c6eSApple OSS Distributions }
140*4d495c6eSApple OSS Distributions
141*4d495c6eSApple OSS Distributions /* Disabled explicitly through boot-arg */
142*4d495c6eSApple OSS Distributions if (strstr(bootargs, "pmap_cs=0")) {
143*4d495c6eSApple OSS Distributions unavailable_reason = "disabled by explicit pmap_cs=0 boot-arg";
144*4d495c6eSApple OSS Distributions goto exit;
145*4d495c6eSApple OSS Distributions }
146*4d495c6eSApple OSS Distributions
147*4d495c6eSApple OSS Distributions /* PMAP_CS technology is disabled by default on below SoCs */
148*4d495c6eSApple OSS Distributions const char *pmap_cs_disabled_platforms[] = {"T8010", "T8011", "T8012", "T8015"};
149*4d495c6eSApple OSS Distributions
150*4d495c6eSApple OSS Distributions for (i = 0; i < sizeof(pmap_cs_disabled_platforms) / sizeof(pmap_cs_disabled_platforms[0]); i++) {
151*4d495c6eSApple OSS Distributions if (strstr(kern_version, pmap_cs_disabled_platforms[i]) && !strstr(bootargs, "pmap_cs=1")) {
152*4d495c6eSApple OSS Distributions unavailable_reason = "disabled by default on this SoC platform";
153*4d495c6eSApple OSS Distributions goto exit;
154*4d495c6eSApple OSS Distributions }
155*4d495c6eSApple OSS Distributions }
156*4d495c6eSApple OSS Distributions
157*4d495c6eSApple OSS Distributions /* If we reach here, it means PMAP_CS is enabled */
158*4d495c6eSApple OSS Distributions pmap_cs_enabled = true;
159*4d495c6eSApple OSS Distributions
160*4d495c6eSApple OSS Distributions exit:
161*4d495c6eSApple OSS Distributions if (bootargs) {
162*4d495c6eSApple OSS Distributions free(bootargs);
163*4d495c6eSApple OSS Distributions }
164*4d495c6eSApple OSS Distributions
165*4d495c6eSApple OSS Distributions if (kern_version) {
166*4d495c6eSApple OSS Distributions free(kern_version);
167*4d495c6eSApple OSS Distributions }
168*4d495c6eSApple OSS Distributions
169*4d495c6eSApple OSS Distributions if (pmap_cs_enabled == false) {
170*4d495c6eSApple OSS Distributions T_LOG("INFO: PMAP_CS is either not available or is disabled on this platform: %s", unavailable_reason);
171*4d495c6eSApple OSS Distributions }
172*4d495c6eSApple OSS Distributions return pmap_cs_enabled;
173*4d495c6eSApple OSS Distributions }
174*4d495c6eSApple OSS Distributions
175*4d495c6eSApple OSS Distributions static bool
pmap_cs_unsigned_pages_allowed(void)176*4d495c6eSApple OSS Distributions pmap_cs_unsigned_pages_allowed(void)
177*4d495c6eSApple OSS Distributions {
178*4d495c6eSApple OSS Distributions char *bootargs = NULL;
179*4d495c6eSApple OSS Distributions bool pmap_cs_unsigned_pages_allow = false;
180*4d495c6eSApple OSS Distributions size_t sysctl_val_len = 0;
181*4d495c6eSApple OSS Distributions
182*4d495c6eSApple OSS Distributions bootargs = (char *)get_sysctl_value_byname("kern.bootargs", &sysctl_val_len);
183*4d495c6eSApple OSS Distributions T_EXPECT_NOTNULL(bootargs, "sysctl kern.bootargs(%s)", bootargs);
184*4d495c6eSApple OSS Distributions if (T_RESULT == T_RESULT_FAIL) {
185*4d495c6eSApple OSS Distributions goto exit;
186*4d495c6eSApple OSS Distributions }
187*4d495c6eSApple OSS Distributions
188*4d495c6eSApple OSS Distributions /*
189*4d495c6eSApple OSS Distributions * Checking for boot-args can be tricky, since `strstr` will return based on the
190*4d495c6eSApple OSS Distributions * first match for the boot-arg.
191*4d495c6eSApple OSS Distributions *
192*4d495c6eSApple OSS Distributions * For example: boot-args="pmap_cs_unrestrict_pmap_cs_disable=1 pmap_cs_unrestrict_pmap_cs_disable=0"
193*4d495c6eSApple OSS Distributions * The following code will only catch the first one, and believe the boot-arg is set, even though
194*4d495c6eSApple OSS Distributions * the kernel will parse both, and consider the latter as the actual value.
195*4d495c6eSApple OSS Distributions *
196*4d495c6eSApple OSS Distributions * This can be potentially fixed with `strrstr`, but that isn't standard in the C library,
197*4d495c6eSApple OSS Distributions * so we don't use it.
198*4d495c6eSApple OSS Distributions */
199*4d495c6eSApple OSS Distributions
200*4d495c6eSApple OSS Distributions if (strstr(bootargs, "pmap_cs_unrestrict_pmap_cs_disable=1")) {
201*4d495c6eSApple OSS Distributions pmap_cs_unsigned_pages_allow = true;
202*4d495c6eSApple OSS Distributions goto exit;
203*4d495c6eSApple OSS Distributions } else if (strstr(bootargs, "amfi=1") || strstr(bootargs, "amfi=3") || strstr(bootargs, "amfi=-1")) {
204*4d495c6eSApple OSS Distributions /* Any of these boot-args enable pmap_cs_unrestrict_pmap_cs_disable, but it can be overridden */
205*4d495c6eSApple OSS Distributions if (!strstr(bootargs, "pmap_cs_unrestrict_pmap_cs_disable=0")) {
206*4d495c6eSApple OSS Distributions /* Boot-arg is NOT overridden, so PMAP_CS will allow unsigned pages */
207*4d495c6eSApple OSS Distributions pmap_cs_unsigned_pages_allow = true;
208*4d495c6eSApple OSS Distributions goto exit;
209*4d495c6eSApple OSS Distributions }
210*4d495c6eSApple OSS Distributions }
211*4d495c6eSApple OSS Distributions
212*4d495c6eSApple OSS Distributions if (strstr(bootargs, "pmap_cs_allow_modified_code_pages=1")) {
213*4d495c6eSApple OSS Distributions pmap_cs_unsigned_pages_allow = true;
214*4d495c6eSApple OSS Distributions goto exit;
215*4d495c6eSApple OSS Distributions } else if (cs_enforcement_disabled()) {
216*4d495c6eSApple OSS Distributions /* cs_enforcement_disable enables pmap_cs_allow_modified_code_pages, but it can be overridden */
217*4d495c6eSApple OSS Distributions if (!strstr(bootargs, "pmap_cs_allow_modified_code_pages=0")) {
218*4d495c6eSApple OSS Distributions /* Boot-arg is NOT overridden, so PMAP_CS will allow unsigned pages */
219*4d495c6eSApple OSS Distributions pmap_cs_unsigned_pages_allow = true;
220*4d495c6eSApple OSS Distributions goto exit;
221*4d495c6eSApple OSS Distributions }
222*4d495c6eSApple OSS Distributions }
223*4d495c6eSApple OSS Distributions
224*4d495c6eSApple OSS Distributions exit:
225*4d495c6eSApple OSS Distributions if (bootargs) {
226*4d495c6eSApple OSS Distributions free(bootargs);
227*4d495c6eSApple OSS Distributions }
228*4d495c6eSApple OSS Distributions
229*4d495c6eSApple OSS Distributions return pmap_cs_unsigned_pages_allow;
230*4d495c6eSApple OSS Distributions }
231*4d495c6eSApple OSS Distributions
232*4d495c6eSApple OSS Distributions static void
pre_test(void)233*4d495c6eSApple OSS Distributions pre_test(void)
234*4d495c6eSApple OSS Distributions {
235*4d495c6eSApple OSS Distributions bool end_test = false;
236*4d495c6eSApple OSS Distributions int *panic_on_unsigned = NULL;
237*4d495c6eSApple OSS Distributions size_t sysctl_val_len = 0;
238*4d495c6eSApple OSS Distributions
239*4d495c6eSApple OSS Distributions /* When the test helper executes unsigned code, it returns a 1 */
240*4d495c6eSApple OSS Distributions expected_code = 1;
241*4d495c6eSApple OSS Distributions
242*4d495c6eSApple OSS Distributions if (pmap_cs_enabled()) {
243*4d495c6eSApple OSS Distributions /*
244*4d495c6eSApple OSS Distributions * When PMAP_CS is enabled, VM layer delegates all executable code signing enforcement
245*4d495c6eSApple OSS Distributions * to it, and doesn't participate in executable code validation. If PMAP_CS isn't allowing
246*4d495c6eSApple OSS Distributions * unsigned code pages to execute, then we expect a SIGBUS error from the helper.
247*4d495c6eSApple OSS Distributions */
248*4d495c6eSApple OSS Distributions if (!pmap_cs_unsigned_pages_allowed()) {
249*4d495c6eSApple OSS Distributions expected_code = 10;
250*4d495c6eSApple OSS Distributions } else {
251*4d495c6eSApple OSS Distributions T_LOG("WANRING: PMAP_CS is present but allowing unsigned code pages");
252*4d495c6eSApple OSS Distributions }
253*4d495c6eSApple OSS Distributions } else {
254*4d495c6eSApple OSS Distributions /*
255*4d495c6eSApple OSS Distributions * When PMAP_CS isn't enabled, VM layer handles all code signing enforcement, including
256*4d495c6eSApple OSS Distributions * that for executable code. If VM layer isn't allowing unsigned code pages to execute, then
257*4d495c6eSApple OSS Distributions * we expect a SIGKILL error from the helper.
258*4d495c6eSApple OSS Distributions */
259*4d495c6eSApple OSS Distributions if (!cs_enforcement_disabled()) {
260*4d495c6eSApple OSS Distributions expected_code = 9;
261*4d495c6eSApple OSS Distributions } else {
262*4d495c6eSApple OSS Distributions T_LOG("WANRING: unsigned code pages are allowed as code signing enforcement is disabled");
263*4d495c6eSApple OSS Distributions }
264*4d495c6eSApple OSS Distributions }
265*4d495c6eSApple OSS Distributions
266*4d495c6eSApple OSS Distributions #if defined(__arm64__)
267*4d495c6eSApple OSS Distributions panic_on_unsigned = (int *)get_sysctl_value_byname("vm.panic_on_unsigned_execute",
268*4d495c6eSApple OSS Distributions &sysctl_val_len);
269*4d495c6eSApple OSS Distributions if (panic_on_unsigned) {
270*4d495c6eSApple OSS Distributions if (*panic_on_unsigned == 1) {
271*4d495c6eSApple OSS Distributions panic_on_unsigned_orig = 1;
272*4d495c6eSApple OSS Distributions *panic_on_unsigned = 0;
273*4d495c6eSApple OSS Distributions T_EXPECT_POSIX_SUCCESS(sysctlbyname("vm.panic_on_unsigned_execute", NULL, 0, panic_on_unsigned, sizeof(int)),
274*4d495c6eSApple OSS Distributions "set sysctl vm.panic_on_unsigned_execute to 0");
275*4d495c6eSApple OSS Distributions if (T_RESULT == T_RESULT_FAIL) {
276*4d495c6eSApple OSS Distributions end_test = true;
277*4d495c6eSApple OSS Distributions goto bail;
278*4d495c6eSApple OSS Distributions }
279*4d495c6eSApple OSS Distributions }
280*4d495c6eSApple OSS Distributions }
281*4d495c6eSApple OSS Distributions #endif /* defined(__arm64__) */
282*4d495c6eSApple OSS Distributions
283*4d495c6eSApple OSS Distributions bail:
284*4d495c6eSApple OSS Distributions if (panic_on_unsigned) {
285*4d495c6eSApple OSS Distributions free(panic_on_unsigned);
286*4d495c6eSApple OSS Distributions }
287*4d495c6eSApple OSS Distributions
288*4d495c6eSApple OSS Distributions if (end_test) {
289*4d495c6eSApple OSS Distributions T_END;
290*4d495c6eSApple OSS Distributions }
291*4d495c6eSApple OSS Distributions
292*4d495c6eSApple OSS Distributions return;
293*4d495c6eSApple OSS Distributions }
294*4d495c6eSApple OSS Distributions
295*4d495c6eSApple OSS Distributions static void
post_test(void)296*4d495c6eSApple OSS Distributions post_test(void)
297*4d495c6eSApple OSS Distributions {
298*4d495c6eSApple OSS Distributions #if defined(__arm64__)
299*4d495c6eSApple OSS Distributions if (panic_on_unsigned_orig == 1) {
300*4d495c6eSApple OSS Distributions T_EXPECT_POSIX_SUCCESS(sysctlbyname("vm.panic_on_unsigned_execute", NULL, 0, &panic_on_unsigned_orig, sizeof(int)),
301*4d495c6eSApple OSS Distributions "restore sysctl vm.panic_on_unsigned_execute to 1");
302*4d495c6eSApple OSS Distributions }
303*4d495c6eSApple OSS Distributions #endif
304*4d495c6eSApple OSS Distributions return;
305*4d495c6eSApple OSS Distributions }
306*4d495c6eSApple OSS Distributions
307*4d495c6eSApple OSS Distributions static void
check_executable(char * exec_path)308*4d495c6eSApple OSS Distributions check_executable(char *exec_path)
309*4d495c6eSApple OSS Distributions {
310*4d495c6eSApple OSS Distributions int ret = -1;
311*4d495c6eSApple OSS Distributions struct stat sb;
312*4d495c6eSApple OSS Distributions
313*4d495c6eSApple OSS Distributions ret = stat(exec_path, &sb);
314*4d495c6eSApple OSS Distributions T_QUIET;
315*4d495c6eSApple OSS Distributions T_ASSERT_POSIX_SUCCESS(ret, "check executable %s", exec_path);
316*4d495c6eSApple OSS Distributions T_QUIET;
317*4d495c6eSApple OSS Distributions T_ASSERT_BITS_SET(sb.st_mode, S_IXUSR, "check %s EXEC permission", exec_path);
318*4d495c6eSApple OSS Distributions }
319*4d495c6eSApple OSS Distributions
320*4d495c6eSApple OSS Distributions T_DECL(code_signing, "testing code siging with unsigned syscall code - \
321*4d495c6eSApple OSS Distributions rdar://problem/23770418", T_META_RUN_CONCURRENTLY(true),
322*4d495c6eSApple OSS Distributions T_META_IGNORECRASHES(".*vm_test_code_signing_helper.*"),
323*4d495c6eSApple OSS Distributions T_META_ENABLED(false) /* rdar://98779213 */, T_META_TAG_VM_NOT_ELIGIBLE)
324*4d495c6eSApple OSS Distributions {
325*4d495c6eSApple OSS Distributions int ret = 0;
326*4d495c6eSApple OSS Distributions int exit_code = 0;
327*4d495c6eSApple OSS Distributions int status = 0;
328*4d495c6eSApple OSS Distributions int signal = 0;
329*4d495c6eSApple OSS Distributions int timeout = 30;
330*4d495c6eSApple OSS Distributions
331*4d495c6eSApple OSS Distributions pid_t child_pid = 0;
332*4d495c6eSApple OSS Distributions bool wait_ret = true;
333*4d495c6eSApple OSS Distributions
334*4d495c6eSApple OSS Distributions char binary_path[MAXPATHLEN], *binary_dir = NULL;
335*4d495c6eSApple OSS Distributions uint32_t path_size = sizeof(binary_path);
336*4d495c6eSApple OSS Distributions
337*4d495c6eSApple OSS Distributions ret = _NSGetExecutablePath(binary_path, &path_size);
338*4d495c6eSApple OSS Distributions T_QUIET;
339*4d495c6eSApple OSS Distributions T_ASSERT_EQ(ret, 0, "_NSGetExecutablePath: %s, size: %d",
340*4d495c6eSApple OSS Distributions binary_path, path_size);
341*4d495c6eSApple OSS Distributions binary_dir = dirname(binary_path);
342*4d495c6eSApple OSS Distributions T_QUIET;
343*4d495c6eSApple OSS Distributions T_WITH_ERRNO;
344*4d495c6eSApple OSS Distributions T_ASSERT_NOTNULL(binary_dir, "get binary directory: %s", binary_dir);
345*4d495c6eSApple OSS Distributions
346*4d495c6eSApple OSS Distributions char *helper_binary = "vm_test_code_signing_helper";
347*4d495c6eSApple OSS Distributions snprintf(binary_path, MAXPATHLEN, "%s/%s", binary_dir, helper_binary);
348*4d495c6eSApple OSS Distributions check_executable(binary_path);
349*4d495c6eSApple OSS Distributions
350*4d495c6eSApple OSS Distributions char *helper_args[] = {binary_path, NULL};
351*4d495c6eSApple OSS Distributions
352*4d495c6eSApple OSS Distributions pre_test();
353*4d495c6eSApple OSS Distributions T_ATEND(post_test);
354*4d495c6eSApple OSS Distributions
355*4d495c6eSApple OSS Distributions ret = dt_launch_tool(&child_pid, helper_args, false, NULL, NULL);
356*4d495c6eSApple OSS Distributions T_ASSERT_EQ(ret, 0, "launch helper: %s", helper_binary);
357*4d495c6eSApple OSS Distributions
358*4d495c6eSApple OSS Distributions wait_ret = dt_waitpid(child_pid, &status, &signal, timeout);
359*4d495c6eSApple OSS Distributions if (wait_ret) {
360*4d495c6eSApple OSS Distributions T_LOG("helper returned: %d", status);
361*4d495c6eSApple OSS Distributions exit_code = status;
362*4d495c6eSApple OSS Distributions } else {
363*4d495c6eSApple OSS Distributions if (signal != 0) {
364*4d495c6eSApple OSS Distributions T_LOG("signal terminated helper: %d", signal);
365*4d495c6eSApple OSS Distributions exit_code = signal;
366*4d495c6eSApple OSS Distributions }
367*4d495c6eSApple OSS Distributions
368*4d495c6eSApple OSS Distributions if (status != 0) {
369*4d495c6eSApple OSS Distributions T_LOG("helper exited: %d", status);
370*4d495c6eSApple OSS Distributions exit_code = status;
371*4d495c6eSApple OSS Distributions }
372*4d495c6eSApple OSS Distributions }
373*4d495c6eSApple OSS Distributions
374*4d495c6eSApple OSS Distributions T_ASSERT_EQ(exit_code, expected_code, "helper exits: %d, expected: %d",
375*4d495c6eSApple OSS Distributions exit_code, expected_code);
376*4d495c6eSApple OSS Distributions }
377