From f80a27e3c6190a9aaec4454696cd4c162e3164e6 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Fri, 14 Oct 2016 19:51:36 +0000 Subject: [PATCH] [linux] When pre-reserving stack pages to work around broken address space layout for PIE binaries, ask the OS how much stack space is already in use to avoid stack overflow if we are run with more than 512K of combined command line arguments + environment variables. llvm-svn: 284271 --- clang/tools/driver/cc1_main.cpp | 42 ++++++++++++++++++++++++++++++++++------- 1 file changed, 35 insertions(+), 7 deletions(-) diff --git a/clang/tools/driver/cc1_main.cpp b/clang/tools/driver/cc1_main.cpp index 45d44a0..0d54278 100644 --- a/clang/tools/driver/cc1_main.cpp +++ b/clang/tools/driver/cc1_main.cpp @@ -80,20 +80,48 @@ void initializePollyPasses(llvm::PassRegistry &Registry); static const int kSufficientStack = 8 << 20; #if defined(__linux__) && defined(__PIE__) +static size_t getCurrentStackAllocation() { + // If we can't compute the current stack usage, allow for 512K of command + // line arguments and environment. + size_t Usage = 512 * 1024; + if (FILE *StatFile = fopen("/proc/self/stat", "r")) { + // We assume that the stack extends from its current address to the end of + // the environment space. In reality, there is another string literal (the + // program name) after the environment, but this is close enough (we only + // need to be within 100K or so). + unsigned long StackPtr, EnvEnd; + if (fscanf(StatFile, + "%*d %*s %*c %*d %*d %*d %*d %*d %*u %*lu %*lu %*lu %*lu %*lu " + "%*lu %*ld %*ld %*ld %*ld %*ld %*ld %*llu %*lu %*ld %*lu %*lu " + "%*lu %*lu %lu %*lu %*lu %*lu %*lu %*lu %*llu %*lu %*lu %*d %*d " + "%*u %*u %*llu %*lu %*ld %*lu %*lu %*lu %*lu %*lu %*lu %lu %*d", + &StackPtr, &EnvEnd) == 2) { + Usage = StackPtr < EnvEnd ? EnvEnd - StackPtr : StackPtr - EnvEnd; + } + fclose(StatFile); + } + return Usage; +} + +#include + LLVM_ATTRIBUTE_NOINLINE -static void ensureStackAddressSpace() { +static void ensureStackAddressSpace(int ExtraChunks = 0) { // Linux kernels prior to 4.1 will sometimes locate the heap of a PIE binary // relatively close to the stack (they are only guaranteed to be 128MiB // apart). This results in crashes if we happen to heap-allocate more than // 128MiB before we reach our stack high-water mark. // // To avoid these crashes, ensure that we have sufficient virtual memory - // pages allocated before we start running by touching an early page. (We - // allow 512KiB for kernel/libc-provided data such as command-line arguments - // and environment variables, and for main and cc1_main) - volatile char ReservedStack[kSufficientStack - 512 * 1024]; - volatile int N = 0; - (void)+ReservedStack[N]; + // pages allocated before we start running. + size_t Curr = getCurrentStackAllocation(); + const int kTargetStack = kSufficientStack - 256 * 1024; + if (Curr < kTargetStack) { + volatile char *volatile Alloc = + static_cast(alloca(kTargetStack - Curr)); + Alloc[0] = 0; + Alloc[kTargetStack - Curr - 1] = 0; + } } #else static void ensureStackAddressSpace() {} -- 2.7.4