summaryrefslogtreecommitdiff
path: root/data/patches/gnuzilla-bug-1036286-2.patch
blob: 6708062f1fd41da479ac0a9555b44a417c8f3b32 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
--- a/mozglue/linker/CustomElf.cpp	
+++ a/mozglue/linker/CustomElf.cpp	
@@ -1,16 +1,17 @@ 
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include <cstring>
 #include <sys/mman.h>
 #include <vector>
 #include <dlfcn.h>
+#include <signal.h>
 #include "CustomElf.h"
 #include "Mappable.h"
 #include "Logging.h"
 
 using namespace Elf;
 using namespace mozilla;
 
 /* TODO: Fill ElfLoader::Singleton.lastError on errors. */
@@ -348,16 +349,21 @@ CustomElf::GetSymbolPtrInDeps(const char
     if (strcmp(symbol + 2, "dso_handle") == 0)
       return const_cast<CustomElf *>(this);
     if (strcmp(symbol + 2, "moz_linker_stats") == 0)
       return FunctionPtr(&ElfLoader::stats);
 #ifdef __ARM_EABI__
     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(signal);
+    if (strcmp(symbol + 2, "gaction") == 0)
+      return FunctionPtr(sigaction);
   }
 
 #define MISSING_FLASH_SYMNAME_START "_ZN7android10VectorImpl19reservedVectorImpl"
 
   // Android changed some symbols that Flash depended on in 4.4,
   // so stub those out here
   if (strncmp(symbol,
               MISSING_FLASH_SYMNAME_START,
--- a/mozglue/linker/ElfLoader.cpp	
+++ a/mozglue/linker/ElfLoader.cpp	
@@ -1014,17 +1014,59 @@ SEGVHandler::FinishInitialization()
 {
   /* Ideally, we'd need some locking here, but in practice, we're not
    * going to race with another thread. */
   initialized = true;
 
   if (signalHandlingBroken || signalHandlingSlow)
     return;
 
-  if (!Divert(sigaction, __wrap_sigaction))
+  typedef int (*sigaction_func)(int, const struct sigaction *,
+                                struct sigaction *);
+
+  sigaction_func libc_sigaction;
+
+#if defined(ANDROID)
+  /* Android > 4.4 comes with a sigaction wrapper in a LD_PRELOADed library
+   * (libsigchain) for ART. That wrapper kind of does the same trick as we
+   * do, so we need extra care in handling it.
+   * - Divert the libc's sigaction, assuming the LD_PRELOADed library uses
+   *   it under the hood (which is more or less true according to the source
+   *   of that library, since it's doing a lookup in RTLD_NEXT)
+   * - With the LD_PRELOADed library in place, all calls to sigaction from
+   *   from system libraries will go to the LD_PRELOADed library.
+   * - The LD_PRELOADed library calls to sigaction go to our __wrap_sigaction.
+   * - The calls to sigaction from libraries faulty.lib loads are sent to
+   *   the LD_PRELOADed library.
+   * In practice, for signal handling, this means:
+   * - The signal handler registered to the kernel is ours.
+   * - Our handler redispatches to the LD_PRELOADed library's if there's a
+   *   segfault we don't handle.
+   * - The LD_PRELOADed library redispatches according to whatever system
+   *   library or faulty.lib-loaded library set with sigaction.
+   *
+   * When there is no sigaction wrapper in place:
+   * - Divert the libc's sigaction.
+   * - Calls to sigaction from system library and faulty.lib-loaded libraries
+   *   all go to the libc's sigaction, which end up in our __wrap_sigaction.
+   * - The signal handler registered to the kernel is ours.
+   * - Our handler redispatches according to whatever system library or
+   *   faulty.lib-loaded library set with sigaction.
+   */
+  void *libc = dlopen("libc.so", RTLD_GLOBAL | RTLD_LAZY);
+  if (libc) {
+    libc_sigaction =
+      reinterpret_cast<sigaction_func>(dlsym(libc, "sigaction"));
+  } else
+#endif
+  {
+    libc_sigaction = sigaction;
+  }
+
+  if (!Divert(libc_sigaction, __wrap_sigaction))
     return;
 
   /* Setup an alternative stack if the already existing one is not big
    * enough, or if there is none. */
   if (sigaltstack(nullptr, &oldStack) == 0) {
     if (oldStack.ss_flags == SS_ONSTACK)
       oldStack.ss_flags = 0;
     if (!oldStack.ss_sp || oldStack.ss_size < stackSize) {