]> granicus.if.org Git - clang/commitdiff
[Driver] Add Scudo as a possible -fsanitize= option
authorKostya Kortchinsky <kostyak@google.com>
Fri, 3 Nov 2017 17:04:13 +0000 (17:04 +0000)
committerKostya Kortchinsky <kostyak@google.com>
Fri, 3 Nov 2017 17:04:13 +0000 (17:04 +0000)
Summary:
This change adds Scudo as a possible Sanitizer option via -fsanitize=.
This allows for easier static & shared linking of the Scudo library, it allows
us to enforce PIE (otherwise the security of the allocator is moot), and check
for incompatible Sanitizers combo.

In its current form, Scudo is not compatible with any other Sanitizer, but the
plan is to make it work in conjunction with UBsan (-fsanitize=scudo,undefined),
which will require additional work outside of the scope of this change.

Reviewers: eugenis, kcc, alekseyshl

Reviewed By: eugenis, alekseyshl

Subscribers: llvm-commits, srhines

Differential Revision: https://reviews.llvm.org/D39334

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

include/clang/Basic/Sanitizers.def
include/clang/Driver/SanitizerArgs.h
lib/Driver/SanitizerArgs.cpp
lib/Driver/ToolChains/CommonArgs.cpp
lib/Driver/ToolChains/Linux.cpp
lib/Lex/PPMacroExpansion.cpp
test/Driver/fsanitize.c
test/Driver/sanitizer-ld.c

index d6df6171729a8339389d2923904856a124eabcfe..3586fc228d091a626b4dd0534ffe469ddb9cf404 100644 (file)
@@ -135,6 +135,9 @@ SANITIZER("efficiency-working-set", EfficiencyWorkingSet)
 SANITIZER_GROUP("efficiency-all", Efficiency,
                 EfficiencyCacheFrag | EfficiencyWorkingSet)
 
+// Scudo hardened allocator
+SANITIZER("scudo", Scudo)
+
 // Magic group, containing all sanitizers. For example, "-fno-sanitize=all"
 // can be used to disable all the sanitizers.
 SANITIZER_GROUP("all", All, ~0ULL)
index 19309c3f3b7f1e7306312a4dfdd7d42f86b74da2..44083aec16fceb44ba1e2663031cfc4be13fffee 100644 (file)
@@ -72,6 +72,7 @@ class SanitizerArgs {
   bool needsEsanRt() const {
     return Sanitizers.hasOneOf(SanitizerKind::Efficiency);
   }
+  bool needsScudoRt() const { return Sanitizers.has(SanitizerKind::Scudo); }
 
   bool requiresPIE() const;
   bool needsUnwindTables() const;
index 32c1c43a5bd99a0c29e15153613aa7dbfe3b0482..8d9f32f84834be9d5fbe63b0b48da5b9199ee90f 100644 (file)
@@ -30,7 +30,7 @@ enum : SanitizerMask {
   NeedsUbsanCxxRt = Vptr | CFI,
   NotAllowedWithTrap = Vptr,
   NotAllowedWithMinimalRuntime = Vptr,
-  RequiresPIE = DataFlow,
+  RequiresPIE = DataFlow | Scudo,
   NeedsUnwindTables = Address | Thread | Memory | DataFlow,
   SupportsCoverage = Address | KernelAddress | Memory | Leak | Undefined |
                      Integer | Nullability | DataFlow | Fuzzer | FuzzerNoLink,
@@ -173,7 +173,7 @@ static SanitizerMask parseSanitizeTrapArgs(const Driver &D,
 bool SanitizerArgs::needsUbsanRt() const {
   // All of these include ubsan.
   if (needsAsanRt() || needsMsanRt() || needsTsanRt() || needsDfsanRt() ||
-      needsLsanRt() || needsCfiDiagRt())
+      needsLsanRt() || needsCfiDiagRt() || needsScudoRt())
     return false;
 
   return (Sanitizers.Mask & NeedsUbsanRt & ~TrapSanitizers.Mask) ||
@@ -370,17 +370,14 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
 
   // Warn about incompatible groups of sanitizers.
   std::pair<SanitizerMask, SanitizerMask> IncompatibleGroups[] = {
-      std::make_pair(Address, Thread), std::make_pair(Address, Memory),
-      std::make_pair(Thread, Memory), std::make_pair(Leak, Thread),
-      std::make_pair(Leak, Memory), std::make_pair(KernelAddress, Address),
-      std::make_pair(KernelAddress, Leak),
-      std::make_pair(KernelAddress, Thread),
-      std::make_pair(KernelAddress, Memory),
-      std::make_pair(Efficiency, Address),
-      std::make_pair(Efficiency, Leak),
-      std::make_pair(Efficiency, Thread),
-      std::make_pair(Efficiency, Memory),
-      std::make_pair(Efficiency, KernelAddress)};
+      std::make_pair(Address, Thread | Memory),
+      std::make_pair(Thread, Memory),
+      std::make_pair(Leak, Thread | Memory),
+      std::make_pair(KernelAddress, Address| Leak | Thread | Memory),
+      std::make_pair(Efficiency, Address | Leak | Thread | Memory |
+                                 KernelAddress),
+      std::make_pair(Scudo, Address | Leak | Thread | Memory | KernelAddress |
+                            Efficiency) };
   for (auto G : IncompatibleGroups) {
     SanitizerMask Group = G.first;
     if (Kinds & Group) {
index b359cbb77ef89f3ff3f279fff4602944a69a93b3..91f653a53e8772c645eac481813123743c0e0705 100644 (file)
@@ -566,7 +566,6 @@ collectSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
       if (!Args.hasArg(options::OPT_shared) && !TC.getTriple().isAndroid())
         HelperStaticRuntimes.push_back("asan-preinit");
     }
-
     if (SanArgs.needsUbsanRt()) {
       if (SanArgs.requiresMinimalRuntime()) {
         SharedRuntimes.push_back("ubsan_minimal");
@@ -574,6 +573,8 @@ collectSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
         SharedRuntimes.push_back("ubsan_standalone");
       }
     }
+    if (SanArgs.needsScudoRt())
+      SharedRuntimes.push_back("scudo");
   }
 
   // The stats_client library is also statically linked into DSOs.
@@ -630,6 +631,11 @@ collectSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
   }
   if (SanArgs.needsEsanRt())
     StaticRuntimes.push_back("esan");
+  if (SanArgs.needsScudoRt()) {
+    StaticRuntimes.push_back("scudo");
+    if (SanArgs.linkCXXRuntimes())
+      StaticRuntimes.push_back("scudo_cxx");
+  }
 }
 
 // Should be called before we add system libraries (C++ ABI, libstdc++/libc++,
index 613a9f3c88e966bfaf3d9cc5ed77a4110743d84f..9b722166c5f6a8f01adbd67250a68c05a22d7ed1 100644 (file)
@@ -845,9 +845,10 @@ SanitizerMask Linux::getSupportedSanitizers() const {
     Res |= SanitizerKind::Memory;
   if (IsX86_64 || IsMIPS64)
     Res |= SanitizerKind::Efficiency;
-  if (IsX86 || IsX86_64) {
+  if (IsX86 || IsX86_64)
     Res |= SanitizerKind::Function;
-  }
+  if (IsX86_64 || IsMIPS64 || IsAArch64 || IsX86 || IsArmArch)
+    Res |= SanitizerKind::Scudo;
   return Res;
 }
 
index b0330f28813a9332d3017b749d49eacc8b6f59cf..9f0c88dd9769c821a46b9100f92b32fa7b45c443 100644 (file)
@@ -1138,6 +1138,7 @@ static bool HasFeature(const Preprocessor &PP, StringRef Feature) {
       .Case("dataflow_sanitizer", LangOpts.Sanitize.has(SanitizerKind::DataFlow))
       .Case("efficiency_sanitizer",
             LangOpts.Sanitize.hasOneOf(SanitizerKind::Efficiency))
+      .Case("scudo", LangOpts.Sanitize.hasOneOf(SanitizerKind::Scudo))
       // Objective-C features
       .Case("objc_arr", LangOpts.ObjCAutoRefCount) // FIXME: REMOVE?
       .Case("objc_arc", LangOpts.ObjCAutoRefCount)
index dcca96ff3a8974bfd2e93cc6e9cd5b2418371145..3de6fa0b35a4a4e97a25fadfd82bbf6edf029246 100644 (file)
 // CHECK-CFI-NOICALL-MINIMAL: "-fsanitize=cfi-derived-cast,cfi-unrelated-cast,cfi-nvcall,cfi-vcall"
 // CHECK-CFI-NOICALL-MINIMAL: "-fsanitize-trap=cfi-derived-cast,cfi-unrelated-cast,cfi-nvcall,cfi-vcall"
 // CHECK-CFI-NOICALL-MINIMAL: "-fsanitize-minimal-runtime"
+
+// RUN: %clang -target aarch64-linux-gnu -fsanitize=scudo %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SCUDO
+// RUN: %clang -target arm-linux-androideabi -fsanitize=scudo %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SCUDO
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=scudo %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SCUDO
+// RUN: %clang -target i386-linux-gnu -fsanitize=scudo %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SCUDO
+// CHECK-SCUDO: "-fsanitize=scudo"
+
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=scudo %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SCUDO-PIE
+// RUN: %clang -target arm-linux-androideabi -fsanitize=scudo %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SCUDO-PIE
+// CHECK-SCUDO-PIE: "-mrelocation-model" "pic" "-pic-level" "2" "-pic-is-pie"
+// CHECK-SCUDO-PIE: "-pie"
+
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=scudo,undefined %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SCUDO-UBSAN
+// CHECK-SCUDO-UBSAN: "-fsanitize={{.*}}scudo"
+
+// RUN: %clang -target powerpc-unknown-linux -fsanitize=scudo %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-NO-SCUDO
+// CHECK-NO-SCUDO: unsupported option
+
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=scudo,address  %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SCUDO-ASAN
+// CHECK-SCUDO-ASAN: error: invalid argument '-fsanitize=scudo' not allowed with '-fsanitize=address'
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=scudo,leak  %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SCUDO-LSAN
+// CHECK-SCUDO-LSAN: error: invalid argument '-fsanitize=scudo' not allowed with '-fsanitize=leak'
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=scudo,memory  %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SCUDO-MSAN
+// CHECK-SCUDO-MSAN: error: invalid argument '-fsanitize=scudo' not allowed with '-fsanitize=memory'
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=scudo,thread  %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SCUDO-TSAN
+// CHECK-SCUDO-TSAN: error: invalid argument '-fsanitize=scudo' not allowed with '-fsanitize=thread'
index f03714c4b57e012251a042ade9ce946e1b2e5a09..8fc31fe37a650a9f87078272d5b03b39bbb92c62 100644 (file)
 //
 // CHECK-ESAN-LINUX: "{{(.*[^-.0-9A-Z_a-z])?}}ld{{(.exe)?}}"
 // CHECK-ESAN-LINUX: libclang_rt.esan-x86_64.a
+
+// RUN: %clang -fsanitize=scudo %s -### -o %t.o 2>&1 \
+// RUN:     -target i386-unknown-linux -fuse-ld=ld \
+// RUN:     --sysroot=%S/Inputs/basic_linux_tree \
+// RUN:   | FileCheck --check-prefix=CHECK-SCUDO-LINUX %s
+// CHECK-SCUDO-LINUX: "{{.*}}ld{{(.exe)?}}"
+// CHECK-SCUDO-LINUX: "-pie"
+// CHECK-SCUDO-LINUX: "-whole-archive" "{{.*}}libclang_rt.scudo-i386.a" "-no-whole-archive"
+// CHECK-SCUDO-LINUX-NOT: "-lstdc++"
+// CHECK-SCUDO-LINUX: "-lpthread"
+// CHECK-SCUDO-LINUX: "-ldl"
+
+// RUN: %clang -no-canonical-prefixes %s -### -o %t.so -shared 2>&1 \
+// RUN:     -target i386-unknown-linux -fuse-ld=ld -fsanitize=scudo -shared-libsan \
+// RUN:     -resource-dir=%S/Inputs/resource_dir \
+// RUN:     --sysroot=%S/Inputs/basic_linux_tree \
+// RUN:   | FileCheck --check-prefix=CHECK-SCUDO-SHARED-LINUX %s
+//
+// CHECK-SCUDO-SHARED-LINUX: "{{(.*[^-.0-9A-Z_a-z])?}}ld{{(.exe)?}}"
+// CHECK-SCUDO-SHARED-LINUX-NOT: "-lc"
+// CHECK-SCUDO-SHARED-LINUX-NOT: libclang_rt.scudo-i386.a"
+// CHECK-SCUDO-SHARED-LINUX: libclang_rt.scudo-i386.so"
+// CHECK-SCUDO-SHARED-LINUX-NOT: "-lpthread"
+// CHECK-SCUDO-SHARED-LINUX-NOT: "-lrt"
+// CHECK-SCUDO-SHARED-LINUX-NOT: "-ldl"
+// CHECK-SCUDO-SHARED-LINUX-NOT: "-export-dynamic"
+// CHECK-SCUDO-SHARED-LINUX-NOT: "--dynamic-list"
+
+// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
+// RUN:     -target arm-linux-androideabi -fuse-ld=ld -fsanitize=scudo \
+// RUN:     --sysroot=%S/Inputs/basic_android_tree/sysroot \
+// RUN:   | FileCheck --check-prefix=CHECK-SCUDO-ANDROID %s
+//
+// CHECK-SCUDO-ANDROID: "{{(.*[^.0-9A-Z_a-z])?}}ld{{(.exe)?}}"
+// CHECK-SCUDO-ANDROID-NOT: "-lc"
+// CHECK-SCUDO-ANDROID: "-pie"
+// CHECK-SCUDO-ANDROID-NOT: "-lpthread"
+// CHECK-SCUDO-ANDROID: libclang_rt.scudo-arm-android.so"
+// CHECK-SCUDO-ANDROID-NOT: "-lpthread"
+
+// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
+// RUN:     -target arm-linux-androideabi -fuse-ld=ld -fsanitize=scudo \
+// RUN:     --sysroot=%S/Inputs/basic_android_tree/sysroot \
+// RUN:     -static-libsan \
+// RUN:   | FileCheck --check-prefix=CHECK-SCUDO-ANDROID-STATIC %s
+// CHECK-SCUDO-ANDROID-STATIC: "{{(.*[^.0-9A-Z_a-z])?}}ld{{(.exe)?}}"
+// CHECK-SCUDO-ANDROID-STATIC: "-pie"
+// CHECK-SCUDO-ANDROID-STATIC: "-whole-archive" "{{.*}}libclang_rt.scudo-arm-android.a" "-no-whole-archive"
+// CHECK-SCUDO-ANDROID-STATIC-NOT: "-lstdc++"
+// CHECK-SCUDO-ANDROID-STATIC: "-lpthread"