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