13cab2bb3Spatrick //===-- asan_linux.cpp ----------------------------------------------------===//
23cab2bb3Spatrick //
33cab2bb3Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
43cab2bb3Spatrick // See https://llvm.org/LICENSE.txt for license information.
53cab2bb3Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
63cab2bb3Spatrick //
73cab2bb3Spatrick //===----------------------------------------------------------------------===//
83cab2bb3Spatrick //
93cab2bb3Spatrick // This file is a part of AddressSanitizer, an address sanity checker.
103cab2bb3Spatrick //
113cab2bb3Spatrick // Linux-specific details.
123cab2bb3Spatrick //===----------------------------------------------------------------------===//
133cab2bb3Spatrick
143cab2bb3Spatrick #include "sanitizer_common/sanitizer_platform.h"
153cab2bb3Spatrick #if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \
163cab2bb3Spatrick SANITIZER_SOLARIS
173cab2bb3Spatrick
18*810390e3Srobert # include <dlfcn.h>
19*810390e3Srobert # include <fcntl.h>
20*810390e3Srobert # include <limits.h>
21*810390e3Srobert # include <pthread.h>
22*810390e3Srobert # include <stdio.h>
23*810390e3Srobert # include <sys/mman.h>
24*810390e3Srobert # include <sys/resource.h>
25*810390e3Srobert # include <sys/syscall.h>
26*810390e3Srobert # include <sys/time.h>
27*810390e3Srobert # include <sys/types.h>
28*810390e3Srobert # include <unistd.h>
29*810390e3Srobert # include <unwind.h>
30*810390e3Srobert
313cab2bb3Spatrick # include "asan_interceptors.h"
323cab2bb3Spatrick # include "asan_internal.h"
333cab2bb3Spatrick # include "asan_premap_shadow.h"
343cab2bb3Spatrick # include "asan_thread.h"
353cab2bb3Spatrick # include "sanitizer_common/sanitizer_flags.h"
363cab2bb3Spatrick # include "sanitizer_common/sanitizer_freebsd.h"
37*810390e3Srobert # include "sanitizer_common/sanitizer_hash.h"
383cab2bb3Spatrick # include "sanitizer_common/sanitizer_libc.h"
393cab2bb3Spatrick # include "sanitizer_common/sanitizer_procmaps.h"
403cab2bb3Spatrick
413cab2bb3Spatrick # if SANITIZER_FREEBSD
423cab2bb3Spatrick # include <sys/link_elf.h>
433cab2bb3Spatrick # endif
443cab2bb3Spatrick
453cab2bb3Spatrick # if SANITIZER_SOLARIS
463cab2bb3Spatrick # include <link.h>
473cab2bb3Spatrick # endif
483cab2bb3Spatrick
493cab2bb3Spatrick # if SANITIZER_ANDROID || SANITIZER_FREEBSD || SANITIZER_SOLARIS
503cab2bb3Spatrick # include <ucontext.h>
513cab2bb3Spatrick extern "C" void *_DYNAMIC;
523cab2bb3Spatrick # elif SANITIZER_NETBSD
533cab2bb3Spatrick # include <link_elf.h>
543cab2bb3Spatrick # include <ucontext.h>
553cab2bb3Spatrick extern Elf_Dyn _DYNAMIC;
563cab2bb3Spatrick # else
573cab2bb3Spatrick # include <link.h>
58*810390e3Srobert # include <sys/ucontext.h>
59d89ec533Spatrick extern ElfW(Dyn) _DYNAMIC[];
603cab2bb3Spatrick # endif
613cab2bb3Spatrick
623cab2bb3Spatrick // x86-64 FreeBSD 9.2 and older define 'ucontext_t' incorrectly in
633cab2bb3Spatrick // 32-bit mode.
643cab2bb3Spatrick # if SANITIZER_FREEBSD && (SANITIZER_WORDSIZE == 32) && \
653cab2bb3Spatrick __FreeBSD_version <= 902001 // v9.2
663cab2bb3Spatrick # define ucontext_t xucontext_t
673cab2bb3Spatrick # endif
683cab2bb3Spatrick
693cab2bb3Spatrick typedef enum {
703cab2bb3Spatrick ASAN_RT_VERSION_UNDEFINED = 0,
713cab2bb3Spatrick ASAN_RT_VERSION_DYNAMIC,
723cab2bb3Spatrick ASAN_RT_VERSION_STATIC,
733cab2bb3Spatrick } asan_rt_version_t;
743cab2bb3Spatrick
753cab2bb3Spatrick // FIXME: perhaps also store abi version here?
763cab2bb3Spatrick extern "C" {
773cab2bb3Spatrick SANITIZER_INTERFACE_ATTRIBUTE
783cab2bb3Spatrick asan_rt_version_t __asan_rt_version;
793cab2bb3Spatrick }
803cab2bb3Spatrick
813cab2bb3Spatrick namespace __asan {
823cab2bb3Spatrick
InitializePlatformInterceptors()833cab2bb3Spatrick void InitializePlatformInterceptors() {}
InitializePlatformExceptionHandlers()843cab2bb3Spatrick void InitializePlatformExceptionHandlers() {}
IsSystemHeapAddress(uptr addr)853cab2bb3Spatrick bool IsSystemHeapAddress(uptr addr) { return false; }
863cab2bb3Spatrick
AsanDoesNotSupportStaticLinkage()873cab2bb3Spatrick void *AsanDoesNotSupportStaticLinkage() {
883cab2bb3Spatrick // This will fail to link with -static.
89d89ec533Spatrick return &_DYNAMIC;
903cab2bb3Spatrick }
913cab2bb3Spatrick
923cab2bb3Spatrick # if ASAN_PREMAP_SHADOW
FindPremappedShadowStart(uptr shadow_size_bytes)93d89ec533Spatrick uptr FindPremappedShadowStart(uptr shadow_size_bytes) {
943cab2bb3Spatrick uptr granularity = GetMmapGranularity();
953cab2bb3Spatrick uptr shadow_start = reinterpret_cast<uptr>(&__asan_shadow);
963cab2bb3Spatrick uptr premap_shadow_size = PremapShadowSize();
97d89ec533Spatrick uptr shadow_size = RoundUpTo(shadow_size_bytes, granularity);
983cab2bb3Spatrick // We may have mapped too much. Release extra memory.
993cab2bb3Spatrick UnmapFromTo(shadow_start + shadow_size, shadow_start + premap_shadow_size);
1003cab2bb3Spatrick return shadow_start;
1013cab2bb3Spatrick }
1023cab2bb3Spatrick # endif
1033cab2bb3Spatrick
FindDynamicShadowStart()1043cab2bb3Spatrick uptr FindDynamicShadowStart() {
105d89ec533Spatrick uptr shadow_size_bytes = MemToShadowSize(kHighMemEnd);
1063cab2bb3Spatrick # if ASAN_PREMAP_SHADOW
1073cab2bb3Spatrick if (!PremapShadowFailed())
108d89ec533Spatrick return FindPremappedShadowStart(shadow_size_bytes);
1093cab2bb3Spatrick # endif
1103cab2bb3Spatrick
111*810390e3Srobert return MapDynamicShadow(shadow_size_bytes, ASAN_SHADOW_SCALE,
112d89ec533Spatrick /*min_shadow_base_alignment*/ 0, kHighMemEnd);
1133cab2bb3Spatrick }
1143cab2bb3Spatrick
AsanApplyToGlobals(globals_op_fptr op,const void * needle)1153cab2bb3Spatrick void AsanApplyToGlobals(globals_op_fptr op, const void *needle) {
1163cab2bb3Spatrick UNIMPLEMENTED();
1173cab2bb3Spatrick }
1183cab2bb3Spatrick
FlushUnneededASanShadowMemory(uptr p,uptr size)119d89ec533Spatrick void FlushUnneededASanShadowMemory(uptr p, uptr size) {
120d89ec533Spatrick // Since asan's mapping is compacting, the shadow chunk may be
121d89ec533Spatrick // not page-aligned, so we only flush the page-aligned portion.
122d89ec533Spatrick ReleaseMemoryPagesToOS(MemToShadow(p), MemToShadow(p + size));
123d89ec533Spatrick }
124d89ec533Spatrick
1253cab2bb3Spatrick # if SANITIZER_ANDROID
1263cab2bb3Spatrick // FIXME: should we do anything for Android?
AsanCheckDynamicRTPrereqs()1273cab2bb3Spatrick void AsanCheckDynamicRTPrereqs() {}
AsanCheckIncompatibleRT()1283cab2bb3Spatrick void AsanCheckIncompatibleRT() {}
1293cab2bb3Spatrick # else
FindFirstDSOCallback(struct dl_phdr_info * info,size_t size,void * data)1303cab2bb3Spatrick static int FindFirstDSOCallback(struct dl_phdr_info *info, size_t size,
1313cab2bb3Spatrick void *data) {
132*810390e3Srobert VReport(2, "info->dlpi_name = %s\tinfo->dlpi_addr = %p\n", info->dlpi_name,
133*810390e3Srobert (void *)info->dlpi_addr);
1343cab2bb3Spatrick
135*810390e3Srobert const char **name = (const char **)data;
1363cab2bb3Spatrick
1373cab2bb3Spatrick // Ignore first entry (the main program)
138*810390e3Srobert if (!*name) {
139*810390e3Srobert *name = "";
1403cab2bb3Spatrick return 0;
1413cab2bb3Spatrick }
1423cab2bb3Spatrick
143*810390e3Srobert # if SANITIZER_LINUX
144*810390e3Srobert // Ignore vDSO. glibc versions earlier than 2.15 (and some patched
145*810390e3Srobert // by distributors) return an empty name for the vDSO entry, so
146*810390e3Srobert // detect this as well.
147*810390e3Srobert if (!info->dlpi_name[0] ||
148*810390e3Srobert internal_strncmp(info->dlpi_name, "linux-", sizeof("linux-") - 1) == 0)
1493cab2bb3Spatrick return 0;
1503cab2bb3Spatrick # endif
1513cab2bb3Spatrick
152*810390e3Srobert *name = info->dlpi_name;
1533cab2bb3Spatrick return 1;
1543cab2bb3Spatrick }
1553cab2bb3Spatrick
IsDynamicRTName(const char * libname)1563cab2bb3Spatrick static bool IsDynamicRTName(const char *libname) {
1573cab2bb3Spatrick return internal_strstr(libname, "libclang_rt.asan") ||
1583cab2bb3Spatrick internal_strstr(libname, "libasan.so");
1593cab2bb3Spatrick }
1603cab2bb3Spatrick
ReportIncompatibleRT()1613cab2bb3Spatrick static void ReportIncompatibleRT() {
1623cab2bb3Spatrick Report("Your application is linked against incompatible ASan runtimes.\n");
1633cab2bb3Spatrick Die();
1643cab2bb3Spatrick }
1653cab2bb3Spatrick
AsanCheckDynamicRTPrereqs()1663cab2bb3Spatrick void AsanCheckDynamicRTPrereqs() {
1673cab2bb3Spatrick if (!ASAN_DYNAMIC || !flags()->verify_asan_link_order)
1683cab2bb3Spatrick return;
1693cab2bb3Spatrick
1703cab2bb3Spatrick // Ensure that dynamic RT is the first DSO in the list
1713cab2bb3Spatrick const char *first_dso_name = nullptr;
1723cab2bb3Spatrick dl_iterate_phdr(FindFirstDSOCallback, &first_dso_name);
173*810390e3Srobert if (first_dso_name && first_dso_name[0] && !IsDynamicRTName(first_dso_name)) {
174*810390e3Srobert Report(
175*810390e3Srobert "ASan runtime does not come first in initial library list; "
1763cab2bb3Spatrick "you should either link runtime to your application or "
1773cab2bb3Spatrick "manually preload it with LD_PRELOAD.\n");
1783cab2bb3Spatrick Die();
1793cab2bb3Spatrick }
1803cab2bb3Spatrick }
1813cab2bb3Spatrick
AsanCheckIncompatibleRT()1823cab2bb3Spatrick void AsanCheckIncompatibleRT() {
1833cab2bb3Spatrick if (ASAN_DYNAMIC) {
1843cab2bb3Spatrick if (__asan_rt_version == ASAN_RT_VERSION_UNDEFINED) {
1853cab2bb3Spatrick __asan_rt_version = ASAN_RT_VERSION_DYNAMIC;
1863cab2bb3Spatrick } else if (__asan_rt_version != ASAN_RT_VERSION_DYNAMIC) {
1873cab2bb3Spatrick ReportIncompatibleRT();
1883cab2bb3Spatrick }
1893cab2bb3Spatrick } else {
1903cab2bb3Spatrick if (__asan_rt_version == ASAN_RT_VERSION_UNDEFINED) {
1913cab2bb3Spatrick // Ensure that dynamic runtime is not present. We should detect it
1923cab2bb3Spatrick // as early as possible, otherwise ASan interceptors could bind to
1933cab2bb3Spatrick // the functions in dynamic ASan runtime instead of the functions in
1943cab2bb3Spatrick // system libraries, causing crashes later in ASan initialization.
1953cab2bb3Spatrick MemoryMappingLayout proc_maps(/*cache_enabled*/ true);
1963cab2bb3Spatrick char filename[PATH_MAX];
1973cab2bb3Spatrick MemoryMappedSegment segment(filename, sizeof(filename));
1983cab2bb3Spatrick while (proc_maps.Next(&segment)) {
1993cab2bb3Spatrick if (IsDynamicRTName(segment.filename)) {
200*810390e3Srobert Report(
201*810390e3Srobert "Your application is linked against "
2023cab2bb3Spatrick "incompatible ASan runtimes.\n");
2033cab2bb3Spatrick Die();
2043cab2bb3Spatrick }
2053cab2bb3Spatrick }
2063cab2bb3Spatrick __asan_rt_version = ASAN_RT_VERSION_STATIC;
2073cab2bb3Spatrick } else if (__asan_rt_version != ASAN_RT_VERSION_STATIC) {
2083cab2bb3Spatrick ReportIncompatibleRT();
2093cab2bb3Spatrick }
2103cab2bb3Spatrick }
2113cab2bb3Spatrick }
2123cab2bb3Spatrick # endif // SANITIZER_ANDROID
2133cab2bb3Spatrick
214*810390e3Srobert # if ASAN_INTERCEPT_SWAPCONTEXT
215*810390e3Srobert constexpr u32 kAsanContextStackFlagsMagic = 0x51260eea;
2163cab2bb3Spatrick
HashContextStack(const ucontext_t & ucp)217*810390e3Srobert static int HashContextStack(const ucontext_t &ucp) {
218*810390e3Srobert MurMur2Hash64Builder hash(kAsanContextStackFlagsMagic);
219*810390e3Srobert hash.add(reinterpret_cast<uptr>(ucp.uc_stack.ss_sp));
220*810390e3Srobert hash.add(ucp.uc_stack.ss_size);
221*810390e3Srobert return static_cast<int>(hash.get());
2223cab2bb3Spatrick }
2233cab2bb3Spatrick
SignContextStack(void * context)224*810390e3Srobert void SignContextStack(void *context) {
225*810390e3Srobert ucontext_t *ucp = reinterpret_cast<ucontext_t *>(context);
226*810390e3Srobert ucp->uc_stack.ss_flags = HashContextStack(*ucp);
227*810390e3Srobert }
228*810390e3Srobert
ReadContextStack(void * context,uptr * stack,uptr * ssize)229*810390e3Srobert void ReadContextStack(void *context, uptr *stack, uptr *ssize) {
230*810390e3Srobert const ucontext_t *ucp = reinterpret_cast<const ucontext_t *>(context);
231*810390e3Srobert if (HashContextStack(*ucp) == ucp->uc_stack.ss_flags) {
232*810390e3Srobert *stack = reinterpret_cast<uptr>(ucp->uc_stack.ss_sp);
233*810390e3Srobert *ssize = ucp->uc_stack.ss_size;
234*810390e3Srobert return;
235*810390e3Srobert }
236*810390e3Srobert *stack = 0;
237*810390e3Srobert *ssize = 0;
238*810390e3Srobert }
239*810390e3Srobert # endif // ASAN_INTERCEPT_SWAPCONTEXT
240*810390e3Srobert
AsanDlSymNext(const char * sym)241*810390e3Srobert void *AsanDlSymNext(const char *sym) { return dlsym(RTLD_NEXT, sym); }
242*810390e3Srobert
HandleDlopenInit()2433cab2bb3Spatrick bool HandleDlopenInit() {
2443cab2bb3Spatrick // Not supported on this platform.
2453cab2bb3Spatrick static_assert(!SANITIZER_SUPPORTS_INIT_FOR_DLOPEN,
2463cab2bb3Spatrick "Expected SANITIZER_SUPPORTS_INIT_FOR_DLOPEN to be false");
2473cab2bb3Spatrick return false;
2483cab2bb3Spatrick }
2493cab2bb3Spatrick
2503cab2bb3Spatrick } // namespace __asan
2513cab2bb3Spatrick
2523cab2bb3Spatrick #endif // SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD ||
2533cab2bb3Spatrick // SANITIZER_SOLARIS
254