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