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 41struct 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 62typedef struct set_sa struct_set_sa; 63 64#ifdef MIPS 65 66struct get_sa { 67 unsigned int flags; 68 unsigned long handler; 69 unsigned long mask[4]; 70}; 71 72typedef struct get_sa struct_get_sa; 73 74#else 75 76typedef struct set_sa struct_get_sa; 77 78#endif 79 80static long 81k_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 88static const kernel_ulong_t signo = 89 (kernel_ulong_t) 0xbadc0ded00000000ULL | (unsigned int) -SIGUSR1; 90# define SIG_STR "-SIGUSR1" 91#else 92static const kernel_ulong_t signo = 93 (kernel_ulong_t) 0xbadc0ded00000000ULL | SIGUSR1; 94# define SIG_STR "SIGUSR1" 95#endif 96 97int 98main(void) 99{ 100 static const kernel_ulong_t addr = 101 (kernel_ulong_t) 0xfacefeed0defacedULL; 102 union { 103 sigset_t libc[1]; 104 unsigned long old[1]; 105 } mask; 106 107 TAIL_ALLOC_OBJECT_CONST_PTR(struct_set_sa, new_act); 108 TAIL_ALLOC_OBJECT_CONST_PTR(struct_get_sa, old_act); 109 110 if (k_sigaction(signo, 0, 0)) 111 perror_msg_and_skip("sigaction"); 112 puts("sigaction(" SIG_STR ", NULL, NULL) = 0"); 113 114 k_sigaction(signo, 0, 0); 115 puts("sigaction(" SIG_STR ", NULL, NULL) = 0"); 116 117 k_sigaction(signo, (uintptr_t) (new_act + 1), 0); 118 printf("sigaction(" SIG_STR ", %p, NULL) = -1 EFAULT (%m)\n", 119 new_act + 1); 120 121 k_sigaction(signo, (uintptr_t) new_act + 2, 0); 122 printf("sigaction(" SIG_STR ", %#lx, NULL) = -1 EFAULT (%m)\n", 123 (unsigned long) new_act + 2); 124 125 k_sigaction(signo, 0, (uintptr_t) (old_act + 1)); 126 printf("sigaction(" SIG_STR ", NULL, %p) = -1 EFAULT (%m)\n", 127 old_act + 1); 128 129 k_sigaction(signo, 0, (uintptr_t) old_act + 2); 130 printf("sigaction(" SIG_STR ", NULL, %#lx) = -1 EFAULT (%m)\n", 131 (unsigned long) old_act + 2); 132 133 k_sigaction(addr, 0, 0); 134 printf("sigaction(%d, NULL, NULL) = -1 EINVAL (%m)\n", (int) addr); 135 136 memset(new_act, 0, sizeof(*new_act)); 137 138 k_sigaction(signo, (uintptr_t) new_act, 0); 139 puts("sigaction(" SIG_STR ", {sa_handler=SIG_DFL, sa_mask=[]" 140 ", sa_flags=0}, NULL) = 0"); 141 142 sigemptyset(mask.libc); 143 sigaddset(mask.libc, SIGHUP); 144 sigaddset(mask.libc, SIGINT); 145 146 new_act->handler = (uintptr_t) SIG_IGN; 147 memcpy(new_act->mask, mask.old, sizeof(mask.old)); 148 new_act->flags = SA_SIGINFO; 149 150 k_sigaction(signo, (uintptr_t) new_act, (uintptr_t) old_act); 151 puts("sigaction(" SIG_STR ", {sa_handler=SIG_IGN, sa_mask=[HUP INT]" 152 ", sa_flags=SA_SIGINFO}, {sa_handler=SIG_DFL, sa_mask=[]" 153 ", sa_flags=0}) = 0"); 154 155 sigemptyset(mask.libc); 156 sigaddset(mask.libc, SIGQUIT); 157 sigaddset(mask.libc, SIGTERM); 158 159 new_act->handler = (unsigned long) addr; 160 memcpy(new_act->mask, mask.old, sizeof(mask.old)); 161 new_act->flags = SA_ONSTACK | SA_RESTART; 162 163 k_sigaction(signo, (uintptr_t) new_act, (uintptr_t) old_act); 164 printf("sigaction(" SIG_STR ", {sa_handler=%#lx, sa_mask=[QUIT TERM]" 165 ", sa_flags=SA_ONSTACK|SA_RESTART}, {sa_handler=SIG_IGN" 166 ", sa_mask=[HUP INT], sa_flags=SA_SIGINFO}) = 0\n", 167 new_act->handler); 168 169 memset(mask.old, -1, sizeof(mask.old)); 170 sigdelset(mask.libc, SIGHUP); 171 172 memcpy(new_act->mask, mask.old, sizeof(mask.old)); 173#ifdef SA_RESTORER 174 new_act->flags = SA_RESTORER; 175 new_act->restorer = (unsigned long) 0xdeadfacecafef00dULL; 176# define SA_RESTORER_FMT ", sa_flags=SA_RESTORER, sa_restorer=%#lx" 177# define SA_RESTORER_ARGS , new_act->restorer 178#else 179 new_act->flags = SA_NODEFER; 180# define SA_RESTORER_FMT ", sa_flags=SA_NODEFER" 181# define SA_RESTORER_ARGS 182#endif 183 184 k_sigaction(signo, (uintptr_t) new_act, (uintptr_t) old_act); 185 printf("sigaction(" SIG_STR ", {sa_handler=%#lx, sa_mask=~[HUP]" 186 SA_RESTORER_FMT "}, {sa_handler=%#lx, sa_mask=[QUIT TERM]" 187 ", sa_flags=SA_ONSTACK|SA_RESTART}) = 0\n", 188 new_act->handler SA_RESTORER_ARGS, 189 new_act->handler); 190 191 puts("+++ exited with 0 +++"); 192 return 0; 193} 194 195#else 196 197SKIP_MAIN_UNDEFINED("__NR_sigaction") 198 199#endif 200