1 /*
2 * Check decoding of signal delivery.
3 *
4 * Copyright (c) 2016-2020 The strace developers.
5 * All rights reserved.
6 *
7 * SPDX-License-Identifier: GPL-2.0-or-later
8 */
9
10 #include "tests.h"
11 #include "pidns.h"
12 #include <signal.h>
13 #include <stdio.h>
14 #include <unistd.h>
15
16 static volatile int s_sig, s_code, s_pid, s_uid;
17
18 static void
19 handler(int sig, siginfo_t *info, void *ucontext)
20 {
21 s_sig = info->si_signo;
22 s_code = info->si_code;
23 s_pid = info->si_pid;
24 s_uid = info->si_uid;
25 }
26
27 int
28 main(void)
29 {
30 PIDNS_TEST_INIT;
31
32 static const char prefix[] = "KERNEL BUG";
33 int printed = 0;
34
35 const int pid = getpid();
36 const char *pid_str = pidns_pid2str(PT_TGID);
37 const int uid = geteuid();
38
39 for (int sig = 1; sig <= 31; ++sig) {
40 if (sig == SIGKILL || sig == SIGSTOP)
41 continue;
42
43 sigset_t mask;
44 sigemptyset(&mask);
45 sigaddset(&mask, sig);
46 if (sigprocmask(SIG_UNBLOCK, &mask, NULL))
47 perror_msg_and_fail("sigprocmask");
48
49 static const struct sigaction act = {
50 .sa_sigaction = handler,
51 .sa_flags = SA_SIGINFO
52 };
53 if (sigaction(sig, &act, NULL))
54 perror_msg_and_fail("sigaction: %d", sig);
55
56 if (kill(pid, sig) != 0)
57 perror_msg_and_fail("kill: %d", sig);
58
59 #ifdef MPERS_IS_m32
60 /*
61 * The tracee has received a compat siginfo_t but
62 * the tracer has received a native siginfo_t.
63 */
64 const int e_sig = sig;
65 const int e_pid = pid;
66 const int e_uid = uid;
67 #else
68 /*
69 * If the tracee is a native process,
70 * then the tracer is also native.
71 * If the tracee is a compat process,
72 * then the tracer is also compat.
73 * Anyway, both the tracee and the tracer
74 * have received the same siginfo_t.
75 */
76 const int e_sig = s_sig;
77 const int e_pid = s_pid;
78 const int e_uid = s_uid;
79 #endif
80 pidns_print_leader();
81 printf("kill(%d%s, %s) = 0\n", pid, pid_str, signal2name(sig));
82 pidns_print_leader();
83 printf("--- %s {si_signo=%s, si_code=SI_USER, si_pid=%d%s"
84 ", si_uid=%d} ---\n",
85 signal2name(sig), signal2name(e_sig),
86 e_pid, pid_str, e_uid);
87
88 if (s_code || sig != s_sig || pid != s_pid || uid != s_uid) {
89 /*
90 * The kernel has failed to initialize siginfo_t
91 * properly. There is nothing that could be done
92 * on the strace side to workaround the kernel bug,
93 * so just print some useful diagnostics.
94 */
95 if (!printed) {
96 printed = 1;
97 fprintf(stderr, "%s: siginfo_t\n", prefix);
98 }
99 fprintf(stderr,
100 "%s: expected: si_signo=%d, si_code=%d"
101 ", si_pid=%d%s, si_uid=%d\n"
102 "%s: received: si_signo=%d, si_code=%d"
103 ", si_pid=%d%s, si_uid=%d\n",
104 prefix, sig, SI_USER, pid, pid_str, uid,
105 prefix, sig, s_code, s_pid, pid_str, s_uid);
106 }
107 }
108
109 if (printed) {
110 fprintf(stderr, "%s: end of diagnostics\n"
111 "*** PLEASE FIX THE KERNEL ***\n", prefix);
112 }
113
114 pidns_print_leader();
115 puts("+++ exited with 0 +++");
116 return 0;
117 }