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