1 #include <darwintest.h>
2 
3 #include <errno.h>
4 #include <libproc.h>
5 #include <signal.h>
6 #include <spawn.h>
7 #include <spawn_private.h>
8 #include <sys/spawn_internal.h>
9 #include <stdbool.h>
10 #include <stdint.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <sys/kauth.h>
15 #include <sys/proc_info.h>
16 #include <sys/sysctl.h>
17 #include <sysexits.h>
18 #include <unistd.h>
19 #include <kern/cs_blobs.h>
20 #include <sys/codesign.h>
21 
22 T_GLOBAL_META(T_META_RUN_CONCURRENTLY(true),
23     T_META_RADAR_COMPONENT_NAME("xnu"),
24     T_META_RADAR_COMPONENT_VERSION("codesigning"));
25 
26 T_DECL(cs_launch_type_t, "Check posix_spawnattr for launch type",
27     T_META_ASROOT(true))
28 {
29 	posix_spawnattr_t attr;
30 	int ret;
31 
32 	ret = posix_spawnattr_init(&attr);
33 	T_QUIET;
34 	T_ASSERT_POSIX_ZERO(ret, "posix_spawnattr_init");
35 
36 	ret = posix_spawnattr_set_launch_type_np(&attr, CS_LAUNCH_TYPE_SYSTEM_SERVICE);
37 	T_QUIET;
38 	T_ASSERT_POSIX_ZERO(ret, "posix_spawnattr_set_launch_type_np");
39 
40 
41 	char * const    prog = "/bin/ls";
42 	char * const    argv_child[] = { prog,
43 		                         NULL, };
44 	pid_t           child_pid;
45 	extern char   **environ;
46 
47 	ret = posix_spawn(&child_pid, prog, NULL, &attr, argv_child, environ);
48 	T_ASSERT_POSIX_ZERO(ret, "posix_spawn");
49 
50 	T_LOG("parent: spawned child with pid %d\n", child_pid);
51 
52 	ret = posix_spawnattr_destroy(&attr);
53 	T_QUIET;
54 	T_ASSERT_POSIX_ZERO(ret, "posix_spawnattr_destroy");
55 
56 	T_LOG("parent: waiting for child process");
57 
58 	int status = 0;
59 	int waitpid_result = waitpid(child_pid, &status, 0);
60 	T_ASSERT_EQ(waitpid_result, child_pid, "waitpid should return child we spawned");
61 	T_ASSERT_EQ(WIFEXITED(status), 1, "child should have exited normally");
62 	T_ASSERT_EQ(WEXITSTATUS(status), EX_OK, "child should have exited with success");
63 }
64