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
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits