1/* 2 * Copyright (C) 2013 The Android Open Source Project 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in 12 * the documentation and/or other materials provided with the 13 * distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 19 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29#include <signal.h> 30#include <string.h> 31 32#include "private/sigrtmin.h" 33 34extern "C" void __restore_rt(void); 35extern "C" void __restore(void); 36 37#if defined(__LP64__) 38 39extern "C" int __rt_sigaction(int, const struct __kernel_sigaction*, struct __kernel_sigaction*, size_t); 40 41int sigaction(int signal, const struct sigaction* bionic_new_action, struct sigaction* bionic_old_action) { 42 __kernel_sigaction kernel_new_action; 43 if (bionic_new_action != NULL) { 44 kernel_new_action.sa_flags = bionic_new_action->sa_flags; 45 kernel_new_action.sa_handler = bionic_new_action->sa_handler; 46 kernel_new_action.sa_mask = filter_reserved_signals(bionic_new_action->sa_mask); 47#if defined(SA_RESTORER) 48 kernel_new_action.sa_restorer = bionic_new_action->sa_restorer; 49#if defined(__aarch64__) 50 // arm64 has sa_restorer, but unwinding works best if you just let the 51 // kernel supply the default restorer from [vdso]. gdb doesn't care, but 52 // libgcc needs the nop that the kernel includes before the actual code. 53 // (We could add that ourselves, but why bother?) 54#else 55 if (!(kernel_new_action.sa_flags & SA_RESTORER)) { 56 kernel_new_action.sa_flags |= SA_RESTORER; 57 kernel_new_action.sa_restorer = &__restore_rt; 58 } 59#endif 60#endif 61 } 62 63 __kernel_sigaction kernel_old_action; 64 int result = __rt_sigaction(signal, 65 (bionic_new_action != NULL) ? &kernel_new_action : NULL, 66 (bionic_old_action != NULL) ? &kernel_old_action : NULL, 67 sizeof(sigset_t)); 68 69 if (bionic_old_action != NULL) { 70 bionic_old_action->sa_flags = kernel_old_action.sa_flags; 71 bionic_old_action->sa_handler = kernel_old_action.sa_handler; 72 bionic_old_action->sa_mask = kernel_old_action.sa_mask; 73#if defined(SA_RESTORER) 74 bionic_old_action->sa_restorer = kernel_old_action.sa_restorer; 75#endif 76 } 77 78 return result; 79} 80 81__strong_alias(sigaction64, sigaction); 82 83#else 84 85extern "C" int __rt_sigaction(int, const struct sigaction64*, struct sigaction64*, size_t); 86 87int sigaction(int signal, const struct sigaction* bionic_new, struct sigaction* bionic_old) { 88 // The 32-bit ABI is broken. struct sigaction includes a too-small sigset_t, 89 // so we have to translate to struct sigaction64 first. 90 struct sigaction64 kernel_new; 91 if (bionic_new) { 92 kernel_new = {}; 93 kernel_new.sa_flags = bionic_new->sa_flags; 94 kernel_new.sa_handler = bionic_new->sa_handler; 95#if defined(SA_RESTORER) 96 kernel_new.sa_restorer = bionic_new->sa_restorer; 97#endif 98 memcpy(&kernel_new.sa_mask, &bionic_new->sa_mask, sizeof(bionic_new->sa_mask)); 99 } 100 101 struct sigaction64 kernel_old; 102 int result = sigaction64(signal, bionic_new ? &kernel_new : nullptr, &kernel_old); 103 if (bionic_old) { 104 *bionic_old = {}; 105 bionic_old->sa_flags = kernel_old.sa_flags; 106 bionic_old->sa_handler = kernel_old.sa_handler; 107#if defined(SA_RESTORER) 108 bionic_old->sa_restorer = kernel_old.sa_restorer; 109#endif 110 memcpy(&bionic_old->sa_mask, &kernel_old.sa_mask, sizeof(bionic_old->sa_mask)); 111 } 112 return result; 113} 114 115int sigaction64(int signal, const struct sigaction64* bionic_new, struct sigaction64* bionic_old) { 116 struct sigaction64 kernel_new; 117 if (bionic_new) { 118 kernel_new = *bionic_new; 119#if defined(SA_RESTORER) 120 if (!(kernel_new.sa_flags & SA_RESTORER)) { 121 kernel_new.sa_flags |= SA_RESTORER; 122 kernel_new.sa_restorer = (kernel_new.sa_flags & SA_SIGINFO) ? &__restore_rt : &__restore; 123 } 124#endif 125 kernel_new.sa_mask = filter_reserved_signals(kernel_new.sa_mask); 126 } 127 128 return __rt_sigaction(signal, 129 bionic_new ? &kernel_new : nullptr, 130 bionic_old, 131 sizeof(kernel_new.sa_mask)); 132} 133 134#endif 135