1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
3 * You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5 #include <string>
6 #include <cstring>
7 #include <cstdlib>
8 #include <cstdio>
9 #include <dlfcn.h>
10 #include <unistd.h>
11 #include <errno.h>
12 #include <algorithm>
13 #include <fcntl.h>
14 #include "ElfLoader.h"
15 #include "BaseElf.h"
16 #include "CustomElf.h"
17 #include "Mappable.h"
18 #include "Logging.h"
19 #include "Utils.h"
20 #include <inttypes.h>
21
22 using namespace mozilla;
23
24 // From Utils.h
25 Atomic<size_t, ReleaseAcquire> gPageSize;
26
27 #if defined(ANDROID)
28 #include <sys/syscall.h>
29 #include <math.h>
30
31 #include <android/api-level.h>
32 #if __ANDROID_API__ < 8
33 /* Android API < 8 doesn't provide sigaltstack */
34
35 extern "C" {
36
sigaltstack(const stack_t * ss,stack_t * oss)37 inline int sigaltstack(const stack_t *ss, stack_t *oss) {
38 return syscall(__NR_sigaltstack, ss, oss);
39 }
40
41 } /* extern "C" */
42 #endif /* __ANDROID_API__ */
43 #endif /* ANDROID */
44
45 #ifdef __ARM_EABI__
46 extern "C" MOZ_EXPORT const void *__gnu_Unwind_Find_exidx(void *pc, int *pcount)
47 __attribute__((weak));
48 #endif
49
50 /* Ideally we'd #include <link.h>, but that's a world of pain
51 * Moreover, not all versions of android support it, so we need a weak
52 * reference. */
53 extern "C" MOZ_EXPORT int dl_iterate_phdr(dl_phdr_cb callback, void *data)
54 __attribute__((weak));
55
56 /* Pointer to the PT_DYNAMIC section of the executable or library
57 * containing this code. */
58 extern "C" Elf::Dyn _DYNAMIC[];
59
60 /**
61 * dlfcn.h replacements functions
62 */
63
__wrap_dlopen(const char * path,int flags)64 void *__wrap_dlopen(const char *path, int flags) {
65 RefPtr<LibHandle> handle = ElfLoader::Singleton.Load(path, flags);
66 if (handle) handle->AddDirectRef();
67 return handle;
68 }
69
__wrap_dlerror(void)70 const char *__wrap_dlerror(void) {
71 const char *error = ElfLoader::Singleton.lastError;
72 ElfLoader::Singleton.lastError = nullptr;
73 return error;
74 }
75
__wrap_dlsym(void * handle,const char * symbol)76 void *__wrap_dlsym(void *handle, const char *symbol) {
77 if (!handle) {
78 ElfLoader::Singleton.lastError = "dlsym(NULL, sym) unsupported";
79 return nullptr;
80 }
81 if (handle != RTLD_DEFAULT && handle != RTLD_NEXT) {
82 LibHandle *h = reinterpret_cast<LibHandle *>(handle);
83 return h->GetSymbolPtr(symbol);
84 }
85
86 void *sym = dlsym(handle, symbol);
87 ElfLoader::Singleton.lastError = dlerror();
88
89 return sym;
90 }
91
__wrap_dlclose(void * handle)92 int __wrap_dlclose(void *handle) {
93 if (!handle) {
94 ElfLoader::Singleton.lastError = "No handle given to dlclose()";
95 return -1;
96 }
97 reinterpret_cast<LibHandle *>(handle)->ReleaseDirectRef();
98 return 0;
99 }
100
__wrap_dladdr(void * addr,Dl_info * info)101 int __wrap_dladdr(void *addr, Dl_info *info) {
102 RefPtr<LibHandle> handle = ElfLoader::Singleton.GetHandleByPtr(addr);
103 if (!handle) {
104 return dladdr(addr, info);
105 }
106 info->dli_fname = handle->GetPath();
107 info->dli_fbase = handle->GetBase();
108 return 1;
109 }
110
111 class DlIteratePhdrHelper {
112 public:
DlIteratePhdrHelper()113 DlIteratePhdrHelper() {
114 int pipefd[2];
115 valid_pipe = (pipe(pipefd) == 0);
116 read_fd.reset(pipefd[0]);
117 write_fd.reset(pipefd[1]);
118 }
119
120 int fill_and_call(dl_phdr_cb callback, const void *l_addr, const char *l_name,
121 void *data);
122
123 private:
124 bool valid_pipe;
125 AutoCloseFD read_fd;
126 AutoCloseFD write_fd;
127 };
128
129 // This function is called for each shared library iterated over by
130 // dl_iterate_phdr, and is used to fill a dl_phdr_info which is then
131 // sent through to the dl_iterate_phdr callback.
fill_and_call(dl_phdr_cb callback,const void * l_addr,const char * l_name,void * data)132 int DlIteratePhdrHelper::fill_and_call(dl_phdr_cb callback, const void *l_addr,
133 const char *l_name, void *data) {
134 dl_phdr_info info;
135 info.dlpi_addr = reinterpret_cast<Elf::Addr>(l_addr);
136 info.dlpi_name = l_name;
137 info.dlpi_phdr = nullptr;
138 info.dlpi_phnum = 0;
139
140 // Assuming l_addr points to Elf headers (in most cases, this is true),
141 // get the Phdr location from there.
142 // Unfortunately, when l_addr doesn't point to Elf headers, it may point
143 // to unmapped memory, or worse, unreadable memory. The only way to detect
144 // the latter without causing a SIGSEGV is to use the pointer in a system
145 // call that will try to read from there, and return an EFAULT error if
146 // it can't. One such system call is write(). It used to be possible to
147 // use a file descriptor on /dev/null for these kind of things, but recent
148 // Linux kernels never return an EFAULT error when using /dev/null.
149 // So instead, we use a self pipe. We do however need to read() from the
150 // read end of the pipe as well so as to not fill up the pipe buffer and
151 // block on subsequent writes.
152 // In the unlikely event reads from or write to the pipe fail for some
153 // other reason than EFAULT, we don't try any further and just skip setting
154 // the Phdr location for all subsequent libraries, rather than trying to
155 // start over with a new pipe.
156 int can_read = true;
157 if (valid_pipe) {
158 int ret;
159 char raw_ehdr[sizeof(Elf::Ehdr)];
160 static_assert(sizeof(raw_ehdr) < PIPE_BUF, "PIPE_BUF is too small");
161 do {
162 // writes are atomic when smaller than PIPE_BUF, per POSIX.1-2008.
163 ret = write(write_fd, l_addr, sizeof(raw_ehdr));
164 } while (ret == -1 && errno == EINTR);
165 if (ret != sizeof(raw_ehdr)) {
166 if (ret == -1 && errno == EFAULT) {
167 can_read = false;
168 } else {
169 valid_pipe = false;
170 }
171 } else {
172 size_t nbytes = 0;
173 do {
174 // Per POSIX.1-2008, interrupted reads can return a length smaller
175 // than the given one instead of failing with errno EINTR.
176 ret = read(read_fd, raw_ehdr + nbytes, sizeof(raw_ehdr) - nbytes);
177 if (ret > 0) nbytes += ret;
178 } while ((nbytes != sizeof(raw_ehdr) && ret > 0) ||
179 (ret == -1 && errno == EINTR));
180 if (nbytes != sizeof(raw_ehdr)) {
181 valid_pipe = false;
182 }
183 }
184 }
185
186 if (valid_pipe && can_read) {
187 const Elf::Ehdr *ehdr = Elf::Ehdr::validate(l_addr);
188 if (ehdr) {
189 info.dlpi_phdr = reinterpret_cast<const Elf::Phdr *>(
190 reinterpret_cast<const char *>(ehdr) + ehdr->e_phoff);
191 info.dlpi_phnum = ehdr->e_phnum;
192 }
193 }
194
195 return callback(&info, sizeof(dl_phdr_info), data);
196 }
197
__wrap_dl_iterate_phdr(dl_phdr_cb callback,void * data)198 int __wrap_dl_iterate_phdr(dl_phdr_cb callback, void *data) {
199 DlIteratePhdrHelper helper;
200 AutoLock lock(&ElfLoader::Singleton.handlesMutex);
201
202 if (dl_iterate_phdr) {
203 for (ElfLoader::LibHandleList::reverse_iterator it =
204 ElfLoader::Singleton.handles.rbegin();
205 it < ElfLoader::Singleton.handles.rend(); ++it) {
206 BaseElf *elf = (*it)->AsBaseElf();
207 if (!elf) {
208 continue;
209 }
210 int ret = helper.fill_and_call(callback, (*it)->GetBase(),
211 (*it)->GetPath(), data);
212 if (ret) return ret;
213 }
214 return dl_iterate_phdr(callback, data);
215 }
216
217 /* For versions of Android that don't support dl_iterate_phdr (< 5.0),
218 * we go through the debugger helper data, which is known to be racy, but
219 * there's not much we can do about this :( . */
220 if (!ElfLoader::Singleton.dbg) return -1;
221
222 for (ElfLoader::DebuggerHelper::iterator it =
223 ElfLoader::Singleton.dbg.begin();
224 it < ElfLoader::Singleton.dbg.end(); ++it) {
225 int ret = helper.fill_and_call(callback, it->l_addr, it->l_name, data);
226 if (ret) return ret;
227 }
228 return 0;
229 }
230
231 #ifdef __ARM_EABI__
__wrap___gnu_Unwind_Find_exidx(void * pc,int * pcount)232 const void *__wrap___gnu_Unwind_Find_exidx(void *pc, int *pcount) {
233 RefPtr<LibHandle> handle = ElfLoader::Singleton.GetHandleByPtr(pc);
234 if (handle) return handle->FindExidx(pcount);
235 if (__gnu_Unwind_Find_exidx) return __gnu_Unwind_Find_exidx(pc, pcount);
236 *pcount = 0;
237 return nullptr;
238 }
239 #endif
240
241 /**
242 * faulty.lib public API
243 */
244
__dl_get_mappable_length(void * handle)245 MFBT_API size_t __dl_get_mappable_length(void *handle) {
246 if (!handle) return 0;
247 return reinterpret_cast<LibHandle *>(handle)->GetMappableLength();
248 }
249
__dl_mmap(void * handle,void * addr,size_t length,off_t offset)250 MFBT_API void *__dl_mmap(void *handle, void *addr, size_t length,
251 off_t offset) {
252 if (!handle) return nullptr;
253 return reinterpret_cast<LibHandle *>(handle)->MappableMMap(addr, length,
254 offset);
255 }
256
__dl_munmap(void * handle,void * addr,size_t length)257 MFBT_API void __dl_munmap(void *handle, void *addr, size_t length) {
258 if (!handle) return;
259 return reinterpret_cast<LibHandle *>(handle)->MappableMUnmap(addr, length);
260 }
261
IsSignalHandlingBroken()262 MFBT_API bool IsSignalHandlingBroken() {
263 return ElfLoader::Singleton.isSignalHandlingBroken();
264 }
265
266 namespace {
267
268 /**
269 * Returns the part after the last '/' for the given path
270 */
LeafName(const char * path)271 const char *LeafName(const char *path) {
272 const char *lastSlash = strrchr(path, '/');
273 if (lastSlash) return lastSlash + 1;
274 return path;
275 }
276
277 } /* Anonymous namespace */
278
279 /**
280 * LibHandle
281 */
~LibHandle()282 LibHandle::~LibHandle() { free(path); }
283
GetName() const284 const char *LibHandle::GetName() const {
285 return path ? LeafName(path) : nullptr;
286 }
287
GetMappableLength() const288 size_t LibHandle::GetMappableLength() const {
289 if (!mappable) mappable = GetMappable();
290 if (!mappable) return 0;
291 return mappable->GetLength();
292 }
293
MappableMMap(void * addr,size_t length,off_t offset) const294 void *LibHandle::MappableMMap(void *addr, size_t length, off_t offset) const {
295 if (!mappable) mappable = GetMappable();
296 if (!mappable) return MAP_FAILED;
297 void *mapped = mappable->mmap(addr, length, PROT_READ, MAP_PRIVATE, offset);
298 return mapped;
299 }
300
MappableMUnmap(void * addr,size_t length) const301 void LibHandle::MappableMUnmap(void *addr, size_t length) const {
302 if (mappable) mappable->munmap(addr, length);
303 }
304
305 /**
306 * SystemElf
307 */
Load(const char * path,int flags)308 already_AddRefed<LibHandle> SystemElf::Load(const char *path, int flags) {
309 /* The Android linker returns a handle when the file name matches an
310 * already loaded library, even when the full path doesn't exist */
311 if (path && path[0] == '/' && (access(path, F_OK) == -1)) {
312 DEBUG_LOG("dlopen(\"%s\", 0x%x) = %p", path, flags, (void *)nullptr);
313 ElfLoader::Singleton.lastError = "Specified file does not exist";
314 return nullptr;
315 }
316
317 void *handle = dlopen(path, flags);
318 DEBUG_LOG("dlopen(\"%s\", 0x%x) = %p", path, flags, handle);
319 ElfLoader::Singleton.lastError = dlerror();
320 if (handle) {
321 SystemElf *elf = new SystemElf(path, handle);
322 ElfLoader::Singleton.Register(elf);
323 RefPtr<LibHandle> lib(elf);
324 return lib.forget();
325 }
326 return nullptr;
327 }
328
~SystemElf()329 SystemElf::~SystemElf() {
330 if (!dlhandle) return;
331 DEBUG_LOG("dlclose(%p [\"%s\"])", dlhandle, GetPath());
332 dlclose(dlhandle);
333 ElfLoader::Singleton.lastError = dlerror();
334 ElfLoader::Singleton.Forget(this);
335 }
336
GetSymbolPtr(const char * symbol) const337 void *SystemElf::GetSymbolPtr(const char *symbol) const {
338 void *sym = dlsym(dlhandle, symbol);
339 DEBUG_LOG("dlsym(%p [\"%s\"], \"%s\") = %p", dlhandle, GetPath(), symbol,
340 sym);
341 ElfLoader::Singleton.lastError = dlerror();
342 return sym;
343 }
344
GetMappable() const345 Mappable *SystemElf::GetMappable() const {
346 const char *path = GetPath();
347 if (!path) return nullptr;
348 #ifdef ANDROID
349 /* On Android, if we don't have the full path, try in /system/lib */
350 const char *name = LeafName(path);
351 std::string systemPath;
352 if (name == path) {
353 systemPath = "/system/lib/";
354 systemPath += path;
355 path = systemPath.c_str();
356 }
357 #endif
358
359 return MappableFile::Create(path);
360 }
361
362 #ifdef __ARM_EABI__
FindExidx(int * pcount) const363 const void *SystemElf::FindExidx(int *pcount) const {
364 /* TODO: properly implement when ElfLoader::GetHandleByPtr
365 does return SystemElf handles */
366 *pcount = 0;
367 return nullptr;
368 }
369 #endif
370
371 /**
372 * ElfLoader
373 */
374
375 /* Unique ElfLoader instance */
376 ElfLoader ElfLoader::Singleton;
377
Load(const char * path,int flags,LibHandle * parent)378 already_AddRefed<LibHandle> ElfLoader::Load(const char *path, int flags,
379 LibHandle *parent) {
380 /* Ensure logging is initialized or refresh if environment changed. */
381 Logging::Init();
382
383 /* Ensure self_elf initialization. */
384 if (!self_elf) Init();
385
386 RefPtr<LibHandle> handle;
387
388 /* Handle dlopen(nullptr) directly. */
389 if (!path) {
390 handle = SystemElf::Load(nullptr, flags);
391 return handle.forget();
392 }
393
394 /* TODO: Handle relative paths correctly */
395 const char *name = LeafName(path);
396
397 /* Search the list of handles we already have for a match. When the given
398 * path is not absolute, compare file names, otherwise compare full paths. */
399 if (name == path) {
400 AutoLock lock(&handlesMutex);
401 for (LibHandleList::iterator it = handles.begin(); it < handles.end(); ++it)
402 if ((*it)->GetName() && (strcmp((*it)->GetName(), name) == 0)) {
403 handle = *it;
404 return handle.forget();
405 }
406 } else {
407 AutoLock lock(&handlesMutex);
408 for (LibHandleList::iterator it = handles.begin(); it < handles.end(); ++it)
409 if ((*it)->GetPath() && (strcmp((*it)->GetPath(), path) == 0)) {
410 handle = *it;
411 return handle.forget();
412 }
413 }
414
415 char *abs_path = nullptr;
416 const char *requested_path = path;
417
418 /* When the path is not absolute and the library is being loaded for
419 * another, first try to load the library from the directory containing
420 * that parent library. */
421 if ((name == path) && parent) {
422 const char *parentPath = parent->GetPath();
423 abs_path = new char[strlen(parentPath) + strlen(path)];
424 strcpy(abs_path, parentPath);
425 char *slash = strrchr(abs_path, '/');
426 strcpy(slash + 1, path);
427 path = abs_path;
428 }
429
430 Mappable *mappable = GetMappableFromPath(path);
431
432 /* Try loading with the custom linker if we have a Mappable */
433 if (mappable) handle = CustomElf::Load(mappable, path, flags);
434
435 /* Try loading with the system linker if everything above failed */
436 if (!handle) handle = SystemElf::Load(path, flags);
437
438 /* If we didn't have an absolute path and haven't been able to load
439 * a library yet, try in the system search path */
440 if (!handle && abs_path) handle = SystemElf::Load(name, flags);
441
442 delete[] abs_path;
443 DEBUG_LOG("ElfLoader::Load(\"%s\", 0x%x, %p [\"%s\"]) = %p", requested_path,
444 flags, reinterpret_cast<void *>(parent),
445 parent ? parent->GetPath() : "", static_cast<void *>(handle));
446
447 return handle.forget();
448 }
449
GetHandleByPtr(void * addr)450 already_AddRefed<LibHandle> ElfLoader::GetHandleByPtr(void *addr) {
451 AutoLock lock(&handlesMutex);
452 /* Scan the list of handles we already have for a match */
453 for (LibHandleList::iterator it = handles.begin(); it < handles.end(); ++it) {
454 if ((*it)->Contains(addr)) {
455 RefPtr<LibHandle> lib = *it;
456 return lib.forget();
457 }
458 }
459 return nullptr;
460 }
461
GetMappableFromPath(const char * path)462 Mappable *ElfLoader::GetMappableFromPath(const char *path) {
463 const char *name = LeafName(path);
464 Mappable *mappable = nullptr;
465 RefPtr<Zip> zip;
466 const char *subpath;
467 if ((subpath = strchr(path, '!'))) {
468 char *zip_path = strndup(path, subpath - path);
469 while (*(++subpath) == '/') {
470 }
471 zip = ZipCollection::GetZip(zip_path);
472 free(zip_path);
473 Zip::Stream s;
474 if (zip && zip->GetStream(subpath, &s)) {
475 /* When the MOZ_LINKER_EXTRACT environment variable is set to "1",
476 * compressed libraries are going to be (temporarily) extracted as
477 * files, in the directory pointed by the MOZ_LINKER_CACHE
478 * environment variable. */
479 const char *extract = getenv("MOZ_LINKER_EXTRACT");
480 if (extract && !strncmp(extract, "1", 2 /* Including '\0' */))
481 mappable = MappableExtractFile::Create(name, zip, &s);
482 if (!mappable) {
483 if (s.GetType() == Zip::Stream::DEFLATE) {
484 mappable = MappableDeflate::Create(name, zip, &s);
485 }
486 }
487 }
488 }
489 /* If we couldn't load above, try with a MappableFile */
490 if (!mappable && !zip) mappable = MappableFile::Create(path);
491
492 return mappable;
493 }
494
Register(LibHandle * handle)495 void ElfLoader::Register(LibHandle *handle) {
496 AutoLock lock(&handlesMutex);
497 handles.push_back(handle);
498 }
499
Register(CustomElf * handle)500 void ElfLoader::Register(CustomElf *handle) {
501 Register(static_cast<LibHandle *>(handle));
502 if (dbg) {
503 dbg.Add(handle);
504 }
505 }
506
Forget(LibHandle * handle)507 void ElfLoader::Forget(LibHandle *handle) {
508 /* Ensure logging is initialized or refresh if environment changed. */
509 Logging::Init();
510
511 AutoLock lock(&handlesMutex);
512 LibHandleList::iterator it =
513 std::find(handles.begin(), handles.end(), handle);
514 if (it != handles.end()) {
515 DEBUG_LOG("ElfLoader::Forget(%p [\"%s\"])",
516 reinterpret_cast<void *>(handle), handle->GetPath());
517 handles.erase(it);
518 } else {
519 DEBUG_LOG("ElfLoader::Forget(%p [\"%s\"]): Handle not found",
520 reinterpret_cast<void *>(handle), handle->GetPath());
521 }
522 }
523
Forget(CustomElf * handle)524 void ElfLoader::Forget(CustomElf *handle) {
525 Forget(static_cast<LibHandle *>(handle));
526 if (dbg) {
527 dbg.Remove(handle);
528 }
529 }
530
Init()531 void ElfLoader::Init() {
532 Dl_info info;
533 /* On Android < 4.1 can't reenter dl* functions. So when the library
534 * containing this code is dlopen()ed, it can't call dladdr from a
535 * static initializer. */
536 if (dladdr(_DYNAMIC, &info) != 0) {
537 self_elf = LoadedElf::Create(info.dli_fname, info.dli_fbase);
538 }
539 #if defined(ANDROID)
540 if (dladdr(FunctionPtr(syscall), &info) != 0) {
541 libc = LoadedElf::Create(info.dli_fname, info.dli_fbase);
542 }
543 if (dladdr(FunctionPtr<int (*)(double)>(isnan), &info) != 0) {
544 libm = LoadedElf::Create(info.dli_fname, info.dli_fbase);
545 }
546 #endif
547 }
548
~ElfLoader()549 ElfLoader::~ElfLoader() {
550 LibHandleList list;
551
552 if (!Singleton.IsShutdownExpected()) {
553 MOZ_CRASH("Unexpected shutdown");
554 }
555
556 /* Release self_elf and libc */
557 self_elf = nullptr;
558 #if defined(ANDROID)
559 libc = nullptr;
560 libm = nullptr;
561 #endif
562
563 AutoLock lock(&handlesMutex);
564 /* Build up a list of all library handles with direct (external) references.
565 * We actually skip system library handles because we want to keep at least
566 * some of these open. Most notably, Mozilla codebase keeps a few libgnome
567 * libraries deliberately open because of the mess that libORBit destruction
568 * is. dlclose()ing these libraries actually leads to problems. */
569 for (LibHandleList::reverse_iterator it = handles.rbegin();
570 it < handles.rend(); ++it) {
571 if ((*it)->DirectRefCount()) {
572 if (SystemElf *se = (*it)->AsSystemElf()) {
573 se->Forget();
574 } else {
575 list.push_back(*it);
576 }
577 }
578 }
579 /* Force release all external references to the handles collected above */
580 for (LibHandleList::iterator it = list.begin(); it < list.end(); ++it) {
581 while ((*it)->ReleaseDirectRef()) {
582 }
583 }
584 /* Remove the remaining system handles. */
585 if (handles.size()) {
586 list = handles;
587 for (LibHandleList::reverse_iterator it = list.rbegin(); it < list.rend();
588 ++it) {
589 if ((*it)->AsSystemElf()) {
590 DEBUG_LOG(
591 "ElfLoader::~ElfLoader(): Remaining handle for \"%s\" "
592 "[%" PRIdPTR " direct refs, %" PRIdPTR " refs total]",
593 (*it)->GetPath(), (*it)->DirectRefCount(), (*it)->refCount());
594 } else {
595 DEBUG_LOG(
596 "ElfLoader::~ElfLoader(): Unexpected remaining handle for \"%s\" "
597 "[%" PRIdPTR " direct refs, %" PRIdPTR " refs total]",
598 (*it)->GetPath(), (*it)->DirectRefCount(), (*it)->refCount());
599 /* Not removing, since it could have references to other libraries,
600 * destroying them as a side effect, and possibly leaving dangling
601 * pointers in the handle list we're scanning */
602 }
603 }
604 }
605 pthread_mutex_destroy(&handlesMutex);
606 }
607
608 #ifdef __ARM_EABI__
__wrap_aeabi_atexit(void * that,ElfLoader::Destructor destructor,void * dso_handle)609 int ElfLoader::__wrap_aeabi_atexit(void *that, ElfLoader::Destructor destructor,
610 void *dso_handle) {
611 Singleton.destructors.push_back(
612 DestructorCaller(destructor, that, dso_handle));
613 return 0;
614 }
615 #else
__wrap_cxa_atexit(ElfLoader::Destructor destructor,void * that,void * dso_handle)616 int ElfLoader::__wrap_cxa_atexit(ElfLoader::Destructor destructor, void *that,
617 void *dso_handle) {
618 Singleton.destructors.push_back(
619 DestructorCaller(destructor, that, dso_handle));
620 return 0;
621 }
622 #endif
623
__wrap_cxa_finalize(void * dso_handle)624 void ElfLoader::__wrap_cxa_finalize(void *dso_handle) {
625 /* Call all destructors for the given DSO handle in reverse order they were
626 * registered. */
627 std::vector<DestructorCaller>::reverse_iterator it;
628 for (it = Singleton.destructors.rbegin(); it < Singleton.destructors.rend();
629 ++it) {
630 if (it->IsForHandle(dso_handle)) {
631 it->Call();
632 }
633 }
634 }
635
Call()636 void ElfLoader::DestructorCaller::Call() {
637 if (destructor) {
638 DEBUG_LOG("ElfLoader::DestructorCaller::Call(%p, %p, %p)",
639 FunctionPtr(destructor), object, dso_handle);
640 destructor(object);
641 destructor = nullptr;
642 }
643 }
644
DebuggerHelper()645 ElfLoader::DebuggerHelper::DebuggerHelper()
646 : dbg(nullptr), firstAdded(nullptr) {
647 /* Find ELF auxiliary vectors.
648 *
649 * The kernel stores the following data on the stack when starting a
650 * program:
651 * argc
652 * argv[0] (pointer into argv strings defined below)
653 * argv[1] (likewise)
654 * ...
655 * argv[argc - 1] (likewise)
656 * nullptr
657 * envp[0] (pointer into environment strings defined below)
658 * envp[1] (likewise)
659 * ...
660 * envp[n] (likewise)
661 * nullptr
662 * ... (more NULLs on some platforms such as Android 4.3)
663 * auxv[0] (first ELF auxiliary vector)
664 * auxv[1] (second ELF auxiliary vector)
665 * ...
666 * auxv[p] (last ELF auxiliary vector)
667 * (AT_NULL, nullptr)
668 * padding
669 * argv strings, separated with '\0'
670 * environment strings, separated with '\0'
671 * nullptr
672 *
673 * What we are after are the auxv values defined by the following struct.
674 */
675 struct AuxVector {
676 Elf::Addr type;
677 Elf::Addr value;
678 };
679
680 /* Pointer to the environment variables list */
681 extern char **environ;
682
683 /* The environment may have changed since the program started, in which
684 * case the environ variables list isn't the list the kernel put on stack
685 * anymore. But in this new list, variables that didn't change still point
686 * to the strings the kernel put on stack. It is quite unlikely that two
687 * modified environment variables point to two consecutive strings in memory,
688 * so we assume that if two consecutive environment variables point to two
689 * consecutive strings, we found strings the kernel put on stack. */
690 char **env;
691 for (env = environ; *env; env++)
692 if (*env + strlen(*env) + 1 == env[1]) break;
693 if (!*env) return;
694
695 /* Next, we scan the stack backwards to find a pointer to one of those
696 * strings we found above, which will give us the location of the original
697 * envp list. As we are looking for pointers, we need to look at 32-bits or
698 * 64-bits aligned values, depening on the architecture. */
699 char **scan = reinterpret_cast<char **>(reinterpret_cast<uintptr_t>(*env) &
700 ~(sizeof(void *) - 1));
701 while (*env != *scan) scan--;
702
703 /* Finally, scan forward to find the last environment variable pointer and
704 * thus the first auxiliary vector. */
705 while (*scan++)
706 ;
707
708 /* Some platforms have more NULLs here, so skip them if we encounter them */
709 while (!*scan) scan++;
710
711 AuxVector *auxv = reinterpret_cast<AuxVector *>(scan);
712
713 /* The two values of interest in the auxiliary vectors are AT_PHDR and
714 * AT_PHNUM, which gives us the the location and size of the ELF program
715 * headers. */
716 Array<Elf::Phdr> phdrs;
717 char *base = nullptr;
718 while (auxv->type) {
719 if (auxv->type == AT_PHDR) {
720 phdrs.Init(reinterpret_cast<Elf::Phdr *>(auxv->value));
721 /* Assume the base address is the first byte of the same page */
722 base = reinterpret_cast<char *>(PageAlignedPtr(auxv->value));
723 }
724 if (auxv->type == AT_PHNUM) phdrs.Init(auxv->value);
725 auxv++;
726 }
727
728 if (!phdrs) {
729 DEBUG_LOG("Couldn't find program headers");
730 return;
731 }
732
733 /* In some cases, the address for the program headers we get from the
734 * auxiliary vectors is not mapped, because of the PT_LOAD segments
735 * definitions in the program executable. Trying to map anonymous memory
736 * with a hint giving the base address will return a different address
737 * if something is mapped there, and the base address otherwise. */
738 MappedPtr mem(MemoryRange::mmap(base, PageSize(), PROT_NONE,
739 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0));
740 if (mem == base) {
741 /* If program headers aren't mapped, try to map them */
742 int fd = open("/proc/self/exe", O_RDONLY);
743 if (fd == -1) {
744 DEBUG_LOG("Failed to open /proc/self/exe");
745 return;
746 }
747 mem.Assign(
748 MemoryRange::mmap(base, PageSize(), PROT_READ, MAP_PRIVATE, fd, 0));
749 /* If we don't manage to map at the right address, just give up. */
750 if (mem != base) {
751 DEBUG_LOG("Couldn't read program headers");
752 return;
753 }
754 }
755 /* Sanity check: the first bytes at the base address should be an ELF
756 * header. */
757 if (!Elf::Ehdr::validate(base)) {
758 DEBUG_LOG("Couldn't find program base");
759 return;
760 }
761
762 /* Search for the program PT_DYNAMIC segment */
763 Array<Elf::Dyn> dyns;
764 for (Array<Elf::Phdr>::iterator phdr = phdrs.begin(); phdr < phdrs.end();
765 ++phdr) {
766 /* While the program headers are expected within the first mapped page of
767 * the program executable, the executable PT_LOADs may actually make them
768 * loaded at an address that is not the wanted base address of the
769 * library. We thus need to adjust the base address, compensating for the
770 * virtual address of the PT_LOAD segment corresponding to offset 0. */
771 if (phdr->p_type == PT_LOAD && phdr->p_offset == 0) base -= phdr->p_vaddr;
772 if (phdr->p_type == PT_DYNAMIC)
773 dyns.Init(base + phdr->p_vaddr, phdr->p_filesz);
774 }
775 if (!dyns) {
776 DEBUG_LOG("Failed to find PT_DYNAMIC section in program");
777 return;
778 }
779
780 /* Search for the DT_DEBUG information */
781 for (Array<Elf::Dyn>::iterator dyn = dyns.begin(); dyn < dyns.end(); ++dyn) {
782 if (dyn->d_tag == DT_DEBUG) {
783 dbg = reinterpret_cast<r_debug *>(dyn->d_un.d_ptr);
784 break;
785 }
786 }
787 DEBUG_LOG("DT_DEBUG points at %p", static_cast<void *>(dbg));
788 }
789
790 /**
791 * Helper class to ensure the given pointer is writable within the scope of
792 * an instance. Permissions to the memory page where the pointer lies are
793 * restored to their original value when the instance is destroyed.
794 */
795 class EnsureWritable {
796 public:
797 template <typename T>
EnsureWritable(T * ptr,size_t length_=sizeof (T))798 EnsureWritable(T *ptr, size_t length_ = sizeof(T)) {
799 MOZ_ASSERT(length_ < PageSize());
800 prot = -1;
801 page = MAP_FAILED;
802
803 char *firstPage = PageAlignedPtr(reinterpret_cast<char *>(ptr));
804 char *lastPageEnd =
805 PageAlignedEndPtr(reinterpret_cast<char *>(ptr) + length_);
806 length = lastPageEnd - firstPage;
807 uintptr_t start = reinterpret_cast<uintptr_t>(firstPage);
808 uintptr_t end;
809
810 prot = getProt(start, &end);
811 if (prot == -1 || (start + length) > end) MOZ_CRASH();
812
813 if (prot & PROT_WRITE) {
814 success = true;
815 return;
816 }
817
818 page = firstPage;
819 int ret = mprotect(page, length, prot | PROT_WRITE);
820 success = ret == 0;
821 if (!success) {
822 ERROR("mprotect(%p, %zu, %d) = %d (errno=%d; %s)", page, length,
823 prot | PROT_WRITE, ret, errno, strerror(errno));
824 }
825 }
826
IsWritable() const827 bool IsWritable() const { return success; }
828
~EnsureWritable()829 ~EnsureWritable() {
830 if (success && page != MAP_FAILED) {
831 mprotect(page, length, prot);
832 }
833 }
834
835 private:
getProt(uintptr_t addr,uintptr_t * end)836 int getProt(uintptr_t addr, uintptr_t *end) {
837 /* The interesting part of the /proc/self/maps format looks like:
838 * startAddr-endAddr rwxp */
839 int result = 0;
840 AutoCloseFILE f(fopen("/proc/self/maps", "r"));
841 while (f) {
842 unsigned long long startAddr, endAddr;
843 char perms[5];
844 if (fscanf(f, "%llx-%llx %4s %*1024[^\n] ", &startAddr, &endAddr,
845 perms) != 3)
846 return -1;
847 if (addr < startAddr || addr >= endAddr) continue;
848 if (perms[0] == 'r')
849 result |= PROT_READ;
850 else if (perms[0] != '-')
851 return -1;
852 if (perms[1] == 'w')
853 result |= PROT_WRITE;
854 else if (perms[1] != '-')
855 return -1;
856 if (perms[2] == 'x')
857 result |= PROT_EXEC;
858 else if (perms[2] != '-')
859 return -1;
860 *end = endAddr;
861 return result;
862 }
863 return -1;
864 }
865
866 int prot;
867 void *page;
868 size_t length;
869 bool success;
870 };
871
872 /**
873 * The system linker maintains a doubly linked list of library it loads
874 * for use by the debugger. Unfortunately, it also uses the list pointers
875 * in a lot of operations and adding our data in the list is likely to
876 * trigger crashes when the linker tries to use data we don't provide or
877 * that fall off the amount data we allocated. Fortunately, the linker only
878 * traverses the list forward and accesses the head of the list from a
879 * private pointer instead of using the value in the r_debug structure.
880 * This means we can safely add members at the beginning of the list.
881 * Unfortunately, gdb checks the coherency of l_prev values, so we have
882 * to adjust the l_prev value for the first element the system linker
883 * knows about. Fortunately, it doesn't use l_prev, and the first element
884 * is not ever going to be released before our elements, since it is the
885 * program executable, so the system linker should not be changing
886 * r_debug::r_map.
887 */
Add(ElfLoader::link_map * map)888 void ElfLoader::DebuggerHelper::Add(ElfLoader::link_map *map) {
889 if (!dbg->r_brk) return;
890
891 dbg->r_state = r_debug::RT_ADD;
892 dbg->r_brk();
893
894 if (!firstAdded) {
895 /* When adding a library for the first time, r_map points to data
896 * handled by the system linker, and that data may be read-only */
897 EnsureWritable w(&dbg->r_map->l_prev);
898 if (!w.IsWritable()) {
899 dbg->r_state = r_debug::RT_CONSISTENT;
900 dbg->r_brk();
901 return;
902 }
903
904 firstAdded = map;
905 dbg->r_map->l_prev = map;
906 } else
907 dbg->r_map->l_prev = map;
908
909 map->l_prev = nullptr;
910 map->l_next = dbg->r_map;
911
912 dbg->r_map = map;
913 dbg->r_state = r_debug::RT_CONSISTENT;
914 dbg->r_brk();
915 }
916
Remove(ElfLoader::link_map * map)917 void ElfLoader::DebuggerHelper::Remove(ElfLoader::link_map *map) {
918 if (!dbg->r_brk) return;
919
920 dbg->r_state = r_debug::RT_DELETE;
921 dbg->r_brk();
922
923 if (map == firstAdded) {
924 /* When removing the first added library, its l_next is going to be
925 * data handled by the system linker, and that data may be read-only */
926 EnsureWritable w(&map->l_next->l_prev);
927 if (!w.IsWritable()) {
928 dbg->r_state = r_debug::RT_CONSISTENT;
929 dbg->r_brk();
930 return;
931 }
932
933 firstAdded = map->l_prev;
934 map->l_next->l_prev = map->l_prev;
935 } else if (map->l_next) {
936 map->l_next->l_prev = map->l_prev;
937 }
938
939 if (dbg->r_map == map)
940 dbg->r_map = map->l_next;
941 else if (map->l_prev) {
942 map->l_prev->l_next = map->l_next;
943 }
944 dbg->r_state = r_debug::RT_CONSISTENT;
945 dbg->r_brk();
946 }
947
948 #if defined(ANDROID) && defined(__NR_sigaction)
949 /* As some system libraries may be calling signal() or sigaction() to
950 * set a SIGSEGV handler, effectively breaking MappableSeekableZStream,
951 * or worse, restore our SIGSEGV handler with wrong flags (which using
952 * signal() will do), we want to hook into the system's sigaction() to
953 * replace it with our own wrapper instead, so that our handler is never
954 * replaced. We used to only do that with libraries this linker loads,
955 * but it turns out at least one system library does call signal() and
956 * breaks us (libsc-a3xx.so on the Samsung Galaxy S4).
957 * As libc's signal (bsd_signal/sysv_signal, really) calls sigaction
958 * under the hood, instead of calling the signal system call directly,
959 * we only need to hook sigaction. This is true for both bionic and
960 * glibc.
961 */
962
963 /* libc's sigaction */
964 extern "C" int sigaction(int signum, const struct sigaction *act,
965 struct sigaction *oldact);
966
967 /* Simple reimplementation of sigaction. This is roughly equivalent
968 * to the assembly that comes in bionic, but not quite equivalent to
969 * glibc's implementation, so we only use this on Android. */
sys_sigaction(int signum,const struct sigaction * act,struct sigaction * oldact)970 int sys_sigaction(int signum, const struct sigaction *act,
971 struct sigaction *oldact) {
972 return syscall(__NR_sigaction, signum, act, oldact);
973 }
974
975 /* Replace the first instructions of the given function with a jump
976 * to the given new function. */
977 template <typename T>
Divert(T func,T new_func)978 static bool Divert(T func, T new_func) {
979 void *ptr = FunctionPtr(func);
980 uintptr_t addr = reinterpret_cast<uintptr_t>(ptr);
981
982 #if defined(__i386__)
983 // A 32-bit jump is a 5 bytes instruction.
984 EnsureWritable w(ptr, 5);
985 *reinterpret_cast<unsigned char *>(addr) = 0xe9; // jmp
986 *reinterpret_cast<intptr_t *>(addr + 1) =
987 reinterpret_cast<uintptr_t>(new_func) - addr - 5; // target displacement
988 return true;
989 #elif defined(__arm__) || defined(__aarch64__)
990 const unsigned char trampoline[] = {
991 #ifdef __arm__
992 // .thumb
993 0x46, 0x04, // nop
994 0x78, 0x47, // bx pc
995 0x46, 0x04, // nop
996 // .arm
997 0x04, 0xf0, 0x1f, 0xe5, // ldr pc, [pc, #-4]
998 // .word <new_func>
999 #else // __aarch64__
1000 0x50, 0x00,
1001 0x00, 0x58, // ldr x16, [pc, #8] ; x16 (aka ip0) is the first
1002 0x00, 0x02,
1003 0x1f, 0xd6, // br x16 ; intra-procedure-call
1004 // .word <new_func.lo> ; scratch register.
1005 // .word <new_func.hi>
1006 #endif
1007 };
1008 const unsigned char *start;
1009 #ifdef __arm__
1010 if (addr & 0x01) {
1011 /* Function is thumb, the actual address of the code is without the
1012 * least significant bit. */
1013 addr--;
1014 /* The arm part of the trampoline needs to be 32-bit aligned */
1015 if (addr & 0x02)
1016 start = trampoline;
1017 else
1018 start = trampoline + 2;
1019 } else {
1020 /* Function is arm, we only need the arm part of the trampoline */
1021 start = trampoline + 6;
1022 }
1023 #else // __aarch64__
1024 start = trampoline;
1025 #endif
1026
1027 size_t len = sizeof(trampoline) - (start - trampoline);
1028 EnsureWritable w(reinterpret_cast<void *>(addr), len + sizeof(void *));
1029 memcpy(reinterpret_cast<void *>(addr), start, len);
1030 *reinterpret_cast<void **>(addr + len) = FunctionPtr(new_func);
1031 __builtin___clear_cache(
1032 reinterpret_cast<char *>(addr),
1033 reinterpret_cast<char *>(addr + len + sizeof(void *)));
1034 return true;
1035 #else
1036 return false;
1037 #endif
1038 }
1039 #else
1040 #define sys_sigaction sigaction
1041 template <typename T>
Divert(T func,T new_func)1042 static bool Divert(T func, T new_func) {
1043 return false;
1044 }
1045 #endif
1046
1047 namespace {
1048
1049 /* Clock that only accounts for time spent in the current process. */
ProcessTimeStamp_Now()1050 static uint64_t ProcessTimeStamp_Now() {
1051 struct timespec ts;
1052 int rv = clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts);
1053
1054 if (rv != 0) {
1055 return 0;
1056 }
1057
1058 uint64_t baseNs = (uint64_t)ts.tv_sec * 1000000000;
1059 return baseNs + (uint64_t)ts.tv_nsec;
1060 }
1061
1062 } // namespace
1063
1064 /* Data structure used to pass data to the temporary signal handler,
1065 * as well as triggering a test crash. */
1066 struct TmpData {
1067 volatile int crash_int;
1068 volatile uint64_t crash_timestamp;
1069 };
1070
SEGVHandler()1071 SEGVHandler::SEGVHandler()
1072 : initialized(false),
1073 registeredHandler(false),
1074 signalHandlingBroken(true),
1075 signalHandlingSlow(true) {
1076 /* Ensure logging is initialized before the DEBUG_LOG in the test_handler.
1077 * As this constructor runs before the ElfLoader constructor (by effect
1078 * of ElfLoader inheriting from this class), this also initializes on behalf
1079 * of ElfLoader and DebuggerHelper. */
1080 Logging::Init();
1081
1082 /* Initialize oldStack.ss_flags to an invalid value when used to set
1083 * an alternative stack, meaning we haven't got information about the
1084 * original alternative stack and thus don't mean to restore it in
1085 * the destructor. */
1086 oldStack.ss_flags = SS_ONSTACK;
1087
1088 /* Get the current segfault signal handler. */
1089 struct sigaction old_action;
1090 sys_sigaction(SIGSEGV, nullptr, &old_action);
1091
1092 /* Some devices don't provide useful information to their SIGSEGV handlers,
1093 * making it impossible for on-demand decompression to work. To check if
1094 * we're on such a device, setup a temporary handler and deliberately
1095 * trigger a segfault. The handler will set signalHandlingBroken if the
1096 * provided information is bogus.
1097 * Some other devices have a kernel option enabled that makes SIGSEGV handler
1098 * have an overhead so high that it affects how on-demand decompression
1099 * performs. The handler will also set signalHandlingSlow if the triggered
1100 * SIGSEGV took too much time. */
1101 struct sigaction action;
1102 action.sa_sigaction = &SEGVHandler::test_handler;
1103 sigemptyset(&action.sa_mask);
1104 action.sa_flags = SA_SIGINFO | SA_NODEFER;
1105 action.sa_restorer = nullptr;
1106 stackPtr.Assign(MemoryRange::mmap(nullptr, PageSize(), PROT_READ | PROT_WRITE,
1107 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0));
1108 if (stackPtr.get() == MAP_FAILED) return;
1109 if (sys_sigaction(SIGSEGV, &action, nullptr)) return;
1110
1111 TmpData *data = reinterpret_cast<TmpData *>(stackPtr.get());
1112 data->crash_timestamp = ProcessTimeStamp_Now();
1113 mprotect(stackPtr, stackPtr.GetLength(), PROT_NONE);
1114 data->crash_int = 123;
1115 /* Restore the original segfault signal handler. */
1116 sys_sigaction(SIGSEGV, &old_action, nullptr);
1117 stackPtr.Assign(MAP_FAILED, 0);
1118 }
1119
FinishInitialization()1120 void SEGVHandler::FinishInitialization() {
1121 /* Ideally, we'd need some locking here, but in practice, we're not
1122 * going to race with another thread. */
1123 initialized = true;
1124
1125 if (signalHandlingBroken || signalHandlingSlow) return;
1126
1127 typedef int (*sigaction_func)(int, const struct sigaction *,
1128 struct sigaction *);
1129
1130 sigaction_func libc_sigaction;
1131
1132 #if defined(ANDROID)
1133 /* Android > 4.4 comes with a sigaction wrapper in a LD_PRELOADed library
1134 * (libsigchain) for ART. That wrapper kind of does the same trick as we
1135 * do, so we need extra care in handling it.
1136 * - Divert the libc's sigaction, assuming the LD_PRELOADed library uses
1137 * it under the hood (which is more or less true according to the source
1138 * of that library, since it's doing a lookup in RTLD_NEXT)
1139 * - With the LD_PRELOADed library in place, all calls to sigaction from
1140 * from system libraries will go to the LD_PRELOADed library.
1141 * - The LD_PRELOADed library calls to sigaction go to our __wrap_sigaction.
1142 * - The calls to sigaction from libraries faulty.lib loads are sent to
1143 * the LD_PRELOADed library.
1144 * In practice, for signal handling, this means:
1145 * - The signal handler registered to the kernel is ours.
1146 * - Our handler redispatches to the LD_PRELOADed library's if there's a
1147 * segfault we don't handle.
1148 * - The LD_PRELOADed library redispatches according to whatever system
1149 * library or faulty.lib-loaded library set with sigaction.
1150 *
1151 * When there is no sigaction wrapper in place:
1152 * - Divert the libc's sigaction.
1153 * - Calls to sigaction from system library and faulty.lib-loaded libraries
1154 * all go to the libc's sigaction, which end up in our __wrap_sigaction.
1155 * - The signal handler registered to the kernel is ours.
1156 * - Our handler redispatches according to whatever system library or
1157 * faulty.lib-loaded library set with sigaction.
1158 */
1159 void *libc = dlopen("libc.so", RTLD_GLOBAL | RTLD_LAZY);
1160 if (libc) {
1161 /*
1162 * Lollipop bionic only has a small trampoline in sigaction, with the real
1163 * work happening in __sigaction. Divert there instead of sigaction if it
1164 * exists. Bug 1154803
1165 */
1166 libc_sigaction =
1167 reinterpret_cast<sigaction_func>(dlsym(libc, "__sigaction"));
1168
1169 if (!libc_sigaction) {
1170 libc_sigaction =
1171 reinterpret_cast<sigaction_func>(dlsym(libc, "sigaction"));
1172 }
1173 } else
1174 #endif
1175 {
1176 libc_sigaction = sigaction;
1177 }
1178
1179 if (!Divert(libc_sigaction, __wrap_sigaction)) return;
1180
1181 /* Setup an alternative stack if the already existing one is not big
1182 * enough, or if there is none. */
1183 if (sigaltstack(nullptr, &oldStack) == 0) {
1184 if (oldStack.ss_flags == SS_ONSTACK) oldStack.ss_flags = 0;
1185 if (!oldStack.ss_sp || oldStack.ss_size < stackSize) {
1186 stackPtr.Assign(MemoryRange::mmap(nullptr, stackSize,
1187 PROT_READ | PROT_WRITE,
1188 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0));
1189 if (stackPtr.get() == MAP_FAILED) return;
1190 stack_t stack;
1191 stack.ss_sp = stackPtr;
1192 stack.ss_size = stackSize;
1193 stack.ss_flags = 0;
1194 if (sigaltstack(&stack, nullptr) != 0) return;
1195 }
1196 }
1197 /* Register our own handler, and store the already registered one in
1198 * SEGVHandler's struct sigaction member */
1199 action.sa_sigaction = &SEGVHandler::handler;
1200 action.sa_flags = SA_SIGINFO | SA_NODEFER | SA_ONSTACK;
1201 registeredHandler = !sys_sigaction(SIGSEGV, &action, &this->action);
1202 }
1203
~SEGVHandler()1204 SEGVHandler::~SEGVHandler() {
1205 /* Restore alternative stack for signals */
1206 if (oldStack.ss_flags != SS_ONSTACK) sigaltstack(&oldStack, nullptr);
1207 /* Restore original signal handler */
1208 if (registeredHandler) sys_sigaction(SIGSEGV, &this->action, nullptr);
1209 }
1210
1211 /* Test handler for a deliberately triggered SIGSEGV that determines whether
1212 * useful information is provided to signal handlers, particularly whether
1213 * si_addr is filled in properly, and whether the segfault handler is called
1214 * quickly enough. */
test_handler(int signum,siginfo_t * info,void * context)1215 void SEGVHandler::test_handler(int signum, siginfo_t *info, void *context) {
1216 SEGVHandler &that = ElfLoader::Singleton;
1217 if (signum == SIGSEGV && info && info->si_addr == that.stackPtr.get())
1218 that.signalHandlingBroken = false;
1219 mprotect(that.stackPtr, that.stackPtr.GetLength(), PROT_READ | PROT_WRITE);
1220 TmpData *data = reinterpret_cast<TmpData *>(that.stackPtr.get());
1221 uint64_t latency = ProcessTimeStamp_Now() - data->crash_timestamp;
1222 DEBUG_LOG("SEGVHandler latency: %" PRIu64, latency);
1223 /* See bug 886736 for timings on different devices, 150 µs is reasonably above
1224 * the latency on "working" devices and seems to be short enough to not incur
1225 * a huge overhead to on-demand decompression. */
1226 if (latency <= 150000) that.signalHandlingSlow = false;
1227 }
1228
1229 /* TODO: "properly" handle signal masks and flags */
handler(int signum,siginfo_t * info,void * context)1230 void SEGVHandler::handler(int signum, siginfo_t *info, void *context) {
1231 // ASSERT(signum == SIGSEGV);
1232 DEBUG_LOG("Caught segmentation fault @%p", info->si_addr);
1233
1234 /* Redispatch to the registered handler */
1235 SEGVHandler &that = ElfLoader::Singleton;
1236 if (that.action.sa_flags & SA_SIGINFO) {
1237 DEBUG_LOG("Redispatching to registered handler @%p",
1238 FunctionPtr(that.action.sa_sigaction));
1239 that.action.sa_sigaction(signum, info, context);
1240 } else if (that.action.sa_handler == SIG_DFL) {
1241 DEBUG_LOG("Redispatching to default handler");
1242 /* Reset the handler to the default one, and trigger it. */
1243 sys_sigaction(signum, &that.action, nullptr);
1244 raise(signum);
1245 } else if (that.action.sa_handler != SIG_IGN) {
1246 DEBUG_LOG("Redispatching to registered handler @%p",
1247 FunctionPtr(that.action.sa_handler));
1248 that.action.sa_handler(signum);
1249 } else {
1250 DEBUG_LOG("Ignoring");
1251 }
1252 }
1253
__wrap_sigaction(int signum,const struct sigaction * act,struct sigaction * oldact)1254 int SEGVHandler::__wrap_sigaction(int signum, const struct sigaction *act,
1255 struct sigaction *oldact) {
1256 SEGVHandler &that = ElfLoader::Singleton;
1257
1258 /* Use system sigaction() function for all but SIGSEGV signals. */
1259 if (!that.registeredHandler || (signum != SIGSEGV))
1260 return sys_sigaction(signum, act, oldact);
1261
1262 if (oldact) *oldact = that.action;
1263 if (act) that.action = *act;
1264 return 0;
1265 }
1266
1267 Logging Logging::Singleton;
1268