From 3243cbdaeaefcb51983b576cac4e38b75809d734 Mon Sep 17 00:00:00 2001 From: Chandler Carruth Date: Tue, 4 Sep 2018 12:38:00 +0000 Subject: [PATCH] [x86/SLH] Add a real Clang flag and LLVM IR attribute for Speculative Load Hardening. Wires up the existing pass to work with a proper IR attribute rather than just a hidden/internal flag. The internal flag continues to work for now, but I'll likely remove it soon. Most of the churn here is adding the IR attribute. I talked about this Kristof Beyls and he seemed at least initially OK with this direction. The idea of using a full attribute here is that we *do* expect at least some forms of this for other architectures. There isn't anything *inherently* x86-specific about this technique, just that we only have an implementation for x86 at the moment. While we could potentially expose this as a Clang-level attribute as well, that seems like a good question to defer for the moment as it isn't 100% clear whether that or some other programmer interface (or both?) would be best. We'll defer the programmer interface side of this for now, but at least get to the point where the feature can be enabled without relying on implementation details. This also allows us to do something that was really hard before: we can enable *just* the indirect call retpolines when using SLH. For x86, we don't have any other way to mitigate indirect calls. Other architectures may take a different approach of course, and none of this is surfaced to user-level flags. Differential Revision: https://reviews.llvm.org/D51157 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@341363 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Driver/Options.td | 4 ++++ include/clang/Frontend/CodeGenOptions.def | 1 + lib/CodeGen/CGCall.cpp | 3 +++ lib/Driver/ToolChains/Arch/X86.cpp | 18 +++++++++++++----- lib/Driver/ToolChains/Clang.cpp | 3 +++ lib/Frontend/CompilerInvocation.cpp | 2 ++ test/CodeGen/attr-speculative-load-hardening.c | 10 ++++++++++ test/Driver/x86-target-features.c | 9 +++++++++ 8 files changed, 45 insertions(+), 5 deletions(-) create mode 100644 test/CodeGen/attr-speculative-load-hardening.c diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index e4539ab080..32038dc733 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -2009,6 +2009,10 @@ def mno_stackrealign : Flag<["-"], "mno-stackrealign">, Group; def mretpoline : Flag<["-"], "mretpoline">, Group, Flags<[CoreOption,DriverOption]>; def mno_retpoline : Flag<["-"], "mno-retpoline">, Group, Flags<[CoreOption,DriverOption]>; +def mspeculative_load_hardening : Flag<["-"], "mspeculative-load-hardening">, + Group, Flags<[CoreOption,CC1Option]>; +def mno_speculative_load_hardening : Flag<["-"], "mno-speculative-load-hardening">, + Group, Flags<[CoreOption]>; def mrelax : Flag<["-"], "mrelax">, Group, HelpText<"Enable linker relaxation">; diff --git a/include/clang/Frontend/CodeGenOptions.def b/include/clang/Frontend/CodeGenOptions.def index 4968e7b2bf..f94979c3e6 100644 --- a/include/clang/Frontend/CodeGenOptions.def +++ b/include/clang/Frontend/CodeGenOptions.def @@ -211,6 +211,7 @@ CODEGENOPT(SanitizeCoverageStackDepth, 1, 0) ///< Enable max stack depth tracing CODEGENOPT(SanitizeStats , 1, 0) ///< Collect statistics for sanitizers. CODEGENOPT(SimplifyLibCalls , 1, 1) ///< Set when -fbuiltin is enabled. CODEGENOPT(SoftFloat , 1, 0) ///< -soft-float. +CODEGENOPT(SpeculativeLoadHardening, 1, 0) ///< Enable speculative load hardening. CODEGENOPT(FineGrainedBitfieldAccesses, 1, 0) ///< Enable fine-grained bitfield accesses. CODEGENOPT(StrictEnums , 1, 0) ///< Optimize based on strict enum definition. CODEGENOPT(StrictVTablePointers, 1, 0) ///< Optimize based on the strict vtable pointers diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp index c2b4c95ae9..8857ffdde4 100644 --- a/lib/CodeGen/CGCall.cpp +++ b/lib/CodeGen/CGCall.cpp @@ -1784,6 +1784,9 @@ void CodeGenModule::ConstructDefaultFnAttrList(StringRef Name, bool HasOptnone, FuncAttrs.addAttribute("stackrealign"); if (CodeGenOpts.Backchain) FuncAttrs.addAttribute("backchain"); + + if (CodeGenOpts.SpeculativeLoadHardening) + FuncAttrs.addAttribute(llvm::Attribute::SpeculativeLoadHardening); } if (getLangOpts().assumeFunctionsAreConvergent()) { diff --git a/lib/Driver/ToolChains/Arch/X86.cpp b/lib/Driver/ToolChains/Arch/X86.cpp index ff2023c2cb..bc707857d8 100644 --- a/lib/Driver/ToolChains/Arch/X86.cpp +++ b/lib/Driver/ToolChains/Arch/X86.cpp @@ -146,15 +146,23 @@ void x86::getX86TargetFeatures(const Driver &D, const llvm::Triple &Triple, // Translate the high level `-mretpoline` flag to the specific target feature // flags. We also detect if the user asked for retpoline external thunks but - // failed to ask for retpolines themselves. This is a bit hacky but keeps - // existing usages working. We should consider deprecated this and instead - // warning if the user requests external retpoline thunks and *doesn't* - // request some form of retpolines. - if (Args.hasArgNoClaim(options::OPT_mretpoline, options::OPT_mno_retpoline)) { + // failed to ask for retpolines themselves (through any of the different + // flags). This is a bit hacky but keeps existing usages working. We should + // consider deprecating this and instead warn if the user requests external + // retpoline thunks and *doesn't* request some form of retpolines. + if (Args.hasArgNoClaim(options::OPT_mretpoline, options::OPT_mno_retpoline, + options::OPT_mspeculative_load_hardening, + options::OPT_mno_speculative_load_hardening)) { if (Args.hasFlag(options::OPT_mretpoline, options::OPT_mno_retpoline, false)) { Features.push_back("+retpoline-indirect-calls"); Features.push_back("+retpoline-indirect-branches"); + } else if (Args.hasFlag(options::OPT_mspeculative_load_hardening, + options::OPT_mno_speculative_load_hardening, + false)) { + // On x86, speculative load hardening relies on at least using retpolines + // for indirect calls. + Features.push_back("+retpoline-indirect-calls"); } } else if (Args.hasFlag(options::OPT_mretpoline_external_thunk, options::OPT_mno_retpoline_external_thunk, false)) { diff --git a/lib/Driver/ToolChains/Clang.cpp b/lib/Driver/ToolChains/Clang.cpp index ff083c79f1..79129a7a7c 100644 --- a/lib/Driver/ToolChains/Clang.cpp +++ b/lib/Driver/ToolChains/Clang.cpp @@ -4132,6 +4132,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, Args.AddLastArg(CmdArgs, options::OPT_pthread); + Args.AddLastArg(CmdArgs, options::OPT_mspeculative_load_hardening, + options::OPT_mno_speculative_load_hardening); + RenderSSPOptions(getToolChain(), Args, CmdArgs, KernelOrKext); // Translate -mstackrealign diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 4ac7929328..5210314493 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -1147,6 +1147,8 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Opts.KeepStaticConsts = Args.hasArg(OPT_fkeep_static_consts); + Opts.SpeculativeLoadHardening = Args.hasArg(OPT_mspeculative_load_hardening); + return Success; } diff --git a/test/CodeGen/attr-speculative-load-hardening.c b/test/CodeGen/attr-speculative-load-hardening.c new file mode 100644 index 0000000000..ccbded44bb --- /dev/null +++ b/test/CodeGen/attr-speculative-load-hardening.c @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -mspeculative-load-hardening -disable-llvm-passes -emit-llvm %s -o - | FileCheck %s -check-prefix=SLH +// +// Check that we set the attribute on each function. + +int test1() { + return 42; +} +// SLH: @{{.*}}test1{{.*}}[[SLH:#[0-9]+]] + +// SLH: attributes [[SLH]] = { {{.*}}speculative_load_hardening{{.*}} } diff --git a/test/Driver/x86-target-features.c b/test/Driver/x86-target-features.c index 527a9a2cff..ee2e6afd61 100644 --- a/test/Driver/x86-target-features.c +++ b/test/Driver/x86-target-features.c @@ -140,6 +140,15 @@ // RETPOLINE-EXTERNAL-THUNK: "-target-feature" "+retpoline-external-thunk" // NO-RETPOLINE-EXTERNAL-THUNK: "-target-feature" "-retpoline-external-thunk" +// RUN: %clang -target i386-linux-gnu -mspeculative-load-hardening %s -### -o %t.o 2>&1 | FileCheck -check-prefix=SLH %s +// RUN: %clang -target i386-linux-gnu -mretpoline -mspeculative-load-hardening %s -### -o %t.o 2>&1 | FileCheck -check-prefix=RETPOLINE %s +// RUN: %clang -target i386-linux-gnu -mno-speculative-load-hardening %s -### -o %t.o 2>&1 | FileCheck -check-prefix=NO-SLH %s +// SLH-NOT: retpoline +// SLH: "-target-feature" "+retpoline-indirect-calls" +// SLH-NOT: retpoline +// SLH: "-mspeculative-load-hardening" +// NO-SLH-NOT: retpoline + // RUN: %clang -target i386-linux-gnu -mwaitpkg %s -### -o %t.o 2>&1 | FileCheck -check-prefix=WAITPKG %s // RUN: %clang -target i386-linux-gnu -mno-waitpkg %s -### -o %t.o 2>&1 | FileCheck -check-prefix=NO-WAITPKG %s // WAITPKG: "-target-feature" "+waitpkg" -- 2.40.0