r242286 - CodeGen: Improve CFI type blacklisting mechanism.

Peter Collingbourne peter at pcc.me.uk
Wed Jul 15 05:15:57 PDT 2015


Author: pcc
Date: Wed Jul 15 07:15:56 2015
New Revision: 242286

URL: http://llvm.org/viewvc/llvm-project?rev=242286&view=rev
Log:
CodeGen: Improve CFI type blacklisting mechanism.

We now use the sanitizer special case list to decide which types to blacklist.
We also support a special blacklist entry for types with a uuid attribute,
which are generally COM types whose virtual tables are defined externally.

Differential Revision: http://reviews.llvm.org/D11096

Added:
    cfe/trunk/test/CodeGenCXX/cfi-blacklist.cpp
Modified:
    cfe/trunk/docs/ControlFlowIntegrity.rst
    cfe/trunk/lib/CodeGen/CGClass.cpp
    cfe/trunk/lib/CodeGen/CGVTables.cpp
    cfe/trunk/lib/Driver/SanitizerArgs.cpp

Modified: cfe/trunk/docs/ControlFlowIntegrity.rst
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/ControlFlowIntegrity.rst?rev=242286&r1=242285&r2=242286&view=diff
==============================================================================
--- cfe/trunk/docs/ControlFlowIntegrity.rst (original)
+++ cfe/trunk/docs/ControlFlowIntegrity.rst Wed Jul 15 07:15:56 2015
@@ -41,11 +41,9 @@ derived class of the static type of the
 This CFI scheme can be enabled on its own using ``-fsanitize=cfi-vcall``.
 
 For this scheme to work, all translation units containing the definition
-of a virtual member function (whether inline or not) must be compiled
-with ``-fsanitize=cfi-vcall`` enabled and be statically linked into the
-program. Classes in the C++ standard library (under namespace ``std``) are
-exempted from checking, and therefore programs may be linked against a
-pre-built standard library, but this may change in the future.
+of a virtual member function (whether inline or not), other than members
+of :ref:`blacklisted <cfi-blacklist>` types, must be compiled with
+``-fsanitize=cfi-vcall`` enabled and be statically linked into the program.
 
 Performance
 ~~~~~~~~~~~
@@ -85,15 +83,13 @@ If a program as a matter of policy forbi
 restriction can normally be enforced. However it may in some cases be necessary
 for a function to perform a forbidden cast to conform with an external API
 (e.g. the ``allocate`` member function of a standard library allocator). Such
-functions may be blacklisted using a :doc:`SanitizerSpecialCaseList`.
+functions may be :ref:`blacklisted <cfi-blacklist>`.
 
 For this scheme to work, all translation units containing the definition
-of a virtual member function (whether inline or not) must be compiled with
+of a virtual member function (whether inline or not), other than members
+of :ref:`blacklisted <cfi-blacklist>` types, must be compiled with
 ``-fsanitize=cfi-derived-cast`` or ``-fsanitize=cfi-unrelated-cast`` enabled
-and be statically linked into the program. Classes in the C++ standard library
-(under namespace ``std``) are exempted from checking, and therefore programs
-may be linked against a pre-built standard library, but this may change in
-the future.
+and be statically linked into the program.
 
 Non-Virtual Member Function Call Checking
 -----------------------------------------
@@ -106,11 +102,9 @@ polymorphic class type.  This CFI scheme
 ``-fsanitize=cfi-nvcall``.
 
 For this scheme to work, all translation units containing the definition
-of a virtual member function (whether inline or not) must be compiled
-with ``-fsanitize=cfi-nvcall`` enabled and be statically linked into the
-program. Classes in the C++ standard library (under namespace ``std``) are
-exempted from checking, and therefore programs may be linked against a
-pre-built standard library, but this may change in the future.
+of a virtual member function (whether inline or not), other than members
+of :ref:`blacklisted <cfi-blacklist>` types, must be compiled with
+``-fsanitize=cfi-nvcall`` enabled and be statically linked into the program.
 
 .. _cfi-strictness:
 
@@ -129,6 +123,32 @@ member functions on class instances with
 most compilers and should not have security implications, so we allow it by
 default. It can be disabled with ``-fsanitize=cfi-cast-strict``.
 
+.. _cfi-blacklist:
+
+Blacklist
+---------
+
+A :doc:`SanitizerSpecialCaseList` can be used to relax CFI checks for certain
+source files, functions and types using the ``src``, ``fun`` and ``type``
+entity types.
+
+In addition, if a type has a ``uuid`` attribute and the blacklist contains
+the type entry ``attr:uuid``, CFI checks are suppressed for that type. This
+allows all COM types to be easily blacklisted, which is useful as COM types
+are typically defined outside of the linked program.
+
+.. code-block:: bash
+
+    # Suppress checking for code in a file.
+    src:bad_file.cpp
+    src:bad_header.h
+    # Ignore all functions with names containing MyFooBar.
+    fun:*MyFooBar*
+    # Ignore all types in the standard library.
+    type:std::*
+    # Ignore all types with a uuid attribute.
+    type:attr:uuid
+
 Design
 ------
 

Modified: cfe/trunk/lib/CodeGen/CGClass.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGClass.cpp?rev=242286&r1=242285&r2=242286&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGClass.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGClass.cpp Wed Jul 15 07:15:56 2015
@@ -2190,15 +2190,6 @@ void CodeGenFunction::EmitVTablePtrCheck
   if (!ClassDecl->isCompleteDefinition() || !ClassDecl->isDynamicClass())
     return;
 
-  SmallString<64> MangledName;
-  llvm::raw_svector_ostream Out(MangledName);
-  CGM.getCXXABI().getMangleContext().mangleCXXRTTI(T.getUnqualifiedType(),
-                                                   Out);
-
-  // Blacklist based on the mangled type.
-  if (CGM.getContext().getSanitizerBlacklist().isBlacklistedType(Out.str()))
-    return;
-
   if (!SanOpts.has(SanitizerKind::CFICastStrict))
     ClassDecl = LeastDerivedClassWithSameLayout(ClassDecl);
 

Modified: cfe/trunk/lib/CodeGen/CGVTables.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGVTables.cpp?rev=242286&r1=242285&r2=242286&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGVTables.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGVTables.cpp Wed Jul 15 07:15:56 2015
@@ -841,8 +841,12 @@ void CodeGenModule::EmitDeferredVTables(
 }
 
 bool CodeGenModule::IsCFIBlacklistedRecord(const CXXRecordDecl *RD) {
-  // FIXME: Make this user configurable.
-  return RD->isInStdNamespace();
+  if (RD->hasAttr<UuidAttr>() &&
+      getContext().getSanitizerBlacklist().isBlacklistedType("attr:uuid"))
+    return true;
+
+  return getContext().getSanitizerBlacklist().isBlacklistedType(
+      RD->getQualifiedNameAsString());
 }
 
 void CodeGenModule::EmitVTableBitSetEntries(llvm::GlobalVariable *VTable,

Modified: cfe/trunk/lib/Driver/SanitizerArgs.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/SanitizerArgs.cpp?rev=242286&r1=242285&r2=242286&view=diff
==============================================================================
--- cfe/trunk/lib/Driver/SanitizerArgs.cpp (original)
+++ cfe/trunk/lib/Driver/SanitizerArgs.cpp Wed Jul 15 07:15:56 2015
@@ -90,6 +90,8 @@ static bool getDefaultBlacklist(const Dr
     BlacklistFile = "tsan_blacklist.txt";
   else if (Kinds & DataFlow)
     BlacklistFile = "dfsan_abilist.txt";
+  else if (Kinds & CFI)
+    BlacklistFile = "cfi_blacklist.txt";
 
   if (BlacklistFile) {
     clang::SmallString<64> Path(D.ResourceDir);

Added: cfe/trunk/test/CodeGenCXX/cfi-blacklist.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/cfi-blacklist.cpp?rev=242286&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenCXX/cfi-blacklist.cpp (added)
+++ cfe/trunk/test/CodeGenCXX/cfi-blacklist.cpp Wed Jul 15 07:15:56 2015
@@ -0,0 +1,30 @@
+// RUN: echo "type:attr:uuid" > %t.txt
+// RUN: %clang_cc1 -fms-extensions -fsanitize=cfi-vcall -fsanitize-blacklist=%t.txt -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=NOUUID %s
+// RUN: echo "type:std::*" > %t.txt
+// RUN: %clang_cc1 -fms-extensions -fsanitize=cfi-vcall -fsanitize-blacklist=%t.txt -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=NOSTD %s
+
+struct __declspec(uuid("00000000-0000-0000-0000-000000000000")) S1 {
+  virtual void f();
+};
+
+namespace std {
+
+struct S2 {
+  virtual void f();
+};
+
+}
+
+// CHECK: define{{.*}}s1f
+// NOSTD: llvm.bitset.test
+// NOUUID-NOT: llvm.bitset.test
+void s1f(S1 *s1) {
+  s1->f();
+}
+
+// CHECK: define{{.*}}s2f
+// NOSTD-NOT: llvm.bitset.test
+// NOUUID: llvm.bitset.test
+void s2f(std::S2 *s2) {
+  s2->f();
+}





More information about the cfe-commits mailing list