1 | //===-- sanitizer_linux.h ---------------------------------------*- C++ -*-===// |
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 | // Linux-specific syscall wrappers and classes. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | #ifndef SANITIZER_LINUX_H |
13 | #define SANITIZER_LINUX_H |
14 | |
15 | #include "sanitizer_platform.h" |
16 | #if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \ |
17 | SANITIZER_SOLARIS || SANITIZER_HAIKU |
18 | # include "sanitizer_common.h" |
19 | # include "sanitizer_internal_defs.h" |
20 | # include "sanitizer_platform_limits_freebsd.h" |
21 | # include "sanitizer_platform_limits_netbsd.h" |
22 | # include "sanitizer_platform_limits_posix.h" |
23 | # include "sanitizer_platform_limits_solaris.h" |
24 | # include "sanitizer_posix.h" |
25 | |
26 | struct link_map; // Opaque type returned by dlopen(). |
27 | struct utsname; |
28 | |
29 | namespace __sanitizer { |
30 | // Dirent structure for getdents(). Note that this structure is different from |
31 | // the one in <dirent.h>, which is used by readdir(). |
32 | struct linux_dirent; |
33 | |
34 | # if SANITIZER_HAIKU |
35 | struct MemoryMappingLayoutData { |
36 | long signed int cookie; |
37 | }; |
38 | # else |
39 | struct ProcSelfMapsBuff { |
40 | char *data; |
41 | uptr mmaped_size; |
42 | uptr len; |
43 | }; |
44 | |
45 | struct MemoryMappingLayoutData { |
46 | ProcSelfMapsBuff proc_self_maps; |
47 | const char *current; |
48 | }; |
49 | |
50 | void ReadProcMaps(ProcSelfMapsBuff *proc_maps); |
51 | # endif // SANITIZER_HAIKU |
52 | |
53 | // Syscall wrappers. |
54 | uptr internal_getdents(fd_t fd, struct linux_dirent *dirp, unsigned int count); |
55 | uptr internal_sigaltstack(const void *ss, void *oss); |
56 | uptr internal_sigprocmask(int how, __sanitizer_sigset_t *set, |
57 | __sanitizer_sigset_t *oldset); |
58 | |
59 | void SetSigProcMask(__sanitizer_sigset_t *set, __sanitizer_sigset_t *oldset); |
60 | void BlockSignals(__sanitizer_sigset_t *oldset = nullptr); |
61 | struct ScopedBlockSignals { |
62 | explicit ScopedBlockSignals(__sanitizer_sigset_t *copy); |
63 | ~ScopedBlockSignals(); |
64 | |
65 | ScopedBlockSignals &operator=(const ScopedBlockSignals &) = delete; |
66 | ScopedBlockSignals(const ScopedBlockSignals &) = delete; |
67 | |
68 | private: |
69 | __sanitizer_sigset_t saved_; |
70 | }; |
71 | |
72 | # if SANITIZER_GLIBC |
73 | uptr internal_clock_gettime(__sanitizer_clockid_t clk_id, void *tp); |
74 | # endif |
75 | |
76 | // Linux-only syscalls. |
77 | # if SANITIZER_LINUX |
78 | uptr internal_prctl(int option, uptr arg2, uptr arg3, uptr arg4, uptr arg5); |
79 | # if defined(__x86_64__) |
80 | uptr internal_arch_prctl(int option, uptr arg2); |
81 | # endif |
82 | // Used only by sanitizer_stoptheworld. Signal handlers that are actually used |
83 | // (like the process-wide error reporting SEGV handler) must use |
84 | // internal_sigaction instead. |
85 | int internal_sigaction_norestorer(int signum, const void *act, void *oldact); |
86 | void internal_sigdelset(__sanitizer_sigset_t *set, int signum); |
87 | # if defined(__x86_64__) || defined(__mips__) || defined(__aarch64__) || \ |
88 | defined(__powerpc64__) || defined(__s390__) || defined(__i386__) || \ |
89 | defined(__arm__) || SANITIZER_RISCV64 || SANITIZER_LOONGARCH64 |
90 | uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg, |
91 | int *parent_tidptr, void *newtls, int *child_tidptr); |
92 | # endif |
93 | int internal_uname(struct utsname *buf); |
94 | # elif SANITIZER_FREEBSD |
95 | uptr internal_procctl(int type, int id, int cmd, void *data); |
96 | void internal_sigdelset(__sanitizer_sigset_t *set, int signum); |
97 | # elif SANITIZER_NETBSD |
98 | void internal_sigdelset(__sanitizer_sigset_t *set, int signum); |
99 | uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg); |
100 | # endif // SANITIZER_LINUX |
101 | |
102 | // This class reads thread IDs from /proc/<pid>/task using only syscalls. |
103 | class ThreadLister { |
104 | public: |
105 | explicit ThreadLister(pid_t pid); |
106 | enum Result { |
107 | Error, |
108 | Incomplete, |
109 | Ok, |
110 | }; |
111 | Result ListThreads(InternalMmapVector<tid_t> *threads); |
112 | const char *LoadStatus(tid_t tid); |
113 | |
114 | private: |
115 | bool IsAlive(tid_t tid); |
116 | |
117 | InternalScopedString task_path_; |
118 | InternalScopedString status_path_; |
119 | InternalMmapVector<char> buffer_; |
120 | }; |
121 | |
122 | // Exposed for testing. |
123 | uptr ThreadDescriptorSize(); |
124 | uptr ThreadSelf(); |
125 | |
126 | // Matches a library's file name against a base name (stripping path and version |
127 | // information). |
128 | bool LibraryNameIs(const char *full_name, const char *base_name); |
129 | |
130 | // Call cb for each region mapped by map. |
131 | void ForEachMappedRegion(link_map *map, void (*cb)(const void *, uptr)); |
132 | |
133 | // Releases memory pages entirely within the [beg, end) address range. |
134 | // The pages no longer count toward RSS; reads are guaranteed to return 0. |
135 | // Requires (but does not verify!) that pages are MAP_PRIVATE. |
136 | inline void ReleaseMemoryPagesToOSAndZeroFill(uptr beg, uptr end) { |
137 | // man madvise on Linux promises zero-fill for anonymous private pages. |
138 | // Testing shows the same behaviour for private (but not anonymous) mappings |
139 | // of shm_open() files, as long as the underlying file is untouched. |
140 | CHECK(SANITIZER_LINUX); |
141 | ReleaseMemoryPagesToOS(beg, end); |
142 | } |
143 | |
144 | # if SANITIZER_ANDROID |
145 | |
146 | # if defined(__aarch64__) |
147 | # define __get_tls() \ |
148 | ({ \ |
149 | void **__v; \ |
150 | __asm__("mrs %0, tpidr_el0" : "=r"(__v)); \ |
151 | __v; \ |
152 | }) |
153 | # elif defined(__arm__) |
154 | # define __get_tls() \ |
155 | ({ \ |
156 | void **__v; \ |
157 | __asm__("mrc p15, 0, %0, c13, c0, 3" : "=r"(__v)); \ |
158 | __v; \ |
159 | }) |
160 | # elif defined(__mips__) |
161 | // On mips32r1, this goes via a kernel illegal instruction trap that's |
162 | // optimized for v1. |
163 | # define __get_tls() \ |
164 | ({ \ |
165 | register void **__v asm("v1"); \ |
166 | __asm__( \ |
167 | ".set push\n" \ |
168 | ".set mips32r2\n" \ |
169 | "rdhwr %0,$29\n" \ |
170 | ".set pop\n" \ |
171 | : "=r"(__v)); \ |
172 | __v; \ |
173 | }) |
174 | # elif defined(__riscv) |
175 | # define __get_tls() \ |
176 | ({ \ |
177 | void **__v; \ |
178 | __asm__("mv %0, tp" : "=r"(__v)); \ |
179 | __v; \ |
180 | }) |
181 | # elif defined(__i386__) |
182 | # define __get_tls() \ |
183 | ({ \ |
184 | void **__v; \ |
185 | __asm__("movl %%gs:0, %0" : "=r"(__v)); \ |
186 | __v; \ |
187 | }) |
188 | # elif defined(__x86_64__) |
189 | # define __get_tls() \ |
190 | ({ \ |
191 | void **__v; \ |
192 | __asm__("mov %%fs:0, %0" : "=r"(__v)); \ |
193 | __v; \ |
194 | }) |
195 | # else |
196 | # error "Unsupported architecture." |
197 | # endif |
198 | |
199 | // The Android Bionic team has allocated a TLS slot for sanitizers starting |
200 | // with Q, given that Android currently doesn't support ELF TLS. It is used to |
201 | // store sanitizer thread specific data. |
202 | static const int TLS_SLOT_SANITIZER = 6; |
203 | |
204 | ALWAYS_INLINE uptr *get_android_tls_ptr() { |
205 | return reinterpret_cast<uptr *>(&__get_tls()[TLS_SLOT_SANITIZER]); |
206 | } |
207 | |
208 | # endif // SANITIZER_ANDROID |
209 | |
210 | } // namespace __sanitizer |
211 | |
212 | #endif |
213 | #endif // SANITIZER_LINUX_H |
214 | |