xref: /xnu-12377.1.9/tests/signal_exit_reason.c (revision f6217f891ac0bb64f3d375211650a4c1ff8ca1ea) !
1*f6217f89SApple OSS Distributions /*
2*f6217f89SApple OSS Distributions  * Copyright (c) 2023 Apple Inc. All rights reserved.
3*f6217f89SApple OSS Distributions  *
4*f6217f89SApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5*f6217f89SApple OSS Distributions  *
6*f6217f89SApple OSS Distributions  * This file contains Original Code and/or Modifications of Original Code
7*f6217f89SApple OSS Distributions  * as defined in and that are subject to the Apple Public Source License
8*f6217f89SApple OSS Distributions  * Version 2.0 (the 'License'). You may not use this file except in
9*f6217f89SApple OSS Distributions  * compliance with the License. The rights granted to you under the License
10*f6217f89SApple OSS Distributions  * may not be used to create, or enable the creation or redistribution of,
11*f6217f89SApple OSS Distributions  * unlawful or unlicensed copies of an Apple operating system, or to
12*f6217f89SApple OSS Distributions  * circumvent, violate, or enable the circumvention or violation of, any
13*f6217f89SApple OSS Distributions  * terms of an Apple operating system software license agreement.
14*f6217f89SApple OSS Distributions  *
15*f6217f89SApple OSS Distributions  * Please obtain a copy of the License at
16*f6217f89SApple OSS Distributions  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17*f6217f89SApple OSS Distributions  *
18*f6217f89SApple OSS Distributions  * The Original Code and all software distributed under the License are
19*f6217f89SApple OSS Distributions  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20*f6217f89SApple OSS Distributions  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21*f6217f89SApple OSS Distributions  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22*f6217f89SApple OSS Distributions  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23*f6217f89SApple OSS Distributions  * Please see the License for the specific language governing rights and
24*f6217f89SApple OSS Distributions  * limitations under the License.
25*f6217f89SApple OSS Distributions  *
26*f6217f89SApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27*f6217f89SApple OSS Distributions  */
28*f6217f89SApple OSS Distributions 
29*f6217f89SApple OSS Distributions /*
30*f6217f89SApple OSS Distributions  * These tests verify that proc_pidinfo returns the expected exit reason and
31*f6217f89SApple OSS Distributions  * namespace for signal-related process termination.
32*f6217f89SApple OSS Distributions  */
33*f6217f89SApple OSS Distributions 
34*f6217f89SApple OSS Distributions #include <darwintest.h>
35*f6217f89SApple OSS Distributions #include <signal.h>
36*f6217f89SApple OSS Distributions #include <libproc.h>
37*f6217f89SApple OSS Distributions #include <sys/wait.h>
38*f6217f89SApple OSS Distributions #include <sys/reason.h>
39*f6217f89SApple OSS Distributions #include <stdlib.h>
40*f6217f89SApple OSS Distributions #include <dispatch/dispatch.h>
41*f6217f89SApple OSS Distributions #include <unistd.h>
42*f6217f89SApple OSS Distributions #include <mach/kern_return.h>
43*f6217f89SApple OSS Distributions #include <mach/mach.h>
44*f6217f89SApple OSS Distributions #include <mach/mach_port.h>
45*f6217f89SApple OSS Distributions #include <mach/message.h>
46*f6217f89SApple OSS Distributions #include <mach/port.h>
47*f6217f89SApple OSS Distributions 
48*f6217f89SApple OSS Distributions 
49*f6217f89SApple OSS Distributions T_GLOBAL_META(
50*f6217f89SApple OSS Distributions 	T_META_NAMESPACE("xnu.misc"),
51*f6217f89SApple OSS Distributions 	T_META_RADAR_COMPONENT_NAME("xnu"),
52*f6217f89SApple OSS Distributions 	T_META_RADAR_COMPONENT_VERSION("misc"),
53*f6217f89SApple OSS Distributions 	T_META_RUN_CONCURRENTLY(true));
54*f6217f89SApple OSS Distributions 
55*f6217f89SApple OSS Distributions static dispatch_queue_t exit_queue;
56*f6217f89SApple OSS Distributions 
57*f6217f89SApple OSS Distributions static void
cleanup(void)58*f6217f89SApple OSS Distributions cleanup(void)
59*f6217f89SApple OSS Distributions {
60*f6217f89SApple OSS Distributions 	dispatch_release(exit_queue);
61*f6217f89SApple OSS Distributions }
62*f6217f89SApple OSS Distributions 
63*f6217f89SApple OSS Distributions static void
64*f6217f89SApple OSS Distributions dispatch_test(void (^test)(void))
65*f6217f89SApple OSS Distributions {
66*f6217f89SApple OSS Distributions 	// Use dispatch to schedule DISPATCH_PROC_EXIT blocks to read out exit reasons
67*f6217f89SApple OSS Distributions 	exit_queue = dispatch_queue_create("exit queue", DISPATCH_QUEUE_SERIAL);
68*f6217f89SApple OSS Distributions 	dispatch_async(dispatch_get_main_queue(), ^{
69*f6217f89SApple OSS Distributions 		test();
70*f6217f89SApple OSS Distributions 	});
71*f6217f89SApple OSS Distributions 	T_ATEND(cleanup);
72*f6217f89SApple OSS Distributions 	dispatch_main();
73*f6217f89SApple OSS Distributions }
74*f6217f89SApple OSS Distributions 
75*f6217f89SApple OSS Distributions static bool
audit_token_for_pid(pid_t pid,audit_token_t * token)76*f6217f89SApple OSS Distributions audit_token_for_pid(pid_t pid, audit_token_t *token)
77*f6217f89SApple OSS Distributions {
78*f6217f89SApple OSS Distributions 	kern_return_t err;
79*f6217f89SApple OSS Distributions 	task_name_t task_name = TASK_NAME_NULL;
80*f6217f89SApple OSS Distributions 	mach_msg_type_number_t info_size = TASK_AUDIT_TOKEN_COUNT;
81*f6217f89SApple OSS Distributions 
82*f6217f89SApple OSS Distributions 	err = task_name_for_pid(mach_task_self(), pid, &task_name);
83*f6217f89SApple OSS Distributions 	if (err != KERN_SUCCESS) {
84*f6217f89SApple OSS Distributions 		T_LOG("task_for_pid returned %d\n", err);
85*f6217f89SApple OSS Distributions 		return false;
86*f6217f89SApple OSS Distributions 	}
87*f6217f89SApple OSS Distributions 
88*f6217f89SApple OSS Distributions 	err = task_info(task_name, TASK_AUDIT_TOKEN, (integer_t *)token, &info_size);
89*f6217f89SApple OSS Distributions 	if (err != KERN_SUCCESS) {
90*f6217f89SApple OSS Distributions 		T_LOG("task_info returned %d\n", err);
91*f6217f89SApple OSS Distributions 		return false;
92*f6217f89SApple OSS Distributions 	}
93*f6217f89SApple OSS Distributions 
94*f6217f89SApple OSS Distributions 	return true;
95*f6217f89SApple OSS Distributions }
96*f6217f89SApple OSS Distributions 
97*f6217f89SApple OSS Distributions static void
check_exit_reason(int pid,uint64_t expected_reason_namespace,uint64_t expected_signal)98*f6217f89SApple OSS Distributions check_exit_reason(int pid, uint64_t expected_reason_namespace, uint64_t expected_signal)
99*f6217f89SApple OSS Distributions {
100*f6217f89SApple OSS Distributions 	T_LOG("check_exit_reason %d", expected_signal);
101*f6217f89SApple OSS Distributions 	int ret, status;
102*f6217f89SApple OSS Distributions 	struct proc_exitreasonbasicinfo exit_reason;
103*f6217f89SApple OSS Distributions 
104*f6217f89SApple OSS Distributions 	ret = proc_pidinfo(pid, PROC_PIDEXITREASONBASICINFO, 1, &exit_reason, PROC_PIDEXITREASONBASICINFOSIZE);
105*f6217f89SApple OSS Distributions 	T_WITH_ERRNO; T_QUIET; T_ASSERT_EQ(ret, PROC_PIDEXITREASONBASICINFOSIZE, "retrieve basic exit reason info");
106*f6217f89SApple OSS Distributions 
107*f6217f89SApple OSS Distributions 	waitpid(pid, &status, 0);
108*f6217f89SApple OSS Distributions 	T_QUIET; T_EXPECT_FALSE(WIFEXITED(status), "process did not exit normally");
109*f6217f89SApple OSS Distributions 	T_QUIET; T_EXPECT_TRUE(WIFSIGNALED(status), "process was terminated because of a signal");
110*f6217f89SApple OSS Distributions 	T_QUIET; T_EXPECT_EQ(WTERMSIG(status), expected_signal, "process should terminate due to signal %llu", expected_signal);
111*f6217f89SApple OSS Distributions 
112*f6217f89SApple OSS Distributions 	T_EXPECT_EQ(exit_reason.beri_namespace, expected_reason_namespace, "expect OS_REASON_SIGNAL");
113*f6217f89SApple OSS Distributions 	T_EXPECT_EQ(exit_reason.beri_code, expected_signal, "expect reason code: %llu", expected_signal);
114*f6217f89SApple OSS Distributions }
115*f6217f89SApple OSS Distributions 
116*f6217f89SApple OSS Distributions static void
wait_collect_exit_reason(int pid,int signal)117*f6217f89SApple OSS Distributions wait_collect_exit_reason(int pid, int signal)
118*f6217f89SApple OSS Distributions {
119*f6217f89SApple OSS Distributions 	dispatch_source_t ds_proc = dispatch_source_create(DISPATCH_SOURCE_TYPE_PROC, pid, DISPATCH_PROC_EXIT, exit_queue);
120*f6217f89SApple OSS Distributions 	dispatch_semaphore_t sem = dispatch_semaphore_create(0);
121*f6217f89SApple OSS Distributions 	dispatch_source_set_event_handler(ds_proc, ^{
122*f6217f89SApple OSS Distributions 		check_exit_reason(pid, OS_REASON_SIGNAL, signal);
123*f6217f89SApple OSS Distributions 		dispatch_semaphore_signal(sem);
124*f6217f89SApple OSS Distributions 	});
125*f6217f89SApple OSS Distributions 	dispatch_activate(ds_proc);
126*f6217f89SApple OSS Distributions 
127*f6217f89SApple OSS Distributions 	// Wait till exit reason is processed
128*f6217f89SApple OSS Distributions 	dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
129*f6217f89SApple OSS Distributions 	dispatch_release(ds_proc);
130*f6217f89SApple OSS Distributions 	dispatch_release(sem);
131*f6217f89SApple OSS Distributions }
132*f6217f89SApple OSS Distributions 
133*f6217f89SApple OSS Distributions static void
wait_with_timeout_expected(int pid,int seconds)134*f6217f89SApple OSS Distributions wait_with_timeout_expected(int pid, int seconds)
135*f6217f89SApple OSS Distributions {
136*f6217f89SApple OSS Distributions 	long timeout = 0;
137*f6217f89SApple OSS Distributions 	dispatch_source_t ds_proc = dispatch_source_create(DISPATCH_SOURCE_TYPE_PROC, pid, DISPATCH_PROC_EXIT, exit_queue);
138*f6217f89SApple OSS Distributions 	dispatch_semaphore_t sem = dispatch_semaphore_create(0);
139*f6217f89SApple OSS Distributions 	dispatch_time_t milestone = dispatch_time(DISPATCH_TIME_NOW, seconds * NSEC_PER_SEC);;
140*f6217f89SApple OSS Distributions 	dispatch_source_set_event_handler(ds_proc, ^{
141*f6217f89SApple OSS Distributions 		dispatch_semaphore_signal(sem);
142*f6217f89SApple OSS Distributions 	});
143*f6217f89SApple OSS Distributions 	dispatch_activate(ds_proc);
144*f6217f89SApple OSS Distributions 
145*f6217f89SApple OSS Distributions 	// Wait till exit reason is processed or timeout
146*f6217f89SApple OSS Distributions 	timeout = dispatch_semaphore_wait(sem, milestone);
147*f6217f89SApple OSS Distributions 	T_QUIET; T_EXPECT_TRUE(timeout != 0, "process exited and was not expected to");
148*f6217f89SApple OSS Distributions 	dispatch_release(ds_proc);
149*f6217f89SApple OSS Distributions 	dispatch_release(sem);
150*f6217f89SApple OSS Distributions }
151*f6217f89SApple OSS Distributions 
152*f6217f89SApple OSS Distributions static void
__test_exit_reason_abort()153*f6217f89SApple OSS Distributions __test_exit_reason_abort()
154*f6217f89SApple OSS Distributions {
155*f6217f89SApple OSS Distributions 	pid_t child = fork();
156*f6217f89SApple OSS Distributions 	if (child > 0) {
157*f6217f89SApple OSS Distributions 		wait_collect_exit_reason(child, SIGABRT);
158*f6217f89SApple OSS Distributions 	} else {
159*f6217f89SApple OSS Distributions 		abort();
160*f6217f89SApple OSS Distributions 	}
161*f6217f89SApple OSS Distributions }
162*f6217f89SApple OSS Distributions 
163*f6217f89SApple OSS Distributions T_DECL(test_exit_reason_abort, "tests exit reason for abort()", T_META_TAG_VM_PREFERRED)
164*f6217f89SApple OSS Distributions {
165*f6217f89SApple OSS Distributions 	dispatch_test(^{
166*f6217f89SApple OSS Distributions 		__test_exit_reason_abort();
167*f6217f89SApple OSS Distributions 		T_END;
168*f6217f89SApple OSS Distributions 	});
169*f6217f89SApple OSS Distributions }
170*f6217f89SApple OSS Distributions 
171*f6217f89SApple OSS Distributions static void
__test_exit_reason_external_signal(int signal)172*f6217f89SApple OSS Distributions __test_exit_reason_external_signal(int signal)
173*f6217f89SApple OSS Distributions {
174*f6217f89SApple OSS Distributions 	T_LOG("Testing external signal %d", signal);
175*f6217f89SApple OSS Distributions 	pid_t child = fork();
176*f6217f89SApple OSS Distributions 	if (child > 0) {
177*f6217f89SApple OSS Distributions 		// Send external signal
178*f6217f89SApple OSS Distributions 		kill(child, signal);
179*f6217f89SApple OSS Distributions 		wait_collect_exit_reason(child, signal);
180*f6217f89SApple OSS Distributions 	} else {
181*f6217f89SApple OSS Distributions 		pause();
182*f6217f89SApple OSS Distributions 	}
183*f6217f89SApple OSS Distributions }
184*f6217f89SApple OSS Distributions 
185*f6217f89SApple OSS Distributions static void
__test_exit_reason_delegate_signal(int signal)186*f6217f89SApple OSS Distributions __test_exit_reason_delegate_signal(int signal)
187*f6217f89SApple OSS Distributions {
188*f6217f89SApple OSS Distributions 	int ret = 0;
189*f6217f89SApple OSS Distributions 	audit_token_t instigator = INVALID_AUDIT_TOKEN_VALUE;
190*f6217f89SApple OSS Distributions 	audit_token_t token = INVALID_AUDIT_TOKEN_VALUE;
191*f6217f89SApple OSS Distributions 	pid_t child = fork();
192*f6217f89SApple OSS Distributions 	if (child > 0) {
193*f6217f89SApple OSS Distributions 		audit_token_for_pid(getpid(), &instigator);
194*f6217f89SApple OSS Distributions 		audit_token_for_pid(child, &token);
195*f6217f89SApple OSS Distributions 		// Send signal to the child with its audit token
196*f6217f89SApple OSS Distributions 		ret = proc_signal_delegate(instigator, token, signal);
197*f6217f89SApple OSS Distributions 		T_EXPECT_EQ_INT(ret, 0, "expect proc_signal_delegate return: %d", ret);
198*f6217f89SApple OSS Distributions 		wait_collect_exit_reason(child, signal);
199*f6217f89SApple OSS Distributions 		// Send signal to the child with its audit token who has exited by now
200*f6217f89SApple OSS Distributions 		ret = proc_signal_delegate(instigator, token, signal);
201*f6217f89SApple OSS Distributions 		T_EXPECT_EQ_INT(ret, ESRCH, "expect no such process return: %d", ret);
202*f6217f89SApple OSS Distributions 	} else {
203*f6217f89SApple OSS Distributions 		pause();
204*f6217f89SApple OSS Distributions 		// This exit should not hit, but we exit abnormally in case something went wrong
205*f6217f89SApple OSS Distributions 		_exit(-1);
206*f6217f89SApple OSS Distributions 	}
207*f6217f89SApple OSS Distributions }
208*f6217f89SApple OSS Distributions 
209*f6217f89SApple OSS Distributions static void
__test_exit_reason_delegate_terminate()210*f6217f89SApple OSS Distributions __test_exit_reason_delegate_terminate()
211*f6217f89SApple OSS Distributions {
212*f6217f89SApple OSS Distributions 	int ret = 0;
213*f6217f89SApple OSS Distributions 	audit_token_t instigator = INVALID_AUDIT_TOKEN_VALUE;
214*f6217f89SApple OSS Distributions 	audit_token_t token = INVALID_AUDIT_TOKEN_VALUE;
215*f6217f89SApple OSS Distributions 	pid_t child = fork();
216*f6217f89SApple OSS Distributions 	int sentsignal = 0;
217*f6217f89SApple OSS Distributions 	if (child > 0) {
218*f6217f89SApple OSS Distributions 		audit_token_for_pid(getpid(), &instigator);
219*f6217f89SApple OSS Distributions 		audit_token_for_pid(child, &token);
220*f6217f89SApple OSS Distributions 		// Send signal to the child with its audit token
221*f6217f89SApple OSS Distributions 		ret = proc_terminate_delegate(instigator, token, &sentsignal);
222*f6217f89SApple OSS Distributions 		T_EXPECT_EQ_INT(ret, 0, "expect proc_terminate_delegate return: %d", ret);
223*f6217f89SApple OSS Distributions 		T_EXPECT_TRUE(sentsignal == SIGTERM || sentsignal == SIGKILL, "sentsignal retval %d", sentsignal);
224*f6217f89SApple OSS Distributions 		wait_collect_exit_reason(child, SIGTERM);
225*f6217f89SApple OSS Distributions 		// Send signal to the child with its audit token who has exited by now
226*f6217f89SApple OSS Distributions 		ret = proc_terminate_delegate(instigator, token, &sentsignal);
227*f6217f89SApple OSS Distributions 		T_EXPECT_EQ_INT(ret, ESRCH, "expect no such process return: %d", ret);
228*f6217f89SApple OSS Distributions 		// Terminating PID 1 should fail with EPERM
229*f6217f89SApple OSS Distributions 		if (audit_token_for_pid(1, &token)) {
230*f6217f89SApple OSS Distributions 			ret = proc_terminate_delegate(instigator, token, &sentsignal);
231*f6217f89SApple OSS Distributions 			T_EXPECT_EQ_INT(ret, EPERM, "expected eperm return: %d", ret);
232*f6217f89SApple OSS Distributions 		}
233*f6217f89SApple OSS Distributions 	} else {
234*f6217f89SApple OSS Distributions 		pause();
235*f6217f89SApple OSS Distributions 		// This exit should not hit, but we exit abnormally in case something went wrong
236*f6217f89SApple OSS Distributions 		_exit(-1);
237*f6217f89SApple OSS Distributions 	}
238*f6217f89SApple OSS Distributions }
239*f6217f89SApple OSS Distributions 
240*f6217f89SApple OSS Distributions static void
__test_exit_reason_terminate()241*f6217f89SApple OSS Distributions __test_exit_reason_terminate()
242*f6217f89SApple OSS Distributions {
243*f6217f89SApple OSS Distributions 	int ret = 0;
244*f6217f89SApple OSS Distributions 	pid_t child = fork();
245*f6217f89SApple OSS Distributions 	int sentsignal = 0;
246*f6217f89SApple OSS Distributions 	if (child > 0) {
247*f6217f89SApple OSS Distributions 		// Send signal to the child with its audit token
248*f6217f89SApple OSS Distributions 		ret = proc_terminate(child, &sentsignal);
249*f6217f89SApple OSS Distributions 		T_EXPECT_EQ_INT(ret, 0, "expect proc_terminate_delegate return: %d", ret);
250*f6217f89SApple OSS Distributions 		T_EXPECT_TRUE(sentsignal == SIGTERM || sentsignal == SIGKILL, "sentsignal retval %d", sentsignal);
251*f6217f89SApple OSS Distributions 		wait_collect_exit_reason(child, SIGTERM);
252*f6217f89SApple OSS Distributions 		// Send signal to the child with its audit token who has exited by now
253*f6217f89SApple OSS Distributions 		ret = proc_terminate(child, &sentsignal);
254*f6217f89SApple OSS Distributions 		T_EXPECT_EQ_INT(ret, ESRCH, "expected no such process return: %d", ret);
255*f6217f89SApple OSS Distributions 		// Terminating PID 1 should fail with EPERM
256*f6217f89SApple OSS Distributions 		ret = proc_terminate(1, &sentsignal);
257*f6217f89SApple OSS Distributions 		T_EXPECT_EQ_INT(ret, EPERM, "expected eperm return: %d", ret);
258*f6217f89SApple OSS Distributions 	} else {
259*f6217f89SApple OSS Distributions 		pause();
260*f6217f89SApple OSS Distributions 		// This exit should not hit, but we exit abnormally in case something went wrong
261*f6217f89SApple OSS Distributions 		_exit(-1);
262*f6217f89SApple OSS Distributions 	}
263*f6217f89SApple OSS Distributions }
264*f6217f89SApple OSS Distributions 
265*f6217f89SApple OSS Distributions static void
__test_exit_reason_signal_with_audittoken(int signal)266*f6217f89SApple OSS Distributions __test_exit_reason_signal_with_audittoken(int signal)
267*f6217f89SApple OSS Distributions {
268*f6217f89SApple OSS Distributions 	int ret = 0;
269*f6217f89SApple OSS Distributions 	audit_token_t token = INVALID_AUDIT_TOKEN_VALUE;
270*f6217f89SApple OSS Distributions 	pid_t child = fork();
271*f6217f89SApple OSS Distributions 	if (child > 0) {
272*f6217f89SApple OSS Distributions 		audit_token_for_pid(child, &token);
273*f6217f89SApple OSS Distributions 		// Send signal to the child with its audit token
274*f6217f89SApple OSS Distributions 		ret = proc_signal_with_audittoken(&token, signal);
275*f6217f89SApple OSS Distributions 		wait_collect_exit_reason(child, signal);
276*f6217f89SApple OSS Distributions 		T_EXPECT_EQ_INT(ret, 0, "expect proc_signal_with_audittoken return: %d", ret);
277*f6217f89SApple OSS Distributions 		// Send signal to the child with its audit token who has exited by now
278*f6217f89SApple OSS Distributions 		ret = proc_signal_with_audittoken(&token, signal);
279*f6217f89SApple OSS Distributions 		T_EXPECT_EQ_INT(ret, ESRCH, "expect no such process return: %d", ret);
280*f6217f89SApple OSS Distributions 	} else {
281*f6217f89SApple OSS Distributions 		pause();
282*f6217f89SApple OSS Distributions 		// This exit should not hit, but we exit abnormally in case something went wrong
283*f6217f89SApple OSS Distributions 		_exit(-1);
284*f6217f89SApple OSS Distributions 	}
285*f6217f89SApple OSS Distributions }
286*f6217f89SApple OSS Distributions 
287*f6217f89SApple OSS Distributions static void
__test_exit_reason_signal_with_audittoken_fail_bad_token(int signal)288*f6217f89SApple OSS Distributions __test_exit_reason_signal_with_audittoken_fail_bad_token(int signal)
289*f6217f89SApple OSS Distributions {
290*f6217f89SApple OSS Distributions 	int ret = 0;
291*f6217f89SApple OSS Distributions 	audit_token_t token = INVALID_AUDIT_TOKEN_VALUE;
292*f6217f89SApple OSS Distributions 	pid_t child = fork();
293*f6217f89SApple OSS Distributions 	if (child > 0) {
294*f6217f89SApple OSS Distributions 		audit_token_for_pid(child, &token);
295*f6217f89SApple OSS Distributions 		// Send signal to the child with its audit token, modified so pidversion is bad
296*f6217f89SApple OSS Distributions 		token.val[7] += 1;
297*f6217f89SApple OSS Distributions 		ret = proc_signal_with_audittoken(&token, signal);
298*f6217f89SApple OSS Distributions 		wait_with_timeout_expected(child, 2);
299*f6217f89SApple OSS Distributions 		T_EXPECT_EQ_INT(ret, ESRCH, "expect bad audit token return: %d", ret);
300*f6217f89SApple OSS Distributions 		// Cleanup child
301*f6217f89SApple OSS Distributions 		kill(child, signal);
302*f6217f89SApple OSS Distributions 	} else {
303*f6217f89SApple OSS Distributions 		pause();
304*f6217f89SApple OSS Distributions 	}
305*f6217f89SApple OSS Distributions }
306*f6217f89SApple OSS Distributions 
307*f6217f89SApple OSS Distributions static void
__test_exit_reason_delegated_signal_fail_bad_instigator_token(int signal)308*f6217f89SApple OSS Distributions __test_exit_reason_delegated_signal_fail_bad_instigator_token(int signal)
309*f6217f89SApple OSS Distributions {
310*f6217f89SApple OSS Distributions 	int ret = 0;
311*f6217f89SApple OSS Distributions 	audit_token_t token = INVALID_AUDIT_TOKEN_VALUE;
312*f6217f89SApple OSS Distributions 	audit_token_t instigator = INVALID_AUDIT_TOKEN_VALUE;
313*f6217f89SApple OSS Distributions 	pid_t child = fork();
314*f6217f89SApple OSS Distributions 	if (child > 0) {
315*f6217f89SApple OSS Distributions 		audit_token_for_pid(child, &token);
316*f6217f89SApple OSS Distributions 		ret = proc_signal_delegate(instigator, token, signal);
317*f6217f89SApple OSS Distributions 		wait_with_timeout_expected(child, 2);
318*f6217f89SApple OSS Distributions 		T_EXPECT_EQ_INT(ret, ESRCH, "expect bad audit token return: %d", ret);
319*f6217f89SApple OSS Distributions 		// Cleanup child
320*f6217f89SApple OSS Distributions 		kill(child, signal);
321*f6217f89SApple OSS Distributions 	} else {
322*f6217f89SApple OSS Distributions 		pause();
323*f6217f89SApple OSS Distributions 	}
324*f6217f89SApple OSS Distributions }
325*f6217f89SApple OSS Distributions 
326*f6217f89SApple OSS Distributions static void
__test_exit_reason_signal_with_audittoken_fail_null_token(int signal)327*f6217f89SApple OSS Distributions __test_exit_reason_signal_with_audittoken_fail_null_token(int signal)
328*f6217f89SApple OSS Distributions {
329*f6217f89SApple OSS Distributions 	int ret = 0;
330*f6217f89SApple OSS Distributions 	pid_t child = fork();
331*f6217f89SApple OSS Distributions 	if (child > 0) {
332*f6217f89SApple OSS Distributions 		// Send signal to the child with null audit token
333*f6217f89SApple OSS Distributions 		ret = proc_signal_with_audittoken(NULL, signal);
334*f6217f89SApple OSS Distributions 		wait_with_timeout_expected(child, 2);
335*f6217f89SApple OSS Distributions 		T_EXPECT_EQ_INT(ret, EINVAL, "expect null audit token return: %d", ret);
336*f6217f89SApple OSS Distributions 		// Cleanup child
337*f6217f89SApple OSS Distributions 		kill(child, signal);
338*f6217f89SApple OSS Distributions 	} else {
339*f6217f89SApple OSS Distributions 		pause();
340*f6217f89SApple OSS Distributions 	}
341*f6217f89SApple OSS Distributions }
342*f6217f89SApple OSS Distributions 
343*f6217f89SApple OSS Distributions static void
__test_exit_reason_signal_with_audittoken_fail_bad_signal(int signal)344*f6217f89SApple OSS Distributions __test_exit_reason_signal_with_audittoken_fail_bad_signal(int signal)
345*f6217f89SApple OSS Distributions {
346*f6217f89SApple OSS Distributions 	int ret = 0;
347*f6217f89SApple OSS Distributions 	audit_token_t token = INVALID_AUDIT_TOKEN_VALUE;
348*f6217f89SApple OSS Distributions 	pid_t child = fork();
349*f6217f89SApple OSS Distributions 	if (child > 0) {
350*f6217f89SApple OSS Distributions 		audit_token_for_pid(child, &token);
351*f6217f89SApple OSS Distributions 		ret = proc_signal_with_audittoken(&token, signal);
352*f6217f89SApple OSS Distributions 		wait_with_timeout_expected(child, 2);
353*f6217f89SApple OSS Distributions 		T_EXPECT_EQ_INT(ret, EINVAL, "expect invalid sig num return: %d", ret);
354*f6217f89SApple OSS Distributions 		kill(child, signal);
355*f6217f89SApple OSS Distributions 	} else {
356*f6217f89SApple OSS Distributions 		pause();
357*f6217f89SApple OSS Distributions 	}
358*f6217f89SApple OSS Distributions }
359*f6217f89SApple OSS Distributions 
360*f6217f89SApple OSS Distributions // Required signal handler for sigwait to work properly
361*f6217f89SApple OSS Distributions static void
null_signal_handler(int sig)362*f6217f89SApple OSS Distributions null_signal_handler(int sig)
363*f6217f89SApple OSS Distributions {
364*f6217f89SApple OSS Distributions }
365*f6217f89SApple OSS Distributions 
366*f6217f89SApple OSS Distributions static void
__test_signal_zombie(void)367*f6217f89SApple OSS Distributions __test_signal_zombie(void)
368*f6217f89SApple OSS Distributions {
369*f6217f89SApple OSS Distributions 	pid_t child;
370*f6217f89SApple OSS Distributions 	sigset_t set;
371*f6217f89SApple OSS Distributions 	sigset_t oldset;
372*f6217f89SApple OSS Distributions 	int sig = 0, ret = 0;
373*f6217f89SApple OSS Distributions 	audit_token_t token = INVALID_AUDIT_TOKEN_VALUE;
374*f6217f89SApple OSS Distributions 
375*f6217f89SApple OSS Distributions 	// Set signal handler
376*f6217f89SApple OSS Distributions 	signal(SIGCHLD, &null_signal_handler);
377*f6217f89SApple OSS Distributions 
378*f6217f89SApple OSS Distributions 	// Mask SIGCHLD so it becomes pending
379*f6217f89SApple OSS Distributions 	// when the child dies.
380*f6217f89SApple OSS Distributions 	sigemptyset(&set);
381*f6217f89SApple OSS Distributions 	sigaddset(&set, SIGCHLD);
382*f6217f89SApple OSS Distributions 	sigprocmask(SIG_BLOCK, &set, &oldset);
383*f6217f89SApple OSS Distributions 
384*f6217f89SApple OSS Distributions 	// Immediately exit child
385*f6217f89SApple OSS Distributions 	if ((child = fork()) == 0) {
386*f6217f89SApple OSS Distributions 		sleep(1);
387*f6217f89SApple OSS Distributions 		exit(0);
388*f6217f89SApple OSS Distributions 	}
389*f6217f89SApple OSS Distributions 
390*f6217f89SApple OSS Distributions 	// Calculate target audit token
391*f6217f89SApple OSS Distributions 	T_EXPECT_TRUE(audit_token_for_pid(child, &token), "audit token determined");
392*f6217f89SApple OSS Distributions 
393*f6217f89SApple OSS Distributions 	// Wait for kernel to notify us of a dead child. Which means it's now in a
394*f6217f89SApple OSS Distributions 	// zombie state.
395*f6217f89SApple OSS Distributions 	sigwait(&set, &sig);
396*f6217f89SApple OSS Distributions 
397*f6217f89SApple OSS Distributions 	// Restore process mask
398*f6217f89SApple OSS Distributions 	sigprocmask(SIG_SETMASK, &oldset, NULL);
399*f6217f89SApple OSS Distributions 
400*f6217f89SApple OSS Distributions 	// First test that kill succeeds for POSIX compliance
401*f6217f89SApple OSS Distributions 	T_EXPECT_EQ_INT(kill(child, 0), 0, "kill() suceeds on a zombie");
402*f6217f89SApple OSS Distributions 
403*f6217f89SApple OSS Distributions 	// Then test that the proc_info path has a sensible error code
404*f6217f89SApple OSS Distributions 	ret = proc_signal_with_audittoken(&token, SIGHUP);
405*f6217f89SApple OSS Distributions 	T_EXPECT_EQ_INT(ret, ESRCH, "expect invalid sig num return: %d", ret);
406*f6217f89SApple OSS Distributions 
407*f6217f89SApple OSS Distributions 	// Cleanup zombie child
408*f6217f89SApple OSS Distributions 	wait_with_timeout_expected(child, 0);
409*f6217f89SApple OSS Distributions }
410*f6217f89SApple OSS Distributions 
411*f6217f89SApple OSS Distributions 
412*f6217f89SApple OSS Distributions T_DECL(signal_zombie, "signaling a zombie should work", T_META_TAG_VM_PREFERRED)
413*f6217f89SApple OSS Distributions {
414*f6217f89SApple OSS Distributions 	dispatch_test(^{
415*f6217f89SApple OSS Distributions 		__test_signal_zombie();
416*f6217f89SApple OSS Distributions 		T_END;
417*f6217f89SApple OSS Distributions 	});
418*f6217f89SApple OSS Distributions }
419*f6217f89SApple OSS Distributions 
420*f6217f89SApple OSS Distributions T_DECL(proc_signal_delegate_success, "proc_signal_delegate should work",
421*f6217f89SApple OSS Distributions     T_META_TAG_VM_PREFERRED,
422*f6217f89SApple OSS Distributions     T_META_ENABLED(false) /* rdar://146369624 */)
423*f6217f89SApple OSS Distributions {
424*f6217f89SApple OSS Distributions 	dispatch_test(^{
425*f6217f89SApple OSS Distributions 		__test_exit_reason_delegate_signal(SIGABRT);
426*f6217f89SApple OSS Distributions 		__test_exit_reason_delegate_signal(SIGKILL);
427*f6217f89SApple OSS Distributions 		__test_exit_reason_delegate_signal(SIGSYS);
428*f6217f89SApple OSS Distributions 		__test_exit_reason_delegate_signal(SIGUSR1);
429*f6217f89SApple OSS Distributions 		__test_exit_reason_delegate_terminate();
430*f6217f89SApple OSS Distributions 		T_END;
431*f6217f89SApple OSS Distributions 	});
432*f6217f89SApple OSS Distributions }
433*f6217f89SApple OSS Distributions 
434*f6217f89SApple OSS Distributions T_DECL(proc_terminate_success, "proc_terminate should work", T_META_TAG_VM_PREFERRED)
435*f6217f89SApple OSS Distributions {
436*f6217f89SApple OSS Distributions 	dispatch_test(^{
437*f6217f89SApple OSS Distributions 		__test_exit_reason_terminate();
438*f6217f89SApple OSS Distributions 		T_END;
439*f6217f89SApple OSS Distributions 	});
440*f6217f89SApple OSS Distributions }
441*f6217f89SApple OSS Distributions 
442*f6217f89SApple OSS Distributions T_DECL(proc_signal_with_audittoken_success, "proc_signal_with_audittoken should work", T_META_TAG_VM_PREFERRED)
443*f6217f89SApple OSS Distributions {
444*f6217f89SApple OSS Distributions 	dispatch_test(^{
445*f6217f89SApple OSS Distributions 		__test_exit_reason_signal_with_audittoken(SIGABRT);
446*f6217f89SApple OSS Distributions 		__test_exit_reason_signal_with_audittoken(SIGKILL);
447*f6217f89SApple OSS Distributions 		__test_exit_reason_signal_with_audittoken(SIGSYS);
448*f6217f89SApple OSS Distributions 		__test_exit_reason_signal_with_audittoken(SIGUSR1);
449*f6217f89SApple OSS Distributions 		T_END;
450*f6217f89SApple OSS Distributions 	});
451*f6217f89SApple OSS Distributions }
452*f6217f89SApple OSS Distributions 
453*f6217f89SApple OSS Distributions T_DECL(proc_signal_with_audittoken_fail_bad_token, "proc_signal_with_audittoken should fail with invalid audit token", T_META_TAG_VM_PREFERRED)
454*f6217f89SApple OSS Distributions {
455*f6217f89SApple OSS Distributions 	dispatch_test(^{
456*f6217f89SApple OSS Distributions 		__test_exit_reason_signal_with_audittoken_fail_bad_token(SIGKILL);
457*f6217f89SApple OSS Distributions 		T_END;
458*f6217f89SApple OSS Distributions 	});
459*f6217f89SApple OSS Distributions }
460*f6217f89SApple OSS Distributions 
461*f6217f89SApple OSS Distributions T_DECL(proc_delegated_signal_fail_bad_instigator_token, "proc_signal_delegated should fail with invalid instigator audit token", T_META_TAG_VM_PREFERRED)
462*f6217f89SApple OSS Distributions {
463*f6217f89SApple OSS Distributions 	dispatch_test(^{
464*f6217f89SApple OSS Distributions 		__test_exit_reason_delegated_signal_fail_bad_instigator_token(SIGKILL);
465*f6217f89SApple OSS Distributions 		T_END;
466*f6217f89SApple OSS Distributions 	});
467*f6217f89SApple OSS Distributions }
468*f6217f89SApple OSS Distributions 
469*f6217f89SApple OSS Distributions T_DECL(proc_signal_with_audittoken_fail_null_token, "proc_signal_with_audittoken should fail with a null audit token", T_META_TAG_VM_PREFERRED)
470*f6217f89SApple OSS Distributions {
471*f6217f89SApple OSS Distributions 	dispatch_test(^{
472*f6217f89SApple OSS Distributions 		__test_exit_reason_signal_with_audittoken_fail_null_token(SIGKILL);
473*f6217f89SApple OSS Distributions 		T_END;
474*f6217f89SApple OSS Distributions 	});
475*f6217f89SApple OSS Distributions }
476*f6217f89SApple OSS Distributions 
477*f6217f89SApple OSS Distributions T_DECL(proc_signal_with_audittoken_fail_bad_signal, "proc_signal_with_audittoken should fail with invalid signals", T_META_TAG_VM_PREFERRED)
478*f6217f89SApple OSS Distributions {
479*f6217f89SApple OSS Distributions 	dispatch_test(^{
480*f6217f89SApple OSS Distributions 		__test_exit_reason_signal_with_audittoken_fail_bad_signal(0);
481*f6217f89SApple OSS Distributions 		__test_exit_reason_signal_with_audittoken_fail_bad_signal(NSIG + 1);
482*f6217f89SApple OSS Distributions 		T_END;
483*f6217f89SApple OSS Distributions 	});
484*f6217f89SApple OSS Distributions }
485*f6217f89SApple OSS Distributions 
486*f6217f89SApple OSS Distributions T_DECL(test_exit_reason_external_signal, "tests exit reason for external signals", T_META_TAG_VM_PREFERRED)
487*f6217f89SApple OSS Distributions {
488*f6217f89SApple OSS Distributions 	dispatch_test(^{
489*f6217f89SApple OSS Distributions 		__test_exit_reason_external_signal(SIGABRT);
490*f6217f89SApple OSS Distributions 		__test_exit_reason_external_signal(SIGKILL);
491*f6217f89SApple OSS Distributions 		__test_exit_reason_external_signal(SIGSYS);
492*f6217f89SApple OSS Distributions 		__test_exit_reason_external_signal(SIGUSR1);
493*f6217f89SApple OSS Distributions 		T_END;
494*f6217f89SApple OSS Distributions 	});
495*f6217f89SApple OSS Distributions }
496*f6217f89SApple OSS Distributions 
497*f6217f89SApple OSS Distributions struct pthread_kill_helper_args {
498*f6217f89SApple OSS Distributions 	pthread_t *pthread;
499*f6217f89SApple OSS Distributions 	int signal;
500*f6217f89SApple OSS Distributions };
501*f6217f89SApple OSS Distributions 
502*f6217f89SApple OSS Distributions static void *_Nullable
pthread_kill_helper(void * _Nullable msg)503*f6217f89SApple OSS Distributions pthread_kill_helper(void *_Nullable msg)
504*f6217f89SApple OSS Distributions {
505*f6217f89SApple OSS Distributions 	struct pthread_kill_helper_args *args = (struct pthread_kill_helper_args *)msg;
506*f6217f89SApple OSS Distributions 	pthread_kill(*args->pthread, args->signal);
507*f6217f89SApple OSS Distributions 	return NULL;
508*f6217f89SApple OSS Distributions }
509*f6217f89SApple OSS Distributions 
510*f6217f89SApple OSS Distributions static void
__test_exit_reason_pthread_kill_self(int signal)511*f6217f89SApple OSS Distributions __test_exit_reason_pthread_kill_self(int signal)
512*f6217f89SApple OSS Distributions {
513*f6217f89SApple OSS Distributions 	T_LOG("Testing pthread_kill for signal %d", signal);
514*f6217f89SApple OSS Distributions 	pid_t child = fork();
515*f6217f89SApple OSS Distributions 	if (child > 0) {
516*f6217f89SApple OSS Distributions 		wait_collect_exit_reason(child, signal);
517*f6217f89SApple OSS Distributions 	} else {
518*f6217f89SApple OSS Distributions 		pthread_t t;
519*f6217f89SApple OSS Distributions 		struct pthread_kill_helper_args args = {&t, signal};
520*f6217f89SApple OSS Distributions 		pthread_create(&t, NULL, (void*(*)(void*))pthread_kill_helper, (void *)&args);
521*f6217f89SApple OSS Distributions 		pthread_join(t, NULL);
522*f6217f89SApple OSS Distributions 	}
523*f6217f89SApple OSS Distributions }
524*f6217f89SApple OSS Distributions 
525*f6217f89SApple OSS Distributions T_DECL(test_exit_reason_pthread_kill_self, "tests exit reason for pthread_kill on caller thread", T_META_TAG_VM_PREFERRED)
526*f6217f89SApple OSS Distributions {
527*f6217f89SApple OSS Distributions 	dispatch_test(^{
528*f6217f89SApple OSS Distributions 		__test_exit_reason_pthread_kill_self(SIGABRT);
529*f6217f89SApple OSS Distributions 		__test_exit_reason_pthread_kill_self(SIGKILL);
530*f6217f89SApple OSS Distributions 		__test_exit_reason_pthread_kill_self(SIGSYS);
531*f6217f89SApple OSS Distributions 		__test_exit_reason_pthread_kill_self(SIGUSR1);
532*f6217f89SApple OSS Distributions 		T_END;
533*f6217f89SApple OSS Distributions 	});
534*f6217f89SApple OSS Distributions }
535