diff options
-rw-r--r-- | clang/include/clang/Basic/Attr.td | 6 | ||||
-rw-r--r-- | clang/include/clang/Basic/AttrDocs.td | 24 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGCall.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclAttr.cpp | 3 | ||||
-rw-r--r-- | clang/test/CodeGen/attr-speculative-load-hardening.cpp | 18 | ||||
-rw-r--r-- | clang/test/CodeGen/attr-speculative-load-hardening.m | 9 | ||||
-rw-r--r-- | clang/test/Misc/pragma-attribute-supported-attributes-list.test | 3 | ||||
-rw-r--r-- | clang/test/SemaCXX/attr-speculative-load-hardening.cpp | 34 | ||||
-rw-r--r-- | llvm/docs/LangRef.rst | 22 |
9 files changed, 109 insertions, 14 deletions
diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index a6be48c234f..5b52ba4f64b 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -3091,3 +3091,9 @@ def AlwaysDestroy : InheritableAttr { let Subjects = SubjectList<[Var]>; let Documentation = [AlwaysDestroyDocs]; } + +def SpeculativeLoadHardening : InheritableAttr { + let Spellings = [Clang<"speculative_load_hardening">]; + let Subjects = SubjectList<[Function, ObjCMethod], ErrorDiag>; + let Documentation = [SpeculativeLoadHardeningDocs]; +} diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index e38c557f140..203ae827195 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -3629,3 +3629,27 @@ GNU inline semantics are the default behavior with ``-std=gnu89``, ``-std=c89``, ``-std=c94``, or ``-fgnu89-inline``. }]; } + +def SpeculativeLoadHardeningDocs : Documentation { + let Category = DocCatFunction; + let Content = [{ + This attribute can be applied to a function declaration in order to indicate + that `Speculative Load Hardening <https://llvm.org/docs/SpeculativeLoadHardening.html>`_ + should be enabled for the function body. This can also be applied to a method + in Objective C. + + Speculative Load Hardening is a best-effort mitigation against + information leak attacks that make use of control flow + miss-speculation - specifically miss-speculation of whether a branch + is taken or not. Typically vulnerabilities enabling such attacks are + classified as "Spectre variant #1". Notably, this does not attempt to + mitigate against miss-speculation of branch target, classified as + "Spectre variant #2" vulnerabilities. + + When inlining, the attribute is sticky. Inlining a function that + carries this attribute will cause the caller to gain the + attribute. This is intended to provide a maximally conservative model + where the code in a function annotated with this attribute will always + (even after inlining) end up hardened. + }]; +} diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 0ec5c7fb452..6d89f3919fd 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -1791,6 +1791,8 @@ void CodeGenModule::ConstructDefaultFnAttrList(StringRef Name, bool HasOptnone, if (CodeGenOpts.Backchain) FuncAttrs.addAttribute("backchain"); + // FIXME: The interaction of this attribute with the SLH command line flag + // has not been determined. if (CodeGenOpts.SpeculativeLoadHardening) FuncAttrs.addAttribute(llvm::Attribute::SpeculativeLoadHardening); } @@ -1854,6 +1856,8 @@ void CodeGenModule::ConstructAttributeList( FuncAttrs.addAttribute(llvm::Attribute::NoDuplicate); if (TargetDecl->hasAttr<ConvergentAttr>()) FuncAttrs.addAttribute(llvm::Attribute::Convergent); + if (TargetDecl->hasAttr<SpeculativeLoadHardeningAttr>()) + FuncAttrs.addAttribute(llvm::Attribute::SpeculativeLoadHardening); if (const FunctionDecl *Fn = dyn_cast<FunctionDecl>(TargetDecl)) { AddAttributesFromFunctionProtoType( diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 9f5325d109e..be662b9b914 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -6373,6 +6373,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case ParsedAttr::AT_Section: handleSectionAttr(S, D, AL); break; + case ParsedAttr::AT_SpeculativeLoadHardening: + handleSimpleAttribute<SpeculativeLoadHardeningAttr>(S, D, AL); + break; case ParsedAttr::AT_CodeSeg: handleCodeSegAttr(S, D, AL); break; diff --git a/clang/test/CodeGen/attr-speculative-load-hardening.cpp b/clang/test/CodeGen/attr-speculative-load-hardening.cpp new file mode 100644 index 00000000000..e2eb805cbb8 --- /dev/null +++ b/clang/test/CodeGen/attr-speculative-load-hardening.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -std=c++11 -disable-llvm-passes -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK1 +// RUN: %clang_cc1 -std=c++11 -disable-llvm-passes -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK2 +// +// Check that we set the attribute on each function. + +[[clang::speculative_load_hardening]] +int test1() { + return 42; +} + +int __attribute__((speculative_load_hardening)) test2() { + return 42; +} +// CHECK1: @{{.*}}test1{{.*}}[[SLH1:#[0-9]+]] +// CHECK1: attributes [[SLH1]] = { {{.*}}speculative_load_hardening{{.*}} } + +// CHECK2: @{{.*}}test2{{.*}}[[SLH2:#[0-9]+]] +// CHECK2: attributes [[SLH2]] = { {{.*}}speculative_load_hardening{{.*}} } diff --git a/clang/test/CodeGen/attr-speculative-load-hardening.m b/clang/test/CodeGen/attr-speculative-load-hardening.m new file mode 100644 index 00000000000..2de945b974f --- /dev/null +++ b/clang/test/CodeGen/attr-speculative-load-hardening.m @@ -0,0 +1,9 @@ +// RUN: %clang -emit-llvm %s -o - -S | FileCheck %s -check-prefix=SLH + +int main() __attribute__((speculative_load_hardening)) { + return 0; +} + +// SLH: @{{.*}}main{{.*}}[[SLH:#[0-9]+]] + +// SLH: attributes [[SLH]] = { {{.*}}speculative_load_hardening{{.*}} } diff --git a/clang/test/Misc/pragma-attribute-supported-attributes-list.test b/clang/test/Misc/pragma-attribute-supported-attributes-list.test index 0a54c6c05ad..0aa923de7df 100644 --- a/clang/test/Misc/pragma-attribute-supported-attributes-list.test +++ b/clang/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 129 attributes: +// CHECK: #pragma clang attribute supports 130 attributes: // CHECK-NEXT: AMDGPUFlatWorkGroupSize (SubjectMatchRule_function) // CHECK-NEXT: AMDGPUNumSGPR (SubjectMatchRule_function) // CHECK-NEXT: AMDGPUNumVGPR (SubjectMatchRule_function) @@ -116,6 +116,7 @@ // CHECK-NEXT: ScopedLockable (SubjectMatchRule_record) // CHECK-NEXT: Section (SubjectMatchRule_function, SubjectMatchRule_variable_is_global, SubjectMatchRule_objc_method, SubjectMatchRule_objc_property) // CHECK-NEXT: SetTypestate (SubjectMatchRule_function_is_member) +// CHECK-NEXT: SpeculativeLoadHardening (SubjectMatchRule_function, SubjectMatchRule_objc_method) // CHECK-NEXT: SwiftContext (SubjectMatchRule_variable_is_parameter) // CHECK-NEXT: SwiftErrorResult (SubjectMatchRule_variable_is_parameter) // CHECK-NEXT: SwiftIndirectResult (SubjectMatchRule_variable_is_parameter) diff --git a/clang/test/SemaCXX/attr-speculative-load-hardening.cpp b/clang/test/SemaCXX/attr-speculative-load-hardening.cpp new file mode 100644 index 00000000000..bba3b6921e8 --- /dev/null +++ b/clang/test/SemaCXX/attr-speculative-load-hardening.cpp @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +int i __attribute__((speculative_load_hardening)); // expected-error {{'speculative_load_hardening' attribute only applies to functions}} + +void f1() __attribute__((speculative_load_hardening)); +void f2() __attribute__((speculative_load_hardening(1))); // expected-error {{'speculative_load_hardening' attribute takes no arguments}} + +template <typename T> +void tf1() __attribute__((speculative_load_hardening)); + +int f3(int __attribute__((speculative_load_hardening)), int); // expected-error {{'speculative_load_hardening' attribute only applies to functions}} + +struct A { + int f __attribute__((speculative_load_hardening)); // expected-error {{'speculative_load_hardening' attribute only applies to functions}} + void mf1() __attribute__((speculative_load_hardening)); + static void mf2() __attribute__((speculative_load_hardening)); +}; + +int ci [[clang::speculative_load_hardening]]; // expected-error {{'speculative_load_hardening' attribute only applies to functions}} + +[[clang::speculative_load_hardening]] void cf1(); +[[clang::speculative_load_hardening(1)]] void cf2(); // expected-error {{'speculative_load_hardening' attribute takes no arguments}} + +template <typename T> +[[clang::speculative_load_hardening]] +void ctf1(); + +int cf3(int c[[clang::speculative_load_hardening]], int); // expected-error {{'speculative_load_hardening' attribute only applies to functions}} + +struct CA { + int f [[clang::speculative_load_hardening]]; // expected-error {{'speculative_load_hardening' attribute only applies to functions}} + [[clang::speculative_load_hardening]] void mf1(); + [[clang::speculative_load_hardening]] static void mf2(); +}; diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst index 7ec157fb73c..fa85b6e6ee7 100644 --- a/llvm/docs/LangRef.rst +++ b/llvm/docs/LangRef.rst @@ -1643,19 +1643,15 @@ example: ``speculative_load_hardening`` This attribute indicates that `Speculative Load Hardening <https://llvm.org/docs/SpeculativeLoadHardening.html>`_ - should be enabled for the function body. This is a best-effort attempt to - mitigate all known speculative execution information leak vulnerabilities - that are based on the fundamental principles of modern processors' - speculative execution. These vulnerabilities are classified as "Spectre - variant #1" vulnerabilities typically. Notably, this does not attempt to - mitigate any vulnerabilities where the speculative execution and/or - prediction devices of specific processors can be *completely* undermined - (such as "Branch Target Injection", a.k.a, "Spectre variant #2"). Instead, - this is a target-independent request to harden against the completely - generic risk posed by speculative execution to incorrectly load secret data, - making it available to some micro-architectural side-channel for information - leak. For a processor without any speculative execution or predictors, this - is expected to be a no-op. + should be enabled for the function body. + + Speculative Load Hardening is a best-effort mitigation against + information leak attacks that make use of control flow + miss-speculation - specifically miss-speculation of whether a branch + is taken or not. Typically vulnerabilities enabling such attacks are + classified as "Spectre variant #1". Notably, this does not attempt to + mitigate against miss-speculation of branch target, classified as + "Spectre variant #2" vulnerabilities. When inlining, the attribute is sticky. Inlining a function that carries this attribute will cause the caller to gain the attribute. This is intended |