[safestack] Add option for non-TLS unsafe stack pointer.
authorEvgeniy Stepanov <eugeni.stepanov@gmail.com>
Tue, 22 Dec 2015 00:13:11 +0000 (00:13 +0000)
committerEvgeniy Stepanov <eugeni.stepanov@gmail.com>
Tue, 22 Dec 2015 00:13:11 +0000 (00:13 +0000)
This patch adds an option, -safe-stack-no-tls, for using normal
storage instead of thread-local storage for the unsafe stack pointer.
This can be useful when SafeStack is applied to an operating system
kernel.

http://reviews.llvm.org/D15673

Patch by Michael LeMay.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@256221 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/Instrumentation/SafeStack.cpp
test/Transforms/SafeStack/array.ll

index 4441663fc6de522bb30d53da446864ea8c03dea9..abed465f102d26a52c77bb5eb7a415b70cb61a5e 100644 (file)
@@ -47,6 +47,17 @@ using namespace llvm;
 
 #define DEBUG_TYPE "safestack"
 
+enum UnsafeStackPtrStorageVal { ThreadLocalUSP, SingleThreadUSP };
+
+static cl::opt<UnsafeStackPtrStorageVal> USPStorage("safe-stack-usp-storage",
+    cl::Hidden, cl::init(ThreadLocalUSP),
+    cl::desc("Type of storage for the unsafe stack pointer"),
+    cl::values(clEnumValN(ThreadLocalUSP, "thread-local",
+                          "Thread-local storage"),
+               clEnumValN(SingleThreadUSP, "single-thread",
+                          "Non-thread-local storage"),
+               clEnumValEnd));
+
 namespace llvm {
 
 STATISTIC(NumFunctions, "Total number of functions");
@@ -344,19 +355,25 @@ Value *SafeStack::getOrCreateUnsafeStackPtr(IRBuilder<> &IRB, Function &F) {
   auto UnsafeStackPtr =
       dyn_cast_or_null<GlobalVariable>(M.getNamedValue(UnsafeStackPtrVar));
 
+  bool UseTLS = USPStorage == ThreadLocalUSP;
+
   if (!UnsafeStackPtr) {
+    auto TLSModel = UseTLS ?
+        GlobalValue::InitialExecTLSModel :
+        GlobalValue::NotThreadLocal;
     // The global variable is not defined yet, define it ourselves.
     // We use the initial-exec TLS model because we do not support the
     // variable living anywhere other than in the main executable.
     UnsafeStackPtr = new GlobalVariable(
         M, StackPtrTy, false, GlobalValue::ExternalLinkage, nullptr,
-        UnsafeStackPtrVar, nullptr, GlobalValue::InitialExecTLSModel);
+        UnsafeStackPtrVar, nullptr, TLSModel);
   } else {
     // The variable exists, check its type and attributes.
     if (UnsafeStackPtr->getValueType() != StackPtrTy)
       report_fatal_error(Twine(UnsafeStackPtrVar) + " must have void* type");
-    if (!UnsafeStackPtr->isThreadLocal())
-      report_fatal_error(Twine(UnsafeStackPtrVar) + " must be thread-local");
+    if (UseTLS != UnsafeStackPtr->isThreadLocal())
+      report_fatal_error(Twine(UnsafeStackPtrVar) + " must " +
+                         (UseTLS ? "" : "not ") + "be thread-local");
   }
   return UnsafeStackPtr;
 }
index b2454dc2bb9e85c00aab5e494c7cd054bb52dea8..564213e6d58fa3d02cce7105ff17ef645e95aafd 100644 (file)
@@ -1,9 +1,14 @@
 ; RUN: opt -safe-stack -S -mtriple=i386-pc-linux-gnu < %s -o - | FileCheck %s
+; RUN: opt -safe-stack -safe-stack-usp-storage=single-thread -S -mtriple=i386-pc-linux-gnu < %s -o - | FileCheck -check-prefix=SINGLE-THREAD %s
 ; RUN: opt -safe-stack -S -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck %s
+; RUN: opt -safe-stack -safe-stack-usp-storage=single-thread -S -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck -check-prefix=SINGLE-THREAD %s
 
 ; array [4 x i8]
 ; Requires protector.
 
+; CHECK: @__safestack_unsafe_stack_ptr = external thread_local(initialexec) global i8*
+; SINGLE-THREAD: @__safestack_unsafe_stack_ptr = external global i8*
+
 define void @foo(i8* %a) nounwind uwtable safestack {
 entry:
   ; CHECK: %[[USP:.*]] = load i8*, i8** @__safestack_unsafe_stack_ptr