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