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