From 86abf9aeb3138dcee9d2c110a911dbe8108fdd62 Mon Sep 17 00:00:00 2001 From: Alex Shlyapnikov Date: Thu, 23 Mar 2017 15:57:58 +0000 Subject: [PATCH] Bypass potential libc's sysconf interceptors Summary: sysconf(_SC_PAGESIZE) is called very early during sanitizer init and any instrumented code (sysconf() wrapper/interceptor will likely be instrumented) calling back to sanitizer before init is done will most surely crash. 2nd attempt, now with glibc version checks (D31092 was reverted). Reviewers: eugenis Subscribers: kubamracek, llvm-commits Differential Revision: https://reviews.llvm.org/D31221 llvm-svn: 298613 --- .../lib/sanitizer_common/sanitizer_linux.cc | 16 ++++++++++++++ .../Linux/sysconf_interceptor_bypass_test.cc | 25 ++++++++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 compiler-rt/test/sanitizer_common/TestCases/Linux/sysconf_interceptor_bypass_test.cc diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc index 24707c7..ab65e2d 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc @@ -77,6 +77,20 @@ extern char **environ; // provided by crt1 #include #endif +#ifndef __GLIBC_PREREQ +#define __GLIBC_PREREQ(x, y) 0 +#endif + +#if SANITIZER_LINUX && __GLIBC_PREREQ(2, 16) +# define SANITIZER_USE_GETAUXVAL 1 +#else +# define SANITIZER_USE_GETAUXVAL 0 +#endif + +#if SANITIZER_USE_GETAUXVAL +#include +#endif + #if SANITIZER_LINUX // struct kernel_timeval { @@ -805,6 +819,8 @@ uptr GetPageSize() { return 4096; #elif SANITIZER_LINUX && (defined(__x86_64__) || defined(__i386__)) return EXEC_PAGESIZE; +#elif SANITIZER_USE_GETAUXVAL + return getauxval(AT_PAGESZ); #else return sysconf(_SC_PAGESIZE); // EXEC_PAGESIZE may not be trustworthy. #endif diff --git a/compiler-rt/test/sanitizer_common/TestCases/Linux/sysconf_interceptor_bypass_test.cc b/compiler-rt/test/sanitizer_common/TestCases/Linux/sysconf_interceptor_bypass_test.cc new file mode 100644 index 0000000..eb4deac --- /dev/null +++ b/compiler-rt/test/sanitizer_common/TestCases/Linux/sysconf_interceptor_bypass_test.cc @@ -0,0 +1,25 @@ +// RUN: %clangxx -O2 %s -o %t && %run %t 2>&1 | FileCheck %s + +#include + +// getauxval() used instead of sysconf() in GetPageSize() is defined starting +// glbc version 2.16. +#if defined(__GLIBC_PREREQ) && __GLIBC_PREREQ(2, 16) +extern "C" long sysconf(int name) { + fprintf(stderr, "sysconf wrapper called\n"); + return 0; +} +#endif // defined(__GLIBC_PREREQ) && __GLIBC_PREREQ(2, 16) + +int main() { + // All we need to check is that the sysconf() interceptor defined above was + // not called. Should it get called, it will crash right there, any + // instrumented code executed before sanitizer init is finished will crash + // accessing non-initialized sanitizer internals. Even if it will not crash + // in some configuration, it should never be called anyway. + fprintf(stderr, "Passed\n"); + // CHECK-NOT: sysconf wrapper called + // CHECK: Passed + // CHECK-NOT: sysconf wrapper called + return 0; +} -- 2.7.4