forked from OSchip/llvm-project
[clang][slh] add attribute for speculative load hardening
Summary: LLVM IR already has an attribute for speculative_load_hardening. Before this commit, when a user passed the -mspeculative-load-hardening flag to Clang, every function would have this attribute added to it. This Clang attribute will allow users to opt into SLH on a function by function basis. This can be applied to functions and Objective C methods. Reviewers: chandlerc, echristo Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D54555 llvm-svn: 347586
This commit is contained in:
parent
94104b1b6b
commit
b0fd2db8fc
|
@ -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];
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
}];
|
||||
}
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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{{.*}} }
|
|
@ -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{{.*}} }
|
|
@ -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 [[speculative_load_hardening]]; // expected-error {{'speculative_load_hardening' attribute only applies to functions}}
|
||||
|
||||
[[speculative_load_hardening]] void cf1();
|
||||
[[speculative_load_hardening(1)]] void cf2(); // expected-error {{'speculative_load_hardening' attribute takes no arguments}}
|
||||
|
||||
template <typename T>
|
||||
[[speculative_load_hardening]]
|
||||
void ctf1();
|
||||
|
||||
int cf3(int c[[speculative_load_hardening]], int); // expected-error {{'speculative_load_hardening' attribute only applies to functions}}
|
||||
|
||||
struct CA {
|
||||
int f [[speculative_load_hardening]]; // expected-error {{'speculative_load_hardening' attribute only applies to functions}}
|
||||
[[speculative_load_hardening]] void mf1();
|
||||
[[speculative_load_hardening]] static void mf2();
|
||||
};
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue