From 95e40852cbaf8b5808e692b9b91bef5813e6dc48 Mon Sep 17 00:00:00 2001 From: Mike Hommey Date: Thu, 24 Jul 2014 13:43:56 +0900 Subject: [PATCH] Bug 1036286 - Make sure libraries loaded by faulty.lib use its own sigaction. r=nfroyd Android L added a libsigchain library it LD_PRELOADs. That library exposes a different sigaction than libc's. It's used for ART. faulty.lib gets its sigaction from libsigchain, but after bug 874708, the libraries it loads simply use libc's sigaction, assuming it would be the hooked one. In turn, this means libraries loaded by faulty.lib may override faulty.lib's handler, which is definitely not the intent. This essentially restores some of the code that bug 874708 removed. An alternative fix would be to add support for LD_PRELOAD, but that has more implications and feels more risky. This could be done, if necessary, as a followup. --- mozglue/linker/CustomElf.cpp | 5 +++++ mozglue/linker/ElfLoader.cpp | 26 ++++++++++++++++++++++++++ mozglue/linker/ElfLoader.h | 8 +++++--- 3 files changed, 36 insertions(+), 3 deletions(-) diff --git a/mozglue/linker/CustomElf.cpp b/mozglue/linker/CustomElf.cpp index 1f73303055b..29208d47e82 100644 --- a/mozglue/linker/CustomElf.cpp +++ b/mozglue/linker/CustomElf.cpp @@ -353,6 +353,11 @@ CustomElf::GetSymbolPtrInDeps(const char *symbol) const if (strcmp(symbol + 2, "gnu_Unwind_Find_exidx") == 0) return FunctionPtr(__wrap___gnu_Unwind_Find_exidx); #endif + } else if (symbol[0] == 's' && symbol[1] == 'i') { + if (strcmp(symbol + 2, "gnal") == 0) + return FunctionPtr(SEGVHandler::__wrap_signal); + if (strcmp(symbol + 2, "gaction") == 0) + return FunctionPtr(SEGVHandler::__wrap_sigaction); } #define MISSING_FLASH_SYMNAME_START "_ZN7android10VectorImpl19reservedVectorImpl" diff --git a/mozglue/linker/ElfLoader.cpp b/mozglue/linker/ElfLoader.cpp index 28b4eb9bf7c..617b07ad538 100644 --- a/mozglue/linker/ElfLoader.cpp +++ b/mozglue/linker/ElfLoader.cpp @@ -1123,4 +1123,30 @@ SEGVHandler::__wrap_sigaction(int signum, const struct sigaction *act, return 0; } +sighandler_t +SEGVHandler::__wrap_signal(int signum, sighandler_t handler) +{ + /* Use system signal() function for all but SIGSEGV signals. */ + if (signum != SIGSEGV) + return signal(signum, handler); + + SEGVHandler &that = ElfLoader::Singleton; + union { + sighandler_t signal; + void (*sigaction)(int, siginfo_t *, void *); + } oldHandler; + + /* Keep the previous handler to return its value */ + if (that.action.sa_flags & SA_SIGINFO) { + oldHandler.sigaction = that.action.sa_sigaction; + } else { + oldHandler.signal = that.action.sa_handler; + } + /* Set the new handler */ + that.action.sa_handler = handler; + that.action.sa_flags = 0; + + return oldHandler.signal; +} + Logging Logging::Singleton; diff --git a/mozglue/linker/ElfLoader.h b/mozglue/linker/ElfLoader.h index 0c59974e527..be644c112d7 100644 --- a/mozglue/linker/ElfLoader.h +++ b/mozglue/linker/ElfLoader.h @@ -319,14 +319,16 @@ public: return signalHandlingBroken; } + static int __wrap_sigaction(int signum, const struct sigaction *act, + struct sigaction *oldact); + + static sighandler_t __wrap_signal(int signum, sighandler_t handler); + protected: SEGVHandler(); ~SEGVHandler(); private: - static int __wrap_sigaction(int signum, const struct sigaction *act, - struct sigaction *oldact); - /** * SIGSEGV handler registered with __wrap_signal or __wrap_sigaction. */