1 //===-- sanitizer_linux_libcdep.cc ----------------------------------------===//
3 // This file is distributed under the University of Illinois Open Source
4 // License. See LICENSE.TXT for details.
6 //===----------------------------------------------------------------------===//
8 // This file is shared between AddressSanitizer and ThreadSanitizer
9 // run-time libraries and implements linux-specific functions from
11 //===----------------------------------------------------------------------===//
13 #include "sanitizer_platform.h"
14 #if SANITIZER_FREEBSD || SANITIZER_LINUX
16 #include "sanitizer_common.h"
17 #include "sanitizer_flags.h"
18 #include "sanitizer_freebsd.h"
19 #include "sanitizer_linux.h"
20 #include "sanitizer_placement_new.h"
21 #include "sanitizer_procmaps.h"
22 #include "sanitizer_stacktrace.h"
23 #include "sanitizer_atomic.h"
24 #include "sanitizer_symbolizer.h"
26 #if SANITIZER_ANDROID || SANITIZER_FREEBSD
27 #include <dlfcn.h> // for dlsym()
32 #include <sys/resource.h>
35 #include <pthread_np.h>
36 #include <osreldate.h>
37 #define pthread_getattr_np pthread_attr_get_np
41 #include <sys/prctl.h>
44 #if !SANITIZER_ANDROID
50 namespace __sanitizer
{
52 // This function is defined elsewhere if we intercepted pthread_attr_getstack.
54 SANITIZER_WEAK_ATTRIBUTE
int
55 real_pthread_attr_getstack(void *attr
, void **addr
, size_t *size
);
58 static int my_pthread_attr_getstack(void *attr
, void **addr
, size_t *size
) {
59 if (real_pthread_attr_getstack
)
60 return real_pthread_attr_getstack((pthread_attr_t
*)attr
, addr
, size
);
61 return pthread_attr_getstack((pthread_attr_t
*)attr
, addr
, size
);
64 SANITIZER_WEAK_ATTRIBUTE
int
65 real_sigaction(int signum
, const void *act
, void *oldact
);
67 int internal_sigaction(int signum
, const void *act
, void *oldact
) {
69 return real_sigaction(signum
, act
, oldact
);
70 return sigaction(signum
, (struct sigaction
*)act
, (struct sigaction
*)oldact
);
73 void GetThreadStackTopAndBottom(bool at_initialization
, uptr
*stack_top
,
77 if (at_initialization
) {
78 // This is the main thread. Libpthread may not be initialized yet.
80 CHECK_EQ(getrlimit(RLIMIT_STACK
, &rl
), 0);
82 // Find the mapping that contains a stack variable.
83 MemoryMappingLayout
proc_maps(/*cache_enabled*/true);
84 uptr start
, end
, offset
;
86 while (proc_maps
.Next(&start
, &end
, &offset
, 0, 0, /* protection */0)) {
91 CHECK((uptr
)&rl
>= start
&& (uptr
)&rl
< end
);
93 // Get stacksize from rlimit, but clip it so that it does not overlap
94 // with other mappings.
95 uptr stacksize
= rl
.rlim_cur
;
96 if (stacksize
> end
- prev_end
)
97 stacksize
= end
- prev_end
;
98 // When running with unlimited stack size, we still want to set some limit.
99 // The unlimited stack size is caused by 'ulimit -s unlimited'.
100 // Also, for some reason, GNU make spawns subprocesses with unlimited stack.
101 if (stacksize
> kMaxThreadStackSize
)
102 stacksize
= kMaxThreadStackSize
;
104 *stack_bottom
= end
- stacksize
;
108 pthread_attr_init(&attr
);
109 CHECK_EQ(pthread_getattr_np(pthread_self(), &attr
), 0);
112 my_pthread_attr_getstack(&attr
, &stackaddr
, (size_t*)&stacksize
);
113 pthread_attr_destroy(&attr
);
115 CHECK_LE(stacksize
, kMaxThreadStackSize
); // Sanity check.
116 *stack_top
= (uptr
)stackaddr
+ stacksize
;
117 *stack_bottom
= (uptr
)stackaddr
;
120 bool SetEnv(const char *name
, const char *value
) {
121 void *f
= dlsym(RTLD_NEXT
, "setenv");
124 typedef int(*setenv_ft
)(const char *name
, const char *value
, int overwrite
);
126 CHECK_EQ(sizeof(setenv_f
), sizeof(f
));
127 internal_memcpy(&setenv_f
, &f
, sizeof(f
));
128 return IndirectExternCall(setenv_f
)(name
, value
, 1) == 0;
131 bool SanitizerSetThreadName(const char *name
) {
133 return 0 == prctl(PR_SET_NAME
, (unsigned long)name
, 0, 0, 0); // NOLINT
139 bool SanitizerGetThreadName(char *name
, int max_len
) {
142 if (prctl(PR_GET_NAME
, (unsigned long)buff
, 0, 0, 0)) // NOLINT
144 internal_strncpy(name
, buff
, max_len
);
152 #if !SANITIZER_FREEBSD
153 static uptr g_tls_size
;
157 # define DL_INTERNAL_FUNCTION __attribute__((regparm(3), stdcall))
159 # define DL_INTERNAL_FUNCTION
163 #if !SANITIZER_FREEBSD && !SANITIZER_ANDROID
164 typedef void (*get_tls_func
)(size_t*, size_t*) DL_INTERNAL_FUNCTION
;
165 get_tls_func get_tls
;
166 void *get_tls_static_info_ptr
= dlsym(RTLD_NEXT
, "_dl_get_tls_static_info");
167 CHECK_EQ(sizeof(get_tls
), sizeof(get_tls_static_info_ptr
));
168 internal_memcpy(&get_tls
, &get_tls_static_info_ptr
,
169 sizeof(get_tls_static_info_ptr
));
170 CHECK_NE(get_tls
, 0);
172 size_t tls_align
= 0;
173 IndirectExternCall(get_tls
)(&tls_size
, &tls_align
);
174 g_tls_size
= tls_size
;
175 #endif // !SANITIZER_FREEBSD && !SANITIZER_ANDROID
178 #if (defined(__x86_64__) || defined(__i386__)) && SANITIZER_LINUX
179 // sizeof(struct thread) from glibc.
180 static atomic_uintptr_t kThreadDescriptorSize
;
182 uptr
ThreadDescriptorSize() {
183 uptr val
= atomic_load(&kThreadDescriptorSize
, memory_order_relaxed
);
186 #ifdef _CS_GNU_LIBC_VERSION
188 uptr len
= confstr(_CS_GNU_LIBC_VERSION
, buf
, sizeof(buf
));
189 if (len
< sizeof(buf
) && internal_strncmp(buf
, "glibc 2.", 8) == 0) {
191 int minor
= internal_simple_strtoll(buf
+ 8, &end
, 10);
192 if (end
!= buf
+ 8 && (*end
== '\0' || *end
== '.')) {
193 /* sizeof(struct thread) values from various glibc versions. */
195 val
= 1728; // Assume only one particular version for x32.
197 val
= FIRST_32_SECOND_64(1104, 1696);
199 val
= FIRST_32_SECOND_64(1120, 1728);
201 val
= FIRST_32_SECOND_64(1136, 1728);
203 val
= FIRST_32_SECOND_64(1136, 1712);
204 else if (minor
== 10)
205 val
= FIRST_32_SECOND_64(1168, 1776);
206 else if (minor
<= 12)
207 val
= FIRST_32_SECOND_64(1168, 2288);
209 val
= FIRST_32_SECOND_64(1216, 2304);
212 atomic_store(&kThreadDescriptorSize
, val
, memory_order_relaxed
);
219 // The offset at which pointer to self is located in the thread descriptor.
220 const uptr kThreadSelfOffset
= FIRST_32_SECOND_64(8, 16);
222 uptr
ThreadSelfOffset() {
223 return kThreadSelfOffset
;
228 # if defined(__i386__)
229 asm("mov %%gs:%c1,%0" : "=r"(descr_addr
) : "i"(kThreadSelfOffset
));
230 # elif defined(__x86_64__)
231 asm("mov %%fs:%c1,%0" : "=r"(descr_addr
) : "i"(kThreadSelfOffset
));
233 # error "unsupported CPU arch"
237 #endif // (defined(__x86_64__) || defined(__i386__)) && SANITIZER_LINUX
239 #if SANITIZER_FREEBSD
240 static void **ThreadSelfSegbase() {
242 # if defined(__i386__)
243 // sysarch(I386_GET_GSBASE, segbase);
244 __asm
__volatile("mov %%gs:0, %0" : "=r" (segbase
));
245 # elif defined(__x86_64__)
246 // sysarch(AMD64_GET_FSBASE, segbase);
247 __asm
__volatile("movq %%fs:0, %0" : "=r" (segbase
));
249 # error "unsupported CPU arch for FreeBSD platform"
255 return (uptr
)ThreadSelfSegbase()[2];
257 #endif // SANITIZER_FREEBSD
259 static void GetTls(uptr
*addr
, uptr
*size
) {
261 # if defined(__x86_64__) || defined(__i386__)
262 *addr
= ThreadSelf();
263 *size
= GetTlsSize();
265 *addr
+= ThreadDescriptorSize();
270 #elif SANITIZER_FREEBSD
271 void** segbase
= ThreadSelfSegbase();
276 // tls_size = round(tls_static_space, tcbalign);
278 // dtv[2] = segbase - tls_static_space;
279 void **dtv
= (void**) segbase
[1];
280 *addr
= (uptr
) dtv
[2];
281 *size
= (*addr
== 0) ? 0 : ((uptr
) segbase
[0] - (uptr
) dtv
[2]);
289 #if SANITIZER_FREEBSD
291 GetTls(&addr
, &size
);
298 void GetThreadStackAndTls(bool main
, uptr
*stk_addr
, uptr
*stk_size
,
299 uptr
*tls_addr
, uptr
*tls_size
) {
300 GetTls(tls_addr
, tls_size
);
302 uptr stack_top
, stack_bottom
;
303 GetThreadStackTopAndBottom(main
, &stack_top
, &stack_bottom
);
304 *stk_addr
= stack_bottom
;
305 *stk_size
= stack_top
- stack_bottom
;
308 // If stack and tls intersect, make them non-intersecting.
309 if (*tls_addr
> *stk_addr
&& *tls_addr
< *stk_addr
+ *stk_size
) {
310 CHECK_GT(*tls_addr
+ *tls_size
, *stk_addr
);
311 CHECK_LE(*tls_addr
+ *tls_size
, *stk_addr
+ *stk_size
);
312 *stk_size
-= *tls_size
;
313 *tls_addr
= *stk_addr
+ *stk_size
;
318 void AdjustStackSize(void *attr_
) {
319 pthread_attr_t
*attr
= (pthread_attr_t
*)attr_
;
321 size_t stacksize
= 0;
322 my_pthread_attr_getstack(attr
, (void**)&stackaddr
, &stacksize
);
323 // GLibC will return (0 - stacksize) as the stack address in the case when
324 // stacksize is set, but stackaddr is not.
325 bool stack_set
= (stackaddr
!= 0) && (stackaddr
+ stacksize
!= 0);
326 // We place a lot of tool data into TLS, account for that.
327 const uptr minstacksize
= GetTlsSize() + 128*1024;
328 if (stacksize
< minstacksize
) {
330 if (stacksize
!= 0) {
331 VPrintf(1, "Sanitizer: increasing stacksize %zu->%zu\n", stacksize
,
333 pthread_attr_setstacksize(attr
, minstacksize
);
336 Printf("Sanitizer: pre-allocated stack size is insufficient: "
337 "%zu < %zu\n", stacksize
, minstacksize
);
338 Printf("Sanitizer: pthread_create is likely to fail.\n");
343 #if SANITIZER_ANDROID
344 uptr
GetListOfModules(LoadedModule
*modules
, uptr max_modules
,
345 string_predicate_t filter
) {
346 MemoryMappingLayout
memory_mapping(false);
347 return memory_mapping
.DumpListOfModules(modules
, max_modules
, filter
);
349 #else // SANITIZER_ANDROID
350 # if !SANITIZER_FREEBSD
351 typedef ElfW(Phdr
) Elf_Phdr
;
352 # elif SANITIZER_WORDSIZE == 32 && __FreeBSD_version <= 902001 // v9.2
353 # define Elf_Phdr XElf32_Phdr
354 # define dl_phdr_info xdl_phdr_info
355 # define dl_iterate_phdr(c, b) xdl_iterate_phdr((c), (b))
358 struct DlIteratePhdrData
{
359 LoadedModule
*modules
;
363 string_predicate_t filter
;
366 static int dl_iterate_phdr_cb(dl_phdr_info
*info
, size_t size
, void *arg
) {
367 DlIteratePhdrData
*data
= (DlIteratePhdrData
*)arg
;
368 if (data
->current_n
== data
->max_n
)
370 InternalScopedBuffer
<char> module_name(kMaxPathLength
);
371 module_name
.data()[0] = '\0';
374 // First module is the binary itself.
375 ReadBinaryName(module_name
.data(), module_name
.size());
376 } else if (info
->dlpi_name
) {
377 internal_strncpy(module_name
.data(), info
->dlpi_name
, module_name
.size());
379 if (module_name
.data()[0] == '\0')
381 if (data
->filter
&& !data
->filter(module_name
.data()))
383 void *mem
= &data
->modules
[data
->current_n
];
384 LoadedModule
*cur_module
= new(mem
) LoadedModule(module_name
.data(),
387 for (int i
= 0; i
< info
->dlpi_phnum
; i
++) {
388 const Elf_Phdr
*phdr
= &info
->dlpi_phdr
[i
];
389 if (phdr
->p_type
== PT_LOAD
) {
390 uptr cur_beg
= info
->dlpi_addr
+ phdr
->p_vaddr
;
391 uptr cur_end
= cur_beg
+ phdr
->p_memsz
;
392 bool executable
= phdr
->p_flags
& PF_X
;
393 cur_module
->addAddressRange(cur_beg
, cur_end
, executable
);
399 uptr
GetListOfModules(LoadedModule
*modules
, uptr max_modules
,
400 string_predicate_t filter
) {
402 DlIteratePhdrData data
= {modules
, 0, true, max_modules
, filter
};
403 dl_iterate_phdr(dl_iterate_phdr_cb
, &data
);
404 return data
.current_n
;
406 #endif // SANITIZER_ANDROID
408 uptr indirect_call_wrapper
;
410 void SetIndirectCallWrapper(uptr wrapper
) {
411 CHECK(!indirect_call_wrapper
);
413 indirect_call_wrapper
= wrapper
;
416 void PrepareForSandboxing(__sanitizer_sandbox_arguments
*args
) {
417 // Some kinds of sandboxes may forbid filesystem access, so we won't be able
418 // to read the file mappings from /proc/self/maps. Luckily, neither the
419 // process will be able to load additional libraries, so it's fine to use the
421 MemoryMappingLayout::CacheMemoryMappings();
422 // Same for /proc/self/exe in the symbolizer.
424 Symbolizer::GetOrInit()->PrepareForSandboxing();
425 CovPrepareForSandboxing(args
);
429 } // namespace __sanitizer
431 #endif // SANITIZER_FREEBSD || SANITIZER_LINUX