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