From 1e14ec2f14e533dbcf38fe773b1006d55111efb5 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 1f73303055b2..29208d47e826 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 28b4eb9bf7cb..617b07ad5388 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 0c59974e527c..be644c112d70 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. */