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