1 /* 2 * Check decoding of signal delivery. 3 * 4 * Copyright (c) 2016-2018 The strace developers. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. The name of the author may not be used to endorse or promote products 16 * derived from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 #include "tests.h" 31 #include <signal.h> 32 #include <stdio.h> 33 #include <unistd.h> 34 35 static volatile int s_sig, s_code, s_pid, s_uid; 36 37 static void 38 handler(int sig, siginfo_t *info, void *ucontext) 39 { 40 s_sig = info->si_signo; 41 s_code = info->si_code; 42 s_pid = info->si_pid; 43 s_uid = info->si_uid; 44 } 45 46 int 47 main(void) 48 { 49 static const char prefix[] = "KERNEL BUG"; 50 int printed = 0; 51 52 const int pid = getpid(); 53 const int uid = geteuid(); 54 55 for (int sig = 1; sig <= 31; ++sig) { 56 if (sig == SIGKILL || sig == SIGSTOP) 57 continue; 58 59 sigset_t mask; 60 sigemptyset(&mask); 61 sigaddset(&mask, sig); 62 if (sigprocmask(SIG_UNBLOCK, &mask, NULL)) 63 perror_msg_and_fail("sigprocmask"); 64 65 static const struct sigaction act = { 66 .sa_sigaction = handler, 67 .sa_flags = SA_SIGINFO 68 }; 69 if (sigaction(sig, &act, NULL)) 70 perror_msg_and_fail("sigaction: %d", sig); 71 72 if (kill(pid, sig) != 0) 73 perror_msg_and_fail("kill: %d", sig); 74 75 #ifdef MPERS_IS_m32 76 /* 77 * The tracee has received a compat siginfo_t but 78 * the tracer has received a native siginfo_t. 79 */ 80 const int e_sig = sig; 81 const int e_pid = pid; 82 const int e_uid = uid; 83 #else 84 /* 85 * If the tracee is a native process, 86 * then the tracer is also native. 87 * If the tracee is a compat process, 88 * then the tracer is also compat. 89 * Anyway, both the tracee and the tracer 90 * have received the same siginfo_t. 91 */ 92 const int e_sig = s_sig; 93 const int e_pid = s_pid; 94 const int e_uid = s_uid; 95 #endif 96 printf("kill(%d, %s) = 0\n", pid, signal2name(sig)); 97 printf("--- %s {si_signo=%s, si_code=SI_USER, si_pid=%d" 98 ", si_uid=%d} ---\n", 99 signal2name(sig), signal2name(e_sig), e_pid, e_uid); 100 101 if (s_code || sig != s_sig || pid != s_pid || uid != s_uid) { 102 /* 103 * The kernel has failed to initialize siginfo_t 104 * properly. There is nothing that could be done 105 * on the strace side to workaround the kernel bug, 106 * so just print some useful diagnostics. 107 */ 108 if (!printed) { 109 printed = 1; 110 fprintf(stderr, "%s: siginfo_t\n", prefix); 111 } 112 fprintf(stderr, 113 "%s: expected: si_signo=%d, si_code=%d" 114 ", si_pid=%d, si_uid=%d\n" 115 "%s: received: si_signo=%d, si_code=%d" 116 ", si_pid=%d, si_uid=%d\n", 117 prefix, sig, SI_USER, pid, uid, 118 prefix, sig, s_code, s_pid, s_uid); 119 } 120 } 121 122 if (printed) { 123 fprintf(stderr, "%s: end of diagnostics\n" 124 "*** PLEASE FIX THE KERNEL ***\n", prefix); 125 } 126 127 puts("+++ exited with 0 +++"); 128 return 0; 129 } 130