oren_ben_simhon updated this revision to Diff 134175.
oren_ben_simhon added a comment.

Implemented comments posted until 2/14 (Thanks Aaron and Craig)


Repository:
  rL LLVM

https://reviews.llvm.org/D41880

Files:
  include/clang/AST/Type.h
  include/clang/Basic/Attr.td
  include/clang/Basic/AttrDocs.td
  include/clang/Sema/Sema.h
  lib/AST/Type.cpp
  lib/AST/TypePrinter.cpp
  lib/CodeGen/CGCall.cpp
  lib/Sema/SemaDeclAttr.cpp
  lib/Sema/SemaType.cpp
  test/CodeGen/attributes.c
  test/CodeGen/cetintrin.c
  test/CodeGen/x86-cf-protection.c
  test/Misc/pragma-attribute-supported-attributes-list.test
  test/Sema/attr-nocf_check.c

Index: test/Sema/attr-nocf_check.c
===================================================================
--- /dev/null
+++ test/Sema/attr-nocf_check.c
@@ -0,0 +1,24 @@
+// RUN: %clang_cc1 -verify -fsyntax-only %s
+
+// Function pointer definition.
+typedef void (*FuncPointerWithNoCfCheck)(void) __attribute__((nocf_check)); // no-warning
+typedef void (*FuncPointer)(void);
+
+// Allow function declaration and definition mismatch.
+void __attribute__((nocf_check)) testNoCfCheck();   // no-warning
+void testNoCfCheck(){}; // no-warning
+
+// No variable or parameter declaration
+__attribute__((nocf_check)) int i;                            // expected-warning {{'nocf_check' attribute only applies to functions and function pointers}}
+void testNoCfCheckImpl(double __attribute__((nocf_check)) i) {} // expected-warning {{'nocf_check' attribute only applies to functions and function pointers}}
+
+// Allow attributed function pointers as well as casting between attributed
+// and non-attributed function pointers.
+void testNoCfCheckMismatch(FuncPointer f) {
+  FuncPointerWithNoCfCheck fNoCfCheck = f; // no-warning
+  (*fNoCfCheck)();                       // no-warning
+  f = fNoCfCheck;                        // no-warning
+}
+
+// 'nocf_check' Attribute has no parameters.
+int testNoCfCheckParams() __attribute__((nocf_check(1))); // expected-error {{'nocf_check' attribute takes no arguments}}
Index: test/Misc/pragma-attribute-supported-attributes-list.test
===================================================================
--- test/Misc/pragma-attribute-supported-attributes-list.test
+++ test/Misc/pragma-attribute-supported-attributes-list.test
@@ -2,7 +2,7 @@
 
 // The number of supported attributes should never go down!
 
-// CHECK: #pragma clang attribute supports 66 attributes:
+// CHECK: #pragma clang attribute supports 67 attributes:
 // CHECK-NEXT: AMDGPUFlatWorkGroupSize (SubjectMatchRule_function)
 // CHECK-NEXT: AMDGPUNumSGPR (SubjectMatchRule_function)
 // CHECK-NEXT: AMDGPUNumVGPR (SubjectMatchRule_function)
@@ -12,6 +12,7 @@
 // CHECK-NEXT: AlignValue (SubjectMatchRule_variable, SubjectMatchRule_type_alias)
 // CHECK-NEXT: AllocSize (SubjectMatchRule_function)
 // CHECK-NEXT: Annotate ()
+// CHECK-NEXT: AnyX86NoCfCheck (SubjectMatchRule_hasType_functionType)
 // CHECK-NEXT: AssumeAligned (SubjectMatchRule_objc_method, SubjectMatchRule_function)
 // CHECK-NEXT: Availability ((SubjectMatchRule_record, SubjectMatchRule_enum, SubjectMatchRule_enum_constant, SubjectMatchRule_field, SubjectMatchRule_function, SubjectMatchRule_namespace, SubjectMatchRule_objc_category, SubjectMatchRule_objc_interface, SubjectMatchRule_objc_method, SubjectMatchRule_objc_property, SubjectMatchRule_objc_protocol, SubjectMatchRule_record, SubjectMatchRule_type_alias, SubjectMatchRule_variable))
 // CHECK-NEXT: CXX11NoReturn (SubjectMatchRule_function)
Index: test/CodeGen/x86-cf-protection.c
===================================================================
--- test/CodeGen/x86-cf-protection.c
+++ test/CodeGen/x86-cf-protection.c
@@ -1,5 +1,5 @@
-// RUN: not %clang_cc1 -fsyntax-only -S -emit-llvm -o %t -triple i386-unknown-unknown -fcf-protection=return %s 2>&1 | FileCheck %s --check-prefix=RETURN
-// RUN: not %clang_cc1 -fsyntax-only -S -emit-llvm -o %t -triple i386-unknown-unknown -fcf-protection=branch %s 2>&1 | FileCheck %s --check-prefix=BRANCH
+// RUN: not %clang_cc1 -fsyntax-only -S -o %t -triple i386-unknown-unknown -fcf-protection=return %s 2>&1 | FileCheck %s --check-prefix=RETURN
+// RUN: not %clang_cc1 -fsyntax-only -S -o %t -triple i386-unknown-unknown -fcf-protection=branch %s 2>&1 | FileCheck %s --check-prefix=BRANCH
 
 // RETURN: error: option 'cf-protection=return' cannot be specified without '-mshstk'
 // BRANCH: error: option 'cf-protection=branch' cannot be specified without '-mibt'
Index: test/CodeGen/cetintrin.c
===================================================================
--- test/CodeGen/cetintrin.c
+++ test/CodeGen/cetintrin.c
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -ffreestanding %s -triple=i386-apple-darwin -target-feature +shstk -emit-llvm -o - -Wall -Werror | FileCheck %s
-// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +shstk  -emit-llvm -o - -Wall -Werror | FileCheck %s --check-prefix=X86_64
+// RUN: %clang_cc1 -ffreestanding %s -triple=i386-unknown-unknown -target-feature +shstk -emit-llvm -o - -Wall -Werror | FileCheck %s
+// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-unknown-unknown -target-feature +shstk  -emit-llvm -o - -Wall -Werror | FileCheck %s --check-prefix=X86_64
 
 #include <immintrin.h>
 
Index: test/CodeGen/attributes.c
===================================================================
--- test/CodeGen/attributes.c
+++ test/CodeGen/attributes.c
@@ -97,8 +97,20 @@
 
 // CHECK: define void @t22() [[NUW]] section ".bar"
 
+// CHECK: define void @t23() [[NOCF_CHECK_FUNC:#[0-9]+]]
+void __attribute__((nocf_check)) t23(void) {}
+
+// CHECK: call void %{{[a-z0-9]+}}() [[NOCF_CHECK_CALL:#[0-9]+]]
+typedef void (*f_t)(void);
+void t24(f_t f1) {
+  __attribute__((nocf_check)) f_t p = f1;
+  (*p)();
+}
+
 // CHECK: attributes [[NUW]] = { noinline nounwind{{.*}} }
 // CHECK: attributes [[NR]] = { noinline noreturn nounwind{{.*}} }
 // CHECK: attributes [[COLDDEF]] = { cold {{.*}}}
 // CHECK: attributes [[COLDDECL]] = { cold {{.*}}}
+// CHECK: attributes [[NOCF_CHECK_FUNC]] = { nocf_check {{.*}}}
 // CHECK: attributes [[COLDSITE]] = { cold {{.*}}}
+// CHECK: attributes [[NOCF_CHECK_CALL]] = { nocf_check }
Index: lib/Sema/SemaType.cpp
===================================================================
--- lib/Sema/SemaType.cpp
+++ lib/Sema/SemaType.cpp
@@ -5127,6 +5127,8 @@
     return AttributeList::AT_ObjCOwnership;
   case AttributedType::attr_noreturn:
     return AttributeList::AT_NoReturn;
+  case AttributedType::attr_nocf_check:
+    return AttributeList::AT_AnyX86NoCfCheck;
   case AttributedType::attr_cdecl:
     return AttributeList::AT_CDecl;
   case AttributedType::attr_fastcall:
@@ -6592,7 +6594,7 @@
   FunctionTypeUnwrapper unwrapped(S, type);
 
   if (attr.getKind() == AttributeList::AT_NoReturn) {
-    if (S.CheckNoReturnAttr(attr))
+    if (S.CheckAttrNoArgs(attr))
       return true;
 
     // Delay if this is not a function type.
@@ -6632,7 +6634,7 @@
   }
 
   if (attr.getKind() == AttributeList::AT_AnyX86NoCallerSavedRegisters) {
-    if (S.CheckNoCallerSavedRegsAttr(attr))
+    if (S.CheckAttrTarget(attr) || S.CheckAttrNoArgs(attr))
       return true;
 
     // Delay if this is not a function type.
Index: lib/Sema/SemaDeclAttr.cpp
===================================================================
--- lib/Sema/SemaDeclAttr.cpp
+++ lib/Sema/SemaDeclAttr.cpp
@@ -1965,7 +1965,7 @@
 static void handleNoReturnAttr(Sema &S, Decl *D, const AttributeList &Attrs) {
   if (hasDeclarator(D)) return;
 
-  if (S.CheckNoReturnAttr(Attrs))
+  if (S.CheckAttrNoArgs(Attrs))
     return;
 
   if (!isa<ObjCMethodDecl>(D)) {
@@ -1980,35 +1980,38 @@
 
 static void handleNoCallerSavedRegsAttr(Sema &S, Decl *D,
                                         const AttributeList &Attr) {
-  if (S.CheckNoCallerSavedRegsAttr(Attr))
+  if (S.CheckAttrTarget(Attr) || S.CheckAttrNoArgs(Attr))
     return;
 
   D->addAttr(::new (S.Context) AnyX86NoCallerSavedRegistersAttr(
       Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex()));
 }
 
-bool Sema::CheckNoReturnAttr(const AttributeList &Attrs) {
-  if (!checkAttributeNumArgs(*this, Attrs, 0)) {
-    Attrs.setInvalid();
+static void handleNoCfCheckAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+  if (S.CheckAttrTarget(Attr))
+    return;
+
+  D->addAttr(::new (S.Context) AnyX86NoCfCheckAttr(
+      Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex()));
+}
+
+bool Sema::CheckAttrNoArgs(const AttributeList &Attr) {
+  if (!checkAttributeNumArgs(*this, Attr, 0)) {
+    Attr.setInvalid();
     return true;
   }
 
   return false;
 }
 
-bool Sema::CheckNoCallerSavedRegsAttr(const AttributeList &Attr) {
+bool Sema::CheckAttrTarget(const AttributeList &Attr) {
   // Check whether the attribute is valid on the current target.
   if (!Attr.existsInTarget(Context.getTargetInfo())) {
     Diag(Attr.getLoc(), diag::warn_unknown_attribute_ignored) << Attr.getName();
     Attr.setInvalid();
     return true;
   }
 
-  if (!checkAttributeNumArgs(*this, Attr, 0)) {
-    Attr.setInvalid();
-    return true;
-  }
-
   return false;
 }
 
@@ -6197,6 +6200,9 @@
   case AttributeList::AT_NoReturn:
     handleNoReturnAttr(S, D, Attr);
     break;
+  case AttributeList::AT_AnyX86NoCfCheck:
+    handleNoCfCheckAttr(S, D, Attr);
+    break;
   case AttributeList::AT_NoThrow:
     handleSimpleAttribute<NoThrowAttr>(S, D, Attr);
     break;
Index: lib/CodeGen/CGCall.cpp
===================================================================
--- lib/CodeGen/CGCall.cpp
+++ lib/CodeGen/CGCall.cpp
@@ -1842,6 +1842,8 @@
       RetAttrs.addAttribute(llvm::Attribute::NonNull);
     if (TargetDecl->hasAttr<AnyX86NoCallerSavedRegistersAttr>())
       FuncAttrs.addAttribute("no_caller_saved_registers");
+    if (TargetDecl->hasAttr<AnyX86NoCfCheckAttr>())
+      FuncAttrs.addAttribute(llvm::Attribute::NoCfCheck);
 
     HasOptnone = TargetDecl->hasAttr<OptimizeNoneAttr>();
     if (auto *AllocSize = TargetDecl->getAttr<AllocSizeAttr>()) {
Index: lib/AST/TypePrinter.cpp
===================================================================
--- lib/AST/TypePrinter.cpp
+++ lib/AST/TypePrinter.cpp
@@ -1396,7 +1396,7 @@
   // FIXME: When Sema learns to form this AttributedType, avoid printing the
   // attribute again in printFunctionProtoAfter.
   case AttributedType::attr_noreturn: OS << "noreturn"; break;
-
+  case AttributedType::attr_nocf_check: OS << "nocf_check"; break;
   case AttributedType::attr_cdecl: OS << "cdecl"; break;
   case AttributedType::attr_fastcall: OS << "fastcall"; break;
   case AttributedType::attr_stdcall: OS << "stdcall"; break;
Index: lib/AST/Type.cpp
===================================================================
--- lib/AST/Type.cpp
+++ lib/AST/Type.cpp
@@ -3097,6 +3097,7 @@
   case AttributedType::attr_uptr:
   case AttributedType::attr_objc_kindof:
   case AttributedType::attr_ns_returns_retained:
+  case AttributedType::attr_nocf_check:
     return false;
   }
   llvm_unreachable("bad attributed type kind");
@@ -3134,6 +3135,7 @@
   case attr_nullable:
   case attr_null_unspecified:
   case attr_objc_kindof:
+  case attr_nocf_check:
     return false;
 
   case attr_pcs:
Index: include/clang/Sema/Sema.h
===================================================================
--- include/clang/Sema/Sema.h
+++ include/clang/Sema/Sema.h
@@ -3328,8 +3328,8 @@
   bool CheckRegparmAttr(const AttributeList &attr, unsigned &value);
   bool CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC,
                             const FunctionDecl *FD = nullptr);
-  bool CheckNoReturnAttr(const AttributeList &attr);
-  bool CheckNoCallerSavedRegsAttr(const AttributeList &attr);
+  bool CheckAttrTarget(const AttributeList &Attr);
+  bool CheckAttrNoArgs(const AttributeList &Attr);
   bool checkStringLiteralArgumentAttr(const AttributeList &Attr,
                                       unsigned ArgNum, StringRef &Str,
                                       SourceLocation *ArgLocation = nullptr);
Index: include/clang/Basic/AttrDocs.td
===================================================================
--- include/clang/Basic/AttrDocs.td
+++ include/clang/Basic/AttrDocs.td
@@ -2870,6 +2870,24 @@
   }];
 }
 
+def AnyX86NoCfCheckDocs : Documentation{
+  let Category = DocCatFunction;
+  let Content = [{
+Jump Oriented Programming attacks rely on tampering with addresses used by
+indirect call / jmp, e.g. redirect control-flow to non-programmer
+intended bytes in the binary.
+X86 Supports Indirect Branch Tracking (IBT) as part of Control-Flow
+Enforcement Technology (CET). IBT instruments ENDBR instructions used to
+specify valid targets of indirect call / jmp.
+The ``nocf_check`` attribute has two roles:
+1. Appertains to a function - do not add ENDBR instruction at the
+    beginning of the function.
+2. Appertains to a function pointer - do not track the target
+    function of this pointer (by adding nocf_check prefix to the
+    indirect-call instruction).
+}];
+}
+
 def SwiftCallDocs : Documentation {
   let Category = DocCatVariable;
   let Content = [{
Index: include/clang/Basic/Attr.td
===================================================================
--- include/clang/Basic/Attr.td
+++ include/clang/Basic/Attr.td
@@ -2085,6 +2085,12 @@
   let Documentation = [AnyX86NoCallerSavedRegistersDocs];
 }
 
+def AnyX86NoCfCheck : InheritableAttr, TargetSpecificAttr<TargetAnyX86>{
+  let Spellings = [GCC<"nocf_check">];
+  let Subjects = SubjectList<[FunctionLike]>;
+  let Documentation = [AnyX86NoCfCheckDocs];
+}
+
 def X86ForceAlignArgPointer : InheritableAttr, TargetSpecificAttr<TargetAnyX86> {
   let Spellings = [GCC<"force_align_arg_pointer">];
   // Technically, this appertains to a FunctionDecl, but the target-specific
Index: include/clang/AST/Type.h
===================================================================
--- include/clang/AST/Type.h
+++ include/clang/AST/Type.h
@@ -4054,6 +4054,7 @@
 
     // No operand.
     attr_noreturn,
+    attr_nocf_check,
     attr_cdecl,
     attr_fastcall,
     attr_stdcall,
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to