1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright (c) 2009 Cisco Systems, Inc. All Rights Reserved. 4 * Copyright (c) 2009 FUJITSU LIMITED. All Rights Reserved. 5 * Author: Liu Bo <liubo2009@cn.fujitsu.com> 6 * Author: Ngie Cooper <yaneurabeya@gmail.com> 7 */ 8 9 #ifndef LAPI_RT_SIGACTION_H__ 10 #define LAPI_RT_SIGACTION_H__ 11 12 #include "ltp_signal.h" 13 14 #define INVAL_SA_PTR ((void *)-1) 15 16 #if defined(__mips__) 17 struct kernel_sigaction { 18 unsigned int sa_flags; 19 void (* k_sa_handler)(int); 20 sigset_t sa_mask; 21 }; 22 #else 23 struct kernel_sigaction { 24 void (* k_sa_handler)(int); 25 unsigned long sa_flags; 26 void (*sa_restorer) (void); 27 sigset_t sa_mask; 28 }; 29 #endif 30 31 /* This macro marks if (struct sigaction) has .sa_restorer member */ 32 #if !defined(__ia64__) && !defined(__alpha__) && !defined(__hppa__) && !defined(__mips__) 33 # define HAVE_SA_RESTORER 34 #endif 35 36 #ifdef __x86_64__ 37 38 /* 39 * From asm/signal.h -- this value isn't exported anywhere outside of glibc and 40 * asm/signal.h and is only required for the rt_sig* function family because 41 * sigaction(2), et all, appends this if necessary to 42 * (struct sigaction).sa_flags. HEH. 43 * 44 * I do #undef though, just in case... 45 * 46 * Also, from .../arch/x86/kernel/signal.c:448 for v2.6.30 (something or 47 * other): 48 * 49 * x86-64 should always use SA_RESTORER. 50 * 51 * -- thus SA_RESTORER must always be defined along with 52 * (struct sigaction).sa_restorer for this architecture. 53 */ 54 #undef SA_RESTORER 55 #define SA_RESTORER 0x04000000 56 57 void (*restore_rt)(void); 58 handler_h(int signal)59 static void handler_h(int signal) 60 { 61 return; 62 } 63 64 /* Setup an initial signal handler for signal number = sig for x86_64. */ sig_initial(int sig)65 static inline int sig_initial(int sig) 66 { 67 int ret_code = -1; 68 struct sigaction act, oact; 69 70 act.sa_handler = handler_h; 71 act.sa_flags = 0; 72 /* Clear out the signal set. */ 73 if (sigemptyset(&act.sa_mask) < 0) { 74 /* Add the signal to the mask set. */ 75 } else if (sigaddset(&act.sa_mask, sig) < 0) { 76 /* Set act.sa_restorer via syscall(2) */ 77 } else if (sigaction(sig, &act, &oact) < 0) { 78 /* Copy oact.sa_restorer via syscall(2) */ 79 } else if (sigaction(sig, &act, &oact) < 0) { 80 /* And voila -- we just tricked the kernel into giving us our 81 * restorer function! */ 82 } else { 83 restore_rt = oact.sa_restorer; 84 ret_code = 0; 85 } 86 87 return ret_code; 88 } 89 90 #endif /* __x86_64__ */ 91 92 #ifdef __sparc__ 93 # if defined __arch64__ || defined __sparcv9 94 95 /* 96 * Based on glibc/sysdeps/unix/sysv/linux/sparc/sparc64/sigaction.c 97 */ 98 99 extern char *__rt_sig_stub; 100 __rt_sigreturn_stub(void)101 static void __attribute__((used)) __rt_sigreturn_stub(void) 102 { 103 __asm__ ("__rt_sig_stub: mov %0, %%g1\n\t" 104 "ta 0x6d\n\t" 105 : /* no outputs */ 106 : "i" (__NR_rt_sigreturn)); 107 } 108 109 # else /* sparc32 */ 110 111 /* 112 * Based on glibc/sysdeps/unix/sysv/linux/sparc/sparc32/sigaction.c 113 */ 114 115 extern char *__rt_sig_stub, *__sig_stub; 116 __rt_sigreturn_stub(void)117 static void __attribute__((used)) __rt_sigreturn_stub(void) 118 { 119 __asm__ ("__rt_sig_stub: mov %0, %%g1\n\t" 120 "ta 0x10\n\t" 121 : /* no outputs */ 122 : "i" (__NR_rt_sigreturn)); 123 } 124 __sigreturn_stub(void)125 static void __attribute__((used)) __sigreturn_stub(void) 126 { 127 __asm__ ("__sig_stub: mov %0, %%g1\n\t" 128 "ta 0x10\n\t" 129 : /* no outputs */ 130 : "i" (__NR_sigreturn)); 131 } 132 133 # endif 134 #endif /* __sparc__ */ 135 136 #ifdef __arc__ 137 138 #undef SA_RESTORER 139 #define SA_RESTORER 0x04000000 140 141 /* 142 * based on uClibc/libc/sysdeps/linux/arc/sigaction.c 143 */ 144 static void restore_rt(void)145 __attribute__ ((optimize("Os"))) __attribute__((used)) restore_rt(void) 146 { 147 __asm__ ( 148 "mov r8, %0 \n\t" 149 #ifdef __ARCHS__ 150 "trap_s 0 \n\t" 151 #else 152 "trap0 \n\t" 153 #endif 154 : /* no outputs */ 155 : "i" (__NR_rt_sigreturn) 156 : "r8"); 157 } 158 #endif 159 160 #ifdef TST_TEST_H__ 161 # define TST_SYSCALL tst_syscall 162 #else 163 # define TST_SYSCALL ltp_syscall 164 #endif 165 166 /* This is a wrapper for __NR_rt_sigaction syscall. 167 * act/oact values of INVAL_SA_PTR is used to pass 168 * an invalid pointer to syscall(__NR_rt_sigaction) 169 * 170 * Based on glibc/sysdeps/unix/sysv/linux/{...}/sigaction.c 171 */ 172 ltp_rt_sigaction(int signum,const struct sigaction * act,struct sigaction * oact,size_t sigsetsize)173 static int ltp_rt_sigaction(int signum, const struct sigaction *act, 174 struct sigaction *oact, size_t sigsetsize) 175 { 176 int ret; 177 struct kernel_sigaction kact, koact; 178 struct kernel_sigaction *kact_p = NULL; 179 struct kernel_sigaction *koact_p = NULL; 180 181 if (act == INVAL_SA_PTR) { 182 kact_p = INVAL_SA_PTR; 183 } else if (act) { 184 kact.k_sa_handler = act->sa_handler; 185 memcpy(&kact.sa_mask, &act->sa_mask, sizeof(sigset_t)); 186 kact.sa_flags = act->sa_flags; 187 #ifndef __mips__ 188 kact.sa_restorer = NULL; 189 #endif 190 kact_p = &kact; 191 } 192 193 if (oact == INVAL_SA_PTR) 194 koact_p = INVAL_SA_PTR; 195 else if (oact) 196 koact_p = &koact; 197 198 #ifdef __x86_64__ 199 sig_initial(signum); 200 #endif 201 202 #if defined __x86_64__ || defined __arc__ 203 kact.sa_flags |= SA_RESTORER; 204 kact.sa_restorer = restore_rt; 205 #endif 206 207 #ifdef __sparc__ 208 unsigned long stub = 0; 209 # if defined __arch64__ || defined __sparcv9 210 stub = ((unsigned long) &__rt_sig_stub) - 8; 211 # else /* sparc32 */ 212 if ((kact.sa_flags & SA_SIGINFO) != 0) 213 stub = ((unsigned long) &__rt_sig_stub) - 8; 214 else 215 stub = ((unsigned long) &__sig_stub) - 8; 216 # endif 217 #endif 218 219 220 #ifdef __sparc__ 221 ret = TST_SYSCALL(__NR_rt_sigaction, signum, 222 kact_p, koact_p, 223 stub, sigsetsize); 224 #else 225 ret = TST_SYSCALL(__NR_rt_sigaction, signum, 226 kact_p, koact_p, 227 sigsetsize); 228 #endif 229 230 if (ret >= 0) { 231 if (oact && (oact != INVAL_SA_PTR)) { 232 oact->sa_handler = koact.k_sa_handler; 233 memcpy(&oact->sa_mask, &koact.sa_mask, 234 sizeof(sigset_t)); 235 oact->sa_flags = koact.sa_flags; 236 #ifdef HAVE_SA_RESTORER 237 oact->sa_restorer = koact.sa_restorer; 238 #endif 239 } 240 } 241 242 return ret; 243 } 244 245 #endif /* LAPI_RT_SIGACTION_H__ */ 246