1 | //===-- msan_dl.cpp -------------------------------------------------------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // This file is a part of MemorySanitizer. |
10 | // |
11 | // Helper functions for unpoisoning results of dladdr and dladdr1. |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #include "msan_dl.h" |
15 | |
16 | #include <dlfcn.h> |
17 | #include <elf.h> |
18 | #include <link.h> |
19 | |
20 | #include "msan_poisoning.h" |
21 | |
22 | namespace __msan { |
23 | |
24 | void UnpoisonDllAddrInfo(void *info) { |
25 | Dl_info *ptr = (Dl_info *)(info); |
26 | __msan_unpoison(a: ptr, size: sizeof(*ptr)); |
27 | if (ptr->dli_fname) |
28 | __msan_unpoison(a: ptr->dli_fname, size: internal_strlen(s: ptr->dli_fname) + 1); |
29 | if (ptr->dli_sname) |
30 | __msan_unpoison(a: ptr->dli_sname, size: internal_strlen(s: ptr->dli_sname) + 1); |
31 | } |
32 | |
33 | #if SANITIZER_GLIBC |
34 | void (void **, int flags) { |
35 | if (flags == RTLD_DL_SYMENT) { |
36 | __msan_unpoison(a: extra_info, size: sizeof(void *)); |
37 | |
38 | ElfW(Sym) *s = *((ElfW(Sym) **)(extra_info)); |
39 | __msan_unpoison(a: s, size: sizeof(ElfW(Sym))); |
40 | } else if (flags == RTLD_DL_LINKMAP) { |
41 | __msan_unpoison(a: extra_info, size: sizeof(void *)); |
42 | |
43 | struct link_map *map = *((struct link_map **)(extra_info)); |
44 | |
45 | // Walk forward |
46 | for (auto *ptr = map; ptr; ptr = ptr->l_next) { |
47 | __msan_unpoison(a: ptr, size: sizeof(struct link_map)); |
48 | if (ptr->l_name) |
49 | __msan_unpoison(a: ptr->l_name, size: internal_strlen(s: ptr->l_name) + 1); |
50 | } |
51 | |
52 | if (!map) |
53 | return; |
54 | |
55 | // Walk backward |
56 | for (auto *ptr = map->l_prev; ptr; ptr = ptr->l_prev) { |
57 | __msan_unpoison(a: ptr, size: sizeof(struct link_map)); |
58 | if (ptr->l_name) |
59 | __msan_unpoison(a: ptr->l_name, size: internal_strlen(s: ptr->l_name) + 1); |
60 | } |
61 | } |
62 | } |
63 | #endif |
64 | |
65 | } // namespace __msan |
66 | |