1 /* 2 * Check decoding of sigaction syscall. 3 * 4 * Copyright (c) 2017 Dmitry V. Levin <ldv@altlinux.org> 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 <asm/unistd.h> 32 33 #ifdef __NR_sigaction 34 35 # include <signal.h> 36 # include <stdint.h> 37 # include <stdio.h> 38 # include <string.h> 39 # include <unistd.h> 40 41 struct set_sa { 42 #if defined MIPS 43 unsigned int flags; 44 unsigned long handler; 45 unsigned long mask[1]; 46 #elif defined ALPHA 47 unsigned long handler; 48 unsigned long mask[1]; 49 unsigned int flags; 50 #else 51 unsigned long handler; 52 unsigned long mask[1]; 53 unsigned long flags; 54 unsigned long restorer; 55 #endif 56 } 57 #ifdef ALPHA 58 ATTRIBUTE_PACKED 59 #endif 60 ; 61 62 typedef struct set_sa struct_set_sa; 63 64 #ifdef MIPS 65 66 struct get_sa { 67 unsigned int flags; 68 unsigned long handler; 69 unsigned long mask[4]; 70 }; 71 72 typedef struct get_sa struct_get_sa; 73 74 #else 75 76 typedef struct set_sa struct_get_sa; 77 78 #endif 79 80 static long 81 k_sigaction(const kernel_ulong_t signum, const kernel_ulong_t new_act, 82 const kernel_ulong_t old_act) 83 { 84 return syscall(__NR_sigaction, signum, new_act, old_act); 85 } 86 87 #if defined SPARC || defined SPARC64 88 /* 89 * See arch/sparc/kernel/sys_sparc_32.c:sys_sparc_sigaction 90 * and arch/sparc/kernel/sys_sparc32.c:compat_sys_sparc_sigaction 91 */ 92 # define ADDR_INT ((unsigned int) -0xdefaced) 93 # define SIGNO_INT ((unsigned int) -SIGUSR1) 94 # define SIG_STR "-SIGUSR1" 95 #else 96 # define ADDR_INT ((unsigned int) 0xdefaced) 97 # define SIGNO_INT ((unsigned int) SIGUSR1) 98 # define SIG_STR "SIGUSR1" 99 #endif 100 static const kernel_ulong_t signo = 101 (kernel_ulong_t) 0xbadc0ded00000000ULL | SIGNO_INT; 102 static const kernel_ulong_t addr = 103 (kernel_ulong_t) 0xfacefeed00000000ULL | ADDR_INT; 104 105 int 106 main(void) 107 { 108 union { 109 sigset_t libc[1]; 110 unsigned long old[1]; 111 } mask; 112 113 TAIL_ALLOC_OBJECT_CONST_PTR(struct_set_sa, new_act); 114 TAIL_ALLOC_OBJECT_CONST_PTR(struct_get_sa, old_act); 115 116 if (k_sigaction(signo, 0, 0)) 117 perror_msg_and_skip("sigaction"); 118 puts("sigaction(" SIG_STR ", NULL, NULL) = 0"); 119 120 k_sigaction(signo, 0, 0); 121 puts("sigaction(" SIG_STR ", NULL, NULL) = 0"); 122 123 k_sigaction(signo, (uintptr_t) (new_act + 1), 0); 124 printf("sigaction(" SIG_STR ", %p, NULL) = -1 EFAULT (%m)\n", 125 new_act + 1); 126 127 k_sigaction(signo, (uintptr_t) new_act + 2, 0); 128 printf("sigaction(" SIG_STR ", %#lx, NULL) = -1 EFAULT (%m)\n", 129 (unsigned long) new_act + 2); 130 131 k_sigaction(signo, 0, (uintptr_t) (old_act + 1)); 132 printf("sigaction(" SIG_STR ", NULL, %p) = -1 EFAULT (%m)\n", 133 old_act + 1); 134 135 k_sigaction(signo, 0, (uintptr_t) old_act + 2); 136 printf("sigaction(" SIG_STR ", NULL, %#lx) = -1 EFAULT (%m)\n", 137 (unsigned long) old_act + 2); 138 139 k_sigaction(addr, 0, 0); 140 printf("sigaction(%d, NULL, NULL) = -1 EINVAL (%m)\n", ADDR_INT); 141 142 memset(new_act, 0, sizeof(*new_act)); 143 144 k_sigaction(signo, (uintptr_t) new_act, 0); 145 puts("sigaction(" SIG_STR ", {sa_handler=SIG_DFL, sa_mask=[]" 146 ", sa_flags=0}, NULL) = 0"); 147 148 sigemptyset(mask.libc); 149 sigaddset(mask.libc, SIGHUP); 150 sigaddset(mask.libc, SIGINT); 151 152 new_act->handler = (uintptr_t) SIG_IGN; 153 memcpy(new_act->mask, mask.old, sizeof(mask.old)); 154 new_act->flags = SA_SIGINFO; 155 156 k_sigaction(signo, (uintptr_t) new_act, (uintptr_t) old_act); 157 puts("sigaction(" SIG_STR ", {sa_handler=SIG_IGN, sa_mask=[HUP INT]" 158 ", sa_flags=SA_SIGINFO}, {sa_handler=SIG_DFL, sa_mask=[]" 159 ", sa_flags=0}) = 0"); 160 161 sigemptyset(mask.libc); 162 sigaddset(mask.libc, SIGQUIT); 163 sigaddset(mask.libc, SIGTERM); 164 165 new_act->handler = (unsigned long) addr; 166 memcpy(new_act->mask, mask.old, sizeof(mask.old)); 167 new_act->flags = SA_ONSTACK | SA_RESTART; 168 169 k_sigaction(signo, (uintptr_t) new_act, (uintptr_t) old_act); 170 printf("sigaction(" SIG_STR ", {sa_handler=%#lx, sa_mask=[QUIT TERM]" 171 ", sa_flags=SA_ONSTACK|SA_RESTART}, {sa_handler=SIG_IGN" 172 ", sa_mask=[HUP INT], sa_flags=SA_SIGINFO}) = 0\n", 173 new_act->handler); 174 175 memset(mask.old, -1, sizeof(mask.old)); 176 sigdelset(mask.libc, SIGHUP); 177 178 memcpy(new_act->mask, mask.old, sizeof(mask.old)); 179 #ifdef SA_RESTORER 180 new_act->flags = SA_RESTORER; 181 new_act->restorer = (unsigned long) 0xdeadfacecafef00dULL; 182 # define SA_RESTORER_FMT ", sa_flags=SA_RESTORER, sa_restorer=%#lx" 183 # define SA_RESTORER_ARGS , new_act->restorer 184 #else 185 new_act->flags = SA_NODEFER; 186 # define SA_RESTORER_FMT ", sa_flags=SA_NODEFER" 187 # define SA_RESTORER_ARGS 188 #endif 189 190 k_sigaction(signo, (uintptr_t) new_act, (uintptr_t) old_act); 191 printf("sigaction(" SIG_STR ", {sa_handler=%#lx, sa_mask=~[HUP]" 192 SA_RESTORER_FMT "}, {sa_handler=%#lx, sa_mask=[QUIT TERM]" 193 ", sa_flags=SA_ONSTACK|SA_RESTART}) = 0\n", 194 new_act->handler SA_RESTORER_ARGS, 195 new_act->handler); 196 197 puts("+++ exited with 0 +++"); 198 return 0; 199 } 200 201 #else 202 203 SKIP_MAIN_UNDEFINED("__NR_sigaction") 204 205 #endif 206