1*c54f35caSApple OSS Distributions #include <stdio.h>
2*c54f35caSApple OSS Distributions #include <sys/sysctl.h>
3*c54f35caSApple OSS Distributions #include <spawn_private.h>
4*c54f35caSApple OSS Distributions #include <signal.h>
5*c54f35caSApple OSS Distributions #include <sys/reason.h>
6*c54f35caSApple OSS Distributions
7*c54f35caSApple OSS Distributions #ifdef T_NAMESPACE
8*c54f35caSApple OSS Distributions #undef T_NAMESPACE
9*c54f35caSApple OSS Distributions #endif
10*c54f35caSApple OSS Distributions #include <darwintest.h>
11*c54f35caSApple OSS Distributions #include <darwintest_utils.h>
12*c54f35caSApple OSS Distributions
13*c54f35caSApple OSS Distributions T_GLOBAL_META(
14*c54f35caSApple OSS Distributions T_META_RADAR_COMPONENT_NAME("xnu"),
15*c54f35caSApple OSS Distributions T_META_RADAR_COMPONENT_VERSION("spawn"),
16*c54f35caSApple OSS Distributions T_META_NAMESPACE("xnu.spawn"));
17*c54f35caSApple OSS Distributions
18*c54f35caSApple OSS Distributions extern char **environ;
19*c54f35caSApple OSS Distributions
20*c54f35caSApple OSS Distributions #define SYSCTL_CRASH_BEHAVIOR_TEST_MODE "kern.crash_behavior_test_mode=1"
21*c54f35caSApple OSS Distributions #define SYSCTL_CRASH_BEHAVIOR_WOULD_PANIC "kern.crash_behavior_test_would_panic"
22*c54f35caSApple OSS Distributions
23*c54f35caSApple OSS Distributions #define TEST_REASON_CODE 5
24*c54f35caSApple OSS Distributions
25*c54f35caSApple OSS Distributions static void
_do_set_crash_behavior_test(char * child_mode,int signal,uint32_t flags,bool expect_panic)26*c54f35caSApple OSS Distributions _do_set_crash_behavior_test(char *child_mode, int signal, uint32_t flags, bool expect_panic)
27*c54f35caSApple OSS Distributions {
28*c54f35caSApple OSS Distributions bool should_wait = (strcmp(child_mode, "wait") == 0);
29*c54f35caSApple OSS Distributions bool reason = (strcmp(child_mode, "reason") == 0);
30*c54f35caSApple OSS Distributions bool dirty = (strcmp(child_mode, "dirty") == 0);
31*c54f35caSApple OSS Distributions bool shutdown = (strcmp(child_mode, "clean") == 0) || dirty;
32*c54f35caSApple OSS Distributions uint64_t deadline = mach_continuous_time();
33*c54f35caSApple OSS Distributions
34*c54f35caSApple OSS Distributions // 0. clear SYSCTL_CRASH_BEHAVIOR_WOULD_PANIC
35*c54f35caSApple OSS Distributions int would_panic = 0;
36*c54f35caSApple OSS Distributions size_t length = sizeof(would_panic);
37*c54f35caSApple OSS Distributions int ret = sysctlbyname(SYSCTL_CRASH_BEHAVIOR_WOULD_PANIC, NULL, 0, &would_panic, length);
38*c54f35caSApple OSS Distributions T_ASSERT_POSIX_SUCCESS(ret, "Clearing SYSCTL_CRASH_BEHAVIOR_WOULD_PANIC");
39*c54f35caSApple OSS Distributions
40*c54f35caSApple OSS Distributions // 1. posix_spawn a child process
41*c54f35caSApple OSS Distributions char *test_program = "./posix_spawnattr_set_crash_behavior_np_child";
42*c54f35caSApple OSS Distributions char *child_args[3];
43*c54f35caSApple OSS Distributions
44*c54f35caSApple OSS Distributions posix_spawnattr_t attrs;
45*c54f35caSApple OSS Distributions posix_spawnattr_init(&attrs);
46*c54f35caSApple OSS Distributions
47*c54f35caSApple OSS Distributions ret = posix_spawnattr_set_crash_behavior_np(&attrs, flags);
48*c54f35caSApple OSS Distributions T_ASSERT_POSIX_ZERO(ret, "posix_spawnattr_set_crash_behavior_np");
49*c54f35caSApple OSS Distributions
50*c54f35caSApple OSS Distributions
51*c54f35caSApple OSS Distributions if (should_wait) {
52*c54f35caSApple OSS Distributions // For the purpose of the test we set the deadline to be now to avoid
53*c54f35caSApple OSS Distributions // making the test wait
54*c54f35caSApple OSS Distributions ret = posix_spawnattr_set_crash_behavior_deadline_np(&attrs, deadline, flags);
55*c54f35caSApple OSS Distributions T_ASSERT_POSIX_ZERO(ret, "posix_spawnattr_set_crash_behavior_deadline_np: %lld", deadline);
56*c54f35caSApple OSS Distributions }
57*c54f35caSApple OSS Distributions
58*c54f35caSApple OSS Distributions child_args[0] = test_program;
59*c54f35caSApple OSS Distributions child_args[1] = child_mode;
60*c54f35caSApple OSS Distributions child_args[2] = NULL;
61*c54f35caSApple OSS Distributions
62*c54f35caSApple OSS Distributions pid_t child_pid = 0;
63*c54f35caSApple OSS Distributions ret = posix_spawn(&child_pid, child_args[0], NULL, &attrs, &child_args[0], environ);
64*c54f35caSApple OSS Distributions T_ASSERT_POSIX_ZERO(ret, "posix_spawn");
65*c54f35caSApple OSS Distributions posix_spawnattr_destroy(&attrs);
66*c54f35caSApple OSS Distributions
67*c54f35caSApple OSS Distributions if (should_wait) {
68*c54f35caSApple OSS Distributions while (mach_continuous_time() <= deadline) {
69*c54f35caSApple OSS Distributions usleep(1);
70*c54f35caSApple OSS Distributions }
71*c54f35caSApple OSS Distributions }
72*c54f35caSApple OSS Distributions
73*c54f35caSApple OSS Distributions if (signal != 0) {
74*c54f35caSApple OSS Distributions ret = kill(child_pid, signal);
75*c54f35caSApple OSS Distributions T_ASSERT_POSIX_SUCCESS(ret, "kill(%d, %d)", child_pid, signal);
76*c54f35caSApple OSS Distributions }
77*c54f35caSApple OSS Distributions
78*c54f35caSApple OSS Distributions if (reason) {
79*c54f35caSApple OSS Distributions ret = terminate_with_reason(child_pid, OS_REASON_TEST, TEST_REASON_CODE,
80*c54f35caSApple OSS Distributions "Test forcing crash", OS_REASON_FLAG_CONSISTENT_FAILURE | OS_REASON_FLAG_NO_CRASH_REPORT);
81*c54f35caSApple OSS Distributions T_ASSERT_POSIX_SUCCESS(ret, "terminate_with_reason(%d)", child_pid);
82*c54f35caSApple OSS Distributions }
83*c54f35caSApple OSS Distributions
84*c54f35caSApple OSS Distributions if (dirty) {
85*c54f35caSApple OSS Distributions ret = proc_set_dirty(child_pid, true);
86*c54f35caSApple OSS Distributions T_ASSERT_POSIX_SUCCESS(ret, "proc_set_dirty(%d)", child_pid);
87*c54f35caSApple OSS Distributions }
88*c54f35caSApple OSS Distributions
89*c54f35caSApple OSS Distributions if (shutdown) {
90*c54f35caSApple OSS Distributions ret = proc_terminate(child_pid, &signal);
91*c54f35caSApple OSS Distributions T_ASSERT_POSIX_SUCCESS(ret, "proc_terminate(%d, %d)", child_pid, signal);
92*c54f35caSApple OSS Distributions }
93*c54f35caSApple OSS Distributions
94*c54f35caSApple OSS Distributions // 2. Wait for the child to exit
95*c54f35caSApple OSS Distributions int child_status;
96*c54f35caSApple OSS Distributions ret = wait4(-1, &child_status, 0, NULL);
97*c54f35caSApple OSS Distributions T_ASSERT_POSIX_SUCCESS(ret, "wait4");
98*c54f35caSApple OSS Distributions
99*c54f35caSApple OSS Distributions // 3. Check if we would have panic'ed
100*c54f35caSApple OSS Distributions would_panic = 0;
101*c54f35caSApple OSS Distributions length = sizeof(would_panic);
102*c54f35caSApple OSS Distributions ret = sysctlbyname(SYSCTL_CRASH_BEHAVIOR_WOULD_PANIC, &would_panic, &length, NULL, 0);
103*c54f35caSApple OSS Distributions T_ASSERT_POSIX_SUCCESS(ret, "SYSCTL_CRASH_BEHAVIOR_WOULD_PANIC");
104*c54f35caSApple OSS Distributions
105*c54f35caSApple OSS Distributions T_EXPECT_EQ(would_panic, expect_panic, NULL);
106*c54f35caSApple OSS Distributions }
107*c54f35caSApple OSS Distributions
108*c54f35caSApple OSS Distributions T_DECL(set_crash_behavior_panic_on_crash_with_crash,
109*c54f35caSApple OSS Distributions "set_crash_behavior_panic_on_crash_with_crash",
110*c54f35caSApple OSS Distributions T_META_SYSCTL_INT(SYSCTL_CRASH_BEHAVIOR_TEST_MODE),
111*c54f35caSApple OSS Distributions T_META_REQUIRES_SYSCTL_EQ("kern.development", 1)) {
112*c54f35caSApple OSS Distributions _do_set_crash_behavior_test("crash", 0, POSIX_SPAWN_PANIC_ON_CRASH, true);
113*c54f35caSApple OSS Distributions }
114*c54f35caSApple OSS Distributions
115*c54f35caSApple OSS Distributions T_DECL(set_crash_behavior_panic_on_crash_with_exit,
116*c54f35caSApple OSS Distributions "set_crash_behavior_panic_on_crash_with_exit",
117*c54f35caSApple OSS Distributions T_META_SYSCTL_INT(SYSCTL_CRASH_BEHAVIOR_TEST_MODE),
118*c54f35caSApple OSS Distributions T_META_REQUIRES_SYSCTL_EQ("kern.development", 1)) {
119*c54f35caSApple OSS Distributions _do_set_crash_behavior_test("exit", 0, POSIX_SPAWN_PANIC_ON_CRASH, false);
120*c54f35caSApple OSS Distributions }
121*c54f35caSApple OSS Distributions
122*c54f35caSApple OSS Distributions T_DECL(set_crash_behavior_panic_on_crash_with_success,
123*c54f35caSApple OSS Distributions "set_crash_behavior_panic_on_crash_with_success",
124*c54f35caSApple OSS Distributions T_META_SYSCTL_INT(SYSCTL_CRASH_BEHAVIOR_TEST_MODE),
125*c54f35caSApple OSS Distributions T_META_REQUIRES_SYSCTL_EQ("kern.development", 1)) {
126*c54f35caSApple OSS Distributions _do_set_crash_behavior_test("success", 0, POSIX_SPAWN_PANIC_ON_CRASH, false);
127*c54f35caSApple OSS Distributions }
128*c54f35caSApple OSS Distributions
129*c54f35caSApple OSS Distributions T_DECL(set_crash_behavior_panic_on_nonzero_with_crash,
130*c54f35caSApple OSS Distributions "set_crash_behavior_panic_on_nonzero_with_crash",
131*c54f35caSApple OSS Distributions T_META_SYSCTL_INT(SYSCTL_CRASH_BEHAVIOR_TEST_MODE),
132*c54f35caSApple OSS Distributions T_META_REQUIRES_SYSCTL_EQ("kern.development", 1)) {
133*c54f35caSApple OSS Distributions _do_set_crash_behavior_test("crash", 0, POSIX_SPAWN_PANIC_ON_NON_ZERO_EXIT, false);
134*c54f35caSApple OSS Distributions }
135*c54f35caSApple OSS Distributions
136*c54f35caSApple OSS Distributions T_DECL(set_crash_behavior_panic_on_nonzero_with_exit,
137*c54f35caSApple OSS Distributions "set_crash_behavior_panic_on_nonzero_with_exit",
138*c54f35caSApple OSS Distributions T_META_SYSCTL_INT(SYSCTL_CRASH_BEHAVIOR_TEST_MODE),
139*c54f35caSApple OSS Distributions T_META_REQUIRES_SYSCTL_EQ("kern.development", 1)) {
140*c54f35caSApple OSS Distributions _do_set_crash_behavior_test("exit", 0, POSIX_SPAWN_PANIC_ON_NON_ZERO_EXIT, true);
141*c54f35caSApple OSS Distributions }
142*c54f35caSApple OSS Distributions
143*c54f35caSApple OSS Distributions T_DECL(set_crash_behavior_panic_on_nonzero_with_success,
144*c54f35caSApple OSS Distributions "set_crash_behavior_panic_on_nonzero_with_success",
145*c54f35caSApple OSS Distributions T_META_SYSCTL_INT(SYSCTL_CRASH_BEHAVIOR_TEST_MODE),
146*c54f35caSApple OSS Distributions T_META_REQUIRES_SYSCTL_EQ("kern.development", 1)) {
147*c54f35caSApple OSS Distributions _do_set_crash_behavior_test("success", 0, POSIX_SPAWN_PANIC_ON_NON_ZERO_EXIT, false);
148*c54f35caSApple OSS Distributions }
149*c54f35caSApple OSS Distributions
150*c54f35caSApple OSS Distributions T_DECL(set_crash_behavior_panic_on_crash_cancelled,
151*c54f35caSApple OSS Distributions "set_crash_behavior_panic_on_crash_cancelled",
152*c54f35caSApple OSS Distributions T_META_SYSCTL_INT(SYSCTL_CRASH_BEHAVIOR_TEST_MODE),
153*c54f35caSApple OSS Distributions T_META_REQUIRES_SYSCTL_EQ("kern.development", 1)) {
154*c54f35caSApple OSS Distributions _do_set_crash_behavior_test("wait", SIGUSR1, POSIX_SPAWN_PANIC_ON_CRASH, false);
155*c54f35caSApple OSS Distributions }
156*c54f35caSApple OSS Distributions
157*c54f35caSApple OSS Distributions T_DECL(set_crash_behavior_panic_on_crash_sigterm,
158*c54f35caSApple OSS Distributions "set_crash_behavior_panic_on_crash_sigterm",
159*c54f35caSApple OSS Distributions T_META_SYSCTL_INT(SYSCTL_CRASH_BEHAVIOR_TEST_MODE),
160*c54f35caSApple OSS Distributions T_META_REQUIRES_SYSCTL_EQ("kern.development", 1)) {
161*c54f35caSApple OSS Distributions _do_set_crash_behavior_test("spin", SIGTERM, POSIX_SPAWN_PANIC_ON_CRASH, false);
162*c54f35caSApple OSS Distributions }
163*c54f35caSApple OSS Distributions
164*c54f35caSApple OSS Distributions T_DECL(set_crash_behavior_panic_on_crash_sigkill,
165*c54f35caSApple OSS Distributions "set_crash_behavior_panic_on_crash_sigkill",
166*c54f35caSApple OSS Distributions T_META_SYSCTL_INT(SYSCTL_CRASH_BEHAVIOR_TEST_MODE),
167*c54f35caSApple OSS Distributions T_META_REQUIRES_SYSCTL_EQ("kern.development", 1)) {
168*c54f35caSApple OSS Distributions _do_set_crash_behavior_test("spin", SIGKILL, POSIX_SPAWN_PANIC_ON_CRASH, false);
169*c54f35caSApple OSS Distributions }
170*c54f35caSApple OSS Distributions
171*c54f35caSApple OSS Distributions T_DECL(set_crash_behavior_panic_on_crash_terminate_with_reason,
172*c54f35caSApple OSS Distributions "set_crash_behavior_panic_on_crash_terminate_with_reason",
173*c54f35caSApple OSS Distributions T_META_SYSCTL_INT(SYSCTL_CRASH_BEHAVIOR_TEST_MODE),
174*c54f35caSApple OSS Distributions T_META_REQUIRES_SYSCTL_EQ("kern.development", 1)) {
175*c54f35caSApple OSS Distributions _do_set_crash_behavior_test("reason", 0, POSIX_SPAWN_PANIC_ON_CRASH, true);
176*c54f35caSApple OSS Distributions }
177*c54f35caSApple OSS Distributions
178*c54f35caSApple OSS Distributions T_DECL(set_crash_behavior_panic_on_crash_proc_terminate_clean,
179*c54f35caSApple OSS Distributions "set_crash_behavior_panic_on_crash_proc_terminate_clean",
180*c54f35caSApple OSS Distributions T_META_SYSCTL_INT(SYSCTL_CRASH_BEHAVIOR_TEST_MODE),
181*c54f35caSApple OSS Distributions T_META_REQUIRES_SYSCTL_EQ("kern.development", 1)) {
182*c54f35caSApple OSS Distributions _do_set_crash_behavior_test("clean", 0, POSIX_SPAWN_PANIC_ON_CRASH, false);
183*c54f35caSApple OSS Distributions }
184*c54f35caSApple OSS Distributions
185*c54f35caSApple OSS Distributions T_DECL(set_crash_behavior_panic_on_crash_proc_terminate_dirty,
186*c54f35caSApple OSS Distributions "set_crash_behavior_panic_on_crash_proc_terminate_dirty",
187*c54f35caSApple OSS Distributions T_META_SYSCTL_INT(SYSCTL_CRASH_BEHAVIOR_TEST_MODE),
188*c54f35caSApple OSS Distributions T_META_REQUIRES_SYSCTL_EQ("kern.development", 1)) {
189*c54f35caSApple OSS Distributions _do_set_crash_behavior_test("dirty", 0, POSIX_SPAWN_PANIC_ON_CRASH, false);
190*c54f35caSApple OSS Distributions }
191