11e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//===-- asan_linux.cc -----------------------------------------------------===//
21e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//
31e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//                     The LLVM Compiler Infrastructure
41e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//
51e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// This file is distributed under the University of Illinois Open Source
61e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// License. See LICENSE.TXT for details.
71e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//
81e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//===----------------------------------------------------------------------===//
91e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//
101e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// This file is a part of AddressSanitizer, an address sanity checker.
111e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//
121e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// Linux-specific details.
131e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//===----------------------------------------------------------------------===//
1424e13723f8477d8c42ab8b2a7f4f69fc089842f1Evgeniy Stepanov
1524e13723f8477d8c42ab8b2a7f4f69fc089842f1Evgeniy Stepanov#include "sanitizer_common/sanitizer_platform.h"
162d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_FREEBSD || SANITIZER_LINUX
171e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
18df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany#include "asan_interceptors.h"
191e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_internal.h"
20c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany#include "asan_thread.h"
212d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include "sanitizer_common/sanitizer_flags.h"
226a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines#include "sanitizer_common/sanitizer_freebsd.h"
23ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#include "sanitizer_common/sanitizer_libc.h"
246895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov#include "sanitizer_common/sanitizer_procmaps.h"
251e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
26c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany#include <sys/time.h>
27c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany#include <sys/resource.h>
281e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include <sys/mman.h>
291e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include <sys/syscall.h>
30de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany#include <sys/types.h>
316a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines#include <dlfcn.h>
32de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany#include <fcntl.h>
33c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany#include <pthread.h>
34df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany#include <stdio.h>
351e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include <unistd.h>
369cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov#include <unwind.h>
371e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
382d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_FREEBSD
392d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include <sys/link_elf.h>
409107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany#endif
419107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany
422d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_ANDROID || SANITIZER_FREEBSD
432d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include <ucontext.h>
44aa33a50c9d0f3e3f22c8b21fa7309ec91f9d939aEvgeniy Stepanovextern "C" void* _DYNAMIC;
452d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else
462d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include <sys/ucontext.h>
472d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include <link.h>
482d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
492d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
506a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines// x86-64 FreeBSD 9.2 and older define 'ucontext_t' incorrectly in
516a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines// 32-bit mode.
526a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines#if SANITIZER_FREEBSD && (SANITIZER_WORDSIZE == 32) && \
536a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  __FreeBSD_version <= 902001  // v9.2
546a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines#define ucontext_t xucontext_t
552d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
562d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
572d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinestypedef enum {
582d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  ASAN_RT_VERSION_UNDEFINED = 0,
592d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  ASAN_RT_VERSION_DYNAMIC,
602d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  ASAN_RT_VERSION_STATIC,
612d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} asan_rt_version_t;
622d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
632d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// FIXME: perhaps also store abi version here?
642d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesextern "C" {
652d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesSANITIZER_INTERFACE_ATTRIBUTE
662d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesasan_rt_version_t  __asan_rt_version;
672d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
68aa33a50c9d0f3e3f22c8b21fa7309ec91f9d939aEvgeniy Stepanov
691e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanynamespace __asan {
701e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
717c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainarvoid InitializePlatformInterceptors() {}
72c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarvoid InitializePlatformExceptionHandlers() {}
737c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar
741e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid *AsanDoesNotSupportStaticLinkage() {
751e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  // This will fail to link with -static.
76efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany  return &_DYNAMIC;  // defined in link.h
771e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
781e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
79c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarvoid AsanApplyToGlobals(globals_op_fptr op, const void *needle) {
80c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  UNIMPLEMENTED();
81c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar}
82c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar
8383cb7877f608eb9b3d65981095216842f686c527Evgeniy Stepanov#if SANITIZER_ANDROID
842d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// FIXME: should we do anything for Android?
852d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid AsanCheckDynamicRTPrereqs() {}
862d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid AsanCheckIncompatibleRT() {}
872d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else
882d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesstatic int FindFirstDSOCallback(struct dl_phdr_info *info, size_t size,
892d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                                void *data) {
902d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  // Continue until the first dynamic library is found
912d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  if (!info->dlpi_name || info->dlpi_name[0] == 0)
922d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    return 0;
932d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
946a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  // Ignore vDSO
956a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  if (internal_strncmp(info->dlpi_name, "linux-", sizeof("linux-") - 1) == 0)
966a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines    return 0;
976a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines
982d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  *(const char **)data = info->dlpi_name;
992d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return 1;
1002d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
1012d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
1022d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesstatic bool IsDynamicRTName(const char *libname) {
1032d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_strstr(libname, "libclang_rt.asan") ||
1042d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    internal_strstr(libname, "libasan.so");
1052d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
1062d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
1072d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesstatic void ReportIncompatibleRT() {
1082d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  Report("Your application is linked against incompatible ASan runtimes.\n");
1092d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  Die();
1102d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
1112d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
1122d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid AsanCheckDynamicRTPrereqs() {
113cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  if (!ASAN_DYNAMIC)
114cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar    return;
115cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar
1162d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  // Ensure that dynamic RT is the first DSO in the list
117799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  const char *first_dso_name = nullptr;
1182d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  dl_iterate_phdr(FindFirstDSOCallback, &first_dso_name);
1192d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  if (first_dso_name && !IsDynamicRTName(first_dso_name)) {
1202d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    Report("ASan runtime does not come first in initial library list; "
1212d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines           "you should either link runtime to your application or "
1222d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines           "manually preload it with LD_PRELOAD.\n");
1232d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    Die();
1242d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  }
1252d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
1262d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
1272d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid AsanCheckIncompatibleRT() {
1282d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  if (ASAN_DYNAMIC) {
1292d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    if (__asan_rt_version == ASAN_RT_VERSION_UNDEFINED) {
1302d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      __asan_rt_version = ASAN_RT_VERSION_DYNAMIC;
1312d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    } else if (__asan_rt_version != ASAN_RT_VERSION_DYNAMIC) {
1322d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      ReportIncompatibleRT();
1332d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    }
1342d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  } else {
1352d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    if (__asan_rt_version == ASAN_RT_VERSION_UNDEFINED) {
1362d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      // Ensure that dynamic runtime is not present. We should detect it
1372d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      // as early as possible, otherwise ASan interceptors could bind to
1382d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      // the functions in dynamic ASan runtime instead of the functions in
1392d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      // system libraries, causing crashes later in ASan initialization.
1402d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      MemoryMappingLayout proc_maps(/*cache_enabled*/true);
1412d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      char filename[128];
142799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar      while (proc_maps.Next(nullptr, nullptr, nullptr, filename,
143799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar                            sizeof(filename), nullptr)) {
1442d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines        if (IsDynamicRTName(filename)) {
1452d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines          Report("Your application is linked against "
1462d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                 "incompatible ASan runtimes.\n");
1472d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines          Die();
1482d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines        }
1492d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      }
1502d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      __asan_rt_version = ASAN_RT_VERSION_STATIC;
1512d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    } else if (__asan_rt_version != ASAN_RT_VERSION_STATIC) {
1522d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      ReportIncompatibleRT();
1532d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    }
1542d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  }
1552d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
156799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#endif // SANITIZER_ANDROID
15775b19ebf25af204cf209d108997272822241d6daAlexander Potapenko
15883cb7877f608eb9b3d65981095216842f686c527Evgeniy Stepanov#if !SANITIZER_ANDROID
15957db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonovvoid ReadContextStack(void *context, uptr *stack, uptr *ssize) {
160f3950c6d6acf53fe60735f6d38715c1ea6df814bAlexey Samsonov  ucontext_t *ucp = (ucontext_t*)context;
16157db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov  *stack = (uptr)ucp->uc_stack.ss_sp;
16257db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov  *ssize = ucp->uc_stack.ss_size;
163f3950c6d6acf53fe60735f6d38715c1ea6df814bAlexey Samsonov}
164f3950c6d6acf53fe60735f6d38715c1ea6df814bAlexey Samsonov#else
16557db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonovvoid ReadContextStack(void *context, uptr *stack, uptr *ssize) {
166ca2849c2819b5c7a8771a1e8bc449cf8f5ef6527Alexey Samsonov  UNIMPLEMENTED();
167f3950c6d6acf53fe60735f6d38715c1ea6df814bAlexey Samsonov}
168f3950c6d6acf53fe60735f6d38715c1ea6df814bAlexey Samsonov#endif
169f3950c6d6acf53fe60735f6d38715c1ea6df814bAlexey Samsonov
1706a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hinesvoid *AsanDlSymNext(const char *sym) {
1716a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  return dlsym(RTLD_NEXT, sym);
1726a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines}
1736a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines
174799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar} // namespace __asan
175d6567c5166412f6acdde851e767c26f332d51d3dKostya Serebryany
176799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#endif // SANITIZER_FREEBSD || SANITIZER_LINUX
177