From df8fe652570024bd6827bd116dafff9646709789 Mon Sep 17 00:00:00 2001 From: arvinzzz Date: Tue, 28 Mar 2023 22:50:37 +0800 Subject: [PATCH] Title: Enhance the function of backward cfi & stack protection. Description: Enhance the function of stack-protector-ret 1 Enhanced Security Capabilities 1.1 Backward CFI protection includes FP into the protection scope, and verifies both FP and LR in the prolog and epilog of the function. 1.2 Change the original `-fstack-protector-ret` to `-fstack-protector-ret-strong` and `-fstack-protector-ret-all` 1.3 Support setting the number of ret-cookies When using `-fstack-protector-ret-all`, you can limit the number of ret-cookies used by backward CFI protection in an ELF object by adding `--param=ssp-ret-cookie-size=XXX` option. 2 Optimize memory usage Set the .ohos.randomdata section to the SHT_NOBITS attribute, do not occupy ROM space in ELF, allocate space and fill random data during linking and loading. Test: llvmts && backward cfi demo test Issue: https://gitee.com/openharmony/third_party_llvm-project/issues/I6R52Q Signed-off-by: arvinzzz Change-Id: I999bf9c01236a4d6a3489df262c4a82a6e228b4d --- clang/docs/ClangCommandLineReference.rst | 12 +- clang/include/clang/Basic/CodeGenOptions.def | 5 + clang/include/clang/Basic/LangOptions.def | 1 + clang/include/clang/Basic/LangOptions.h | 2 +- clang/include/clang/Driver/Options.td | 15 +- clang/lib/CodeGen/CGCall.cpp | 2 + clang/lib/CodeGen/CodeGenModule.cpp | 8 +- clang/lib/Driver/ToolChains/Clang.cpp | 37 +++- clang/lib/Frontend/InitPreprocessor.cpp | 8 +- clang/test/CodeGen/stack-protector.c | 22 +++ clang/test/Driver/claim-unused.c | 4 + clang/test/Driver/stack-protector.c | 18 ++ lld/ELF/LinkerScript.cpp | 2 +- lld/ELF/ScriptParser.cpp | 2 +- lld/ELF/Writer.cpp | 4 +- lld/wasm/Writer.cpp | 4 + llvm/docs/LangRef.rst | 61 ++++++ llvm/include/llvm/BinaryFormat/ELF.h | 2 +- llvm/include/llvm/Bitcode/LLVMBitCodes.h | 5 +- llvm/include/llvm/CodeGen/MachineFrameInfo.h | 4 + llvm/include/llvm/CodeGen/StackProtector.h | 7 +- .../llvm/CodeGen/StackProtectorRetLowering.h | 2 + .../llvm/CodeGen/TargetFrameLowering.h | 5 +- llvm/include/llvm/IR/Attributes.td | 9 +- llvm/include/llvm/IR/Function.h | 6 +- llvm/lib/Bitcode/Reader/BitcodeReader.cpp | 10 +- llvm/lib/Bitcode/Writer/BitcodeWriter.cpp | 8 +- llvm/lib/CodeGen/CMakeLists.txt | 2 +- llvm/lib/CodeGen/LocalStackSlotAllocation.cpp | 9 +- llvm/lib/CodeGen/PrologEpilogInserter.cpp | 25 ++- llvm/lib/CodeGen/SafeStack.cpp | 5 +- llvm/lib/CodeGen/StackProtector.cpp | 25 ++- .../lib/CodeGen/StackProtectorRetLowering.cpp | 11 +- .../CodeGen/TargetLoweringObjectFileImpl.cpp | 6 + llvm/lib/IR/Attributes.cpp | 29 ++- llvm/lib/IR/Function.cpp | 5 +- llvm/lib/MC/MCParser/ELFAsmParser.cpp | 7 +- llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp | 2 + .../Target/AArch64/AArch64FrameLowering.cpp | 6 +- .../lib/Target/AArch64/AArch64FrameLowering.h | 9 +- llvm/lib/Target/AArch64/AArch64InstrInfo.td | 2 + .../AArch64StackProtectorRetLowering.cpp | 17 +- .../AArch64StackProtectorRetLowering.h | 2 + llvm/lib/Target/AArch64/CMakeLists.txt | 2 +- llvm/lib/Transforms/Utils/CodeExtractor.cpp | 5 +- llvm/test/Bitcode/attributes.ll | 18 ++ .../AArch64/stack-protector-ret-target.ll | 31 +++ llvm/test/Transforms/Inline/inline_sspret.ll | 176 ++++++++++++++++++ .../test/tools/llvm-objdump/ohos-headers.test | 1 + llvm/tools/llvm-objdump/ELFDump.cpp | 2 + llvm/tools/llvm-readobj/ELFDumper.cpp | 2 +- 51 files changed, 595 insertions(+), 69 deletions(-) create mode 100644 llvm/test/CodeGen/AArch64/stack-protector-ret-target.ll create mode 100644 llvm/test/Transforms/Inline/inline_sspret.ll diff --git a/clang/docs/ClangCommandLineReference.rst b/clang/docs/ClangCommandLineReference.rst index f29396749305..41fb8f7259eb 100644 --- a/clang/docs/ClangCommandLineReference.rst +++ b/clang/docs/ClangCommandLineReference.rst @@ -2506,13 +2506,17 @@ Enable stack protectors for some functions vulnerable to stack smashing. This us Enable stack protectors for all functions -.. option:: -fstack-protector-strong +.. option:: -fstack-protector-ret-all -Enable stack protectors for some functions vulnerable to stack smashing. Compared to -fstack-protector, this uses a stronger heuristic that includes functions containing arrays of any size (and any type), as well as any calls to alloca or the taking of an address from a local variable +Enable stack protectors for all functions with return address check -.. option:: -fstack-protector-ret +.. option:: -fstack-protector-ret-strong -Enable stack protectors for all functions with return address check +Enable stack protectors for some functions vulnerable to stack smashing with return address check + +.. option:: -fstack-protector-strong + +Enable stack protectors for some functions vulnerable to stack smashing. Compared to -fstack-protector, this uses a stronger heuristic that includes functions containing arrays of any size (and any type), as well as any calls to alloca or the taking of an address from a local variable .. option:: -fstack-size-section, -fno-stack-size-section diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def index ef7957979dcc..5d4aec842db3 100644 --- a/clang/include/clang/Basic/CodeGenOptions.def +++ b/clang/include/clang/Basic/CodeGenOptions.def @@ -373,6 +373,11 @@ VALUE_CODEGENOPT(SmallDataLimit, 32, 0) /// The lower bound for a buffer to be considered for stack protection. VALUE_CODEGENOPT(SSPBufferSize, 32, 0) +/// OHOS_LOCAL begin +/// The maximum total of cookies used by backward cfi for stack protection. +VALUE_CODEGENOPT(SSPRetCookieSize, 32, 1) +/// OHOS_LOCAL end + /// The kind of generated debug info. ENUM_CODEGENOPT(DebugInfo, codegenoptions::DebugInfoKind, 4, codegenoptions::NoDebugInfo) diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def index 4faec655636c..c58c45416107 100644 --- a/clang/include/clang/Basic/LangOptions.def +++ b/clang/include/clang/Basic/LangOptions.def @@ -358,6 +358,7 @@ ENUM_LANGOPT(ExternDeclNoDLLStorageClassVisibility, Visibility, 3, HiddenVisibil BENIGN_LANGOPT(SemanticInterposition , 1, 0, "semantic interposition") BENIGN_LANGOPT(HalfNoSemanticInterposition, 1, 0, "Like -fno-semantic-interposition but don't use local aliases") +/// OHOS_LOCAL ENUM_LANGOPT(StackProtector, StackProtectorMode, 3, SSPOff, "stack protector mode") ENUM_LANGOPT(TrivialAutoVarInit, TrivialAutoVarInitKind, 2, TrivialAutoVarInitKind::Uninitialized, diff --git a/clang/include/clang/Basic/LangOptions.h b/clang/include/clang/Basic/LangOptions.h index 046775964905..10b8260b3489 100644 --- a/clang/include/clang/Basic/LangOptions.h +++ b/clang/include/clang/Basic/LangOptions.h @@ -81,7 +81,7 @@ public: using RoundingMode = llvm::RoundingMode; enum GCMode { NonGC, GCOnly, HybridGC }; - enum StackProtectorMode { SSPOff, SSPOn, SSPStrong, SSPReq, SSPRet }; + enum StackProtectorMode { SSPOff, SSPOn, SSPStrong, SSPReq, SSPRetStrong, SSPRetReq }; // OHOS_LOCAL // Automatic variables live on the stack, and when trivial they're usually // uninitialized because it's undefined behavior to use them without diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 1b96288ff225..7d0d72700b71 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -2738,8 +2738,12 @@ defm split_stack : BoolFOption<"split-stack", PosFlag>; def fstack_protector_all : Flag<["-"], "fstack-protector-all">, Group, HelpText<"Enable stack protectors for all functions">; -def fstack_protector_ret : Flag<["-"], "fstack-protector-ret">, Group, +// OHOS_LOCAL begin +def fstack_protector_ret_all : Flag<["-"], "fstack-protector-ret-all">, Group, HelpText<"Enable stack protectors for all functions with return address check">; +def fstack_protector_ret_strong : Flag<["-"], "fstack-protector-ret-strong">, Group, + HelpText<"Enable stack protectors for some functions vulnerable to stack smashing with return address check">; +// OHOS_LOCAL end defm stack_clash_protection : BoolFOption<"stack-clash-protection", CodeGenOpts<"StackClashProtector">, DefaultFalse, PosFlag, NegFlag, @@ -6052,13 +6056,18 @@ def static_define : Flag<["-"], "static-define">, MarshallingInfoFlag>; def stack_protector : Separate<["-"], "stack-protector">, HelpText<"Enable stack protectors">, - Values<"0,1,2,3,4">, + Values<"0,1,2,3,4,5">, // OHOS_LOCAL NormalizedValuesScope<"LangOptions">, - NormalizedValues<["SSPOff", "SSPOn", "SSPStrong", "SSPReq", "SSPRet"]>, + NormalizedValues<["SSPOff", "SSPOn", "SSPStrong", "SSPReq", "SSPRetStrong", "SSPRetReq"]>, // OHOS_LOCAL MarshallingInfoEnum, "SSPOff">; def stack_protector_buffer_size : Separate<["-"], "stack-protector-buffer-size">, HelpText<"Lower bound for a buffer to be considered for stack protection">, MarshallingInfoInt, "8">; +// OHOS_LOCAL begin +def stack_protector_ret_cookie_size : Separate<["-"], "stack-protector-ret-cookie-size">, + HelpText<"Maximum number of cookies for return address check to be considered for stack protection">, + MarshallingInfoInt, "1">; +// OHOS_LOCAL end def fvisibility : Separate<["-"], "fvisibility">, HelpText<"Default type and symbol visibility">, MarshallingInfoVisibility, "DefaultVisibility">; diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index dfa78bf59c65..996fe6c1bd20 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -1866,6 +1866,8 @@ void CodeGenModule::getDefaultFunctionAttributes(StringRef Name, FuncAttrs.addAttribute("use-soft-float", "true"); FuncAttrs.addAttribute("stack-protector-buffer-size", llvm::utostr(CodeGenOpts.SSPBufferSize)); + FuncAttrs.addAttribute("stack-protector-ret-cookie-size", + llvm::utostr(CodeGenOpts.SSPRetCookieSize)); // OHOS_LOCAL if (LangOpts.NoSignedZero) FuncAttrs.addAttribute("no-signed-zeros-fp-math", "true"); diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index c67643c43a7d..f5f0d56515c2 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -1951,8 +1951,12 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D, B.addAttribute(llvm::Attribute::StackProtectStrong); else if (LangOpts.getStackProtector() == LangOptions::SSPReq) B.addAttribute(llvm::Attribute::StackProtectReq); - else if (LangOpts.getStackProtector() == LangOptions::SSPRet) - B.addAttribute(llvm::Attribute::StackProtectRet); + // OHOS_LOCAL begin + else if (LangOpts.getStackProtector() == LangOptions::SSPRetStrong) + B.addAttribute(llvm::Attribute::StackProtectRetStrong); + else if (LangOpts.getStackProtector() == LangOptions::SSPRetReq) + B.addAttribute(llvm::Attribute::StackProtectRetReq); + // OHOS_LOCAL end } if (!D) { diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index c4355b9d52ec..d54dd6e1dfec 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -3259,7 +3259,10 @@ static void RenderSSPOptions(const Driver &D, const ToolChain &TC, if (Arg *A = Args.getLastArg(options::OPT_fno_stack_protector, options::OPT_fstack_protector_all, - options::OPT_fstack_protector_ret, + // OHOS_LOCAL begin + options::OPT_fstack_protector_ret_all, + options::OPT_fstack_protector_ret_strong, + // OHOS_LOCAL end options::OPT_fstack_protector_strong, options::OPT_fstack_protector)) { if (A->getOption().matches(options::OPT_fstack_protector)) @@ -3267,8 +3270,12 @@ static void RenderSSPOptions(const Driver &D, const ToolChain &TC, std::max<>(LangOptions::SSPOn, DefaultStackProtectorLevel); else if (A->getOption().matches(options::OPT_fstack_protector_strong)) StackProtectorLevel = LangOptions::SSPStrong; - else if (A->getOption().matches(options::OPT_fstack_protector_ret)) - StackProtectorLevel = LangOptions::SSPRet; + // OHOS_LOCAL begin + else if (A->getOption().matches(options::OPT_fstack_protector_ret_strong)) + StackProtectorLevel = LangOptions::SSPRetStrong; + else if (A->getOption().matches(options::OPT_fstack_protector_ret_all)) + StackProtectorLevel = LangOptions::SSPRetReq; + // OHOS_LOCAL end else if (A->getOption().matches(options::OPT_fstack_protector_all)) StackProtectorLevel = LangOptions::SSPReq; } else { @@ -3280,7 +3287,7 @@ static void RenderSSPOptions(const Driver &D, const ToolChain &TC, CmdArgs.push_back(Args.MakeArgString(Twine(StackProtectorLevel))); } - // --param ssp-buffer-size= + // --param ssp-buffer-size= && ssp-ret-cookie-size=, OHOS_LOCAL for (const Arg *A : Args.filtered(options::OPT__param)) { StringRef Str(A->getValue()); if (Str.startswith("ssp-buffer-size=")) { @@ -3291,6 +3298,28 @@ static void RenderSSPOptions(const Driver &D, const ToolChain &TC, } A->claim(); } + // OHOS_LOCAL begin + if (Str.startswith("ssp-ret-cookie-size=")) { + unsigned int SSPRetCookieSize = 0; + // Currently only supports AArch64 architecture. + if (!EffectiveTriple.isAArch64() || !EffectiveTriple.isOSBinFormatELF()) { + D.Diag(diag::err_drv_unsupported_opt_for_target) + << Str.take_front(19) << EffectiveTriple.getTriple(); + continue; + } + // The parameter must be greater than 0. + if (Str.drop_front(20).getAsInteger(10, SSPRetCookieSize) || !SSPRetCookieSize) { + D.Diag(diag::err_drv_invalid_int_value) + << Str.take_front(19) << Str.drop_front(20); + continue; + } + if (StackProtectorLevel) { + CmdArgs.push_back("-stack-protector-ret-cookie-size"); + CmdArgs.push_back(Args.MakeArgString(Str.drop_front(20))); + } + A->claim(); + } + // OHOS_LOCAL end } const std::string &TripleStr = EffectiveTriple.getTriple(); diff --git a/clang/lib/Frontend/InitPreprocessor.cpp b/clang/lib/Frontend/InitPreprocessor.cpp index 34f8c91fb79d..cf40036385f2 100644 --- a/clang/lib/Frontend/InitPreprocessor.cpp +++ b/clang/lib/Frontend/InitPreprocessor.cpp @@ -1185,8 +1185,12 @@ static void InitializePredefinedMacros(const TargetInfo &TI, Builder.defineMacro("__SSP_STRONG__", "2"); else if (LangOpts.getStackProtector() == LangOptions::SSPReq) Builder.defineMacro("__SSP_ALL__", "3"); - else if (LangOpts.getStackProtector() == LangOptions::SSPRet) - Builder.defineMacro("__SSP_RET__", "4"); + // OHOS_LOCAL begin + else if (LangOpts.getStackProtector() == LangOptions::SSPRetStrong) + Builder.defineMacro("__SSP_RET_STRONG__", "4"); + else if (LangOpts.getStackProtector() == LangOptions::SSPRetReq) + Builder.defineMacro("__SSP_RET_ALL__", "5"); + // OHOS_LOCAL end if (PPOpts.SetUpStaticAnalyzer) Builder.defineMacro("__clang_analyzer__"); diff --git a/clang/test/CodeGen/stack-protector.c b/clang/test/CodeGen/stack-protector.c index e880f4b2a3aa..6085e4844be1 100644 --- a/clang/test/CodeGen/stack-protector.c +++ b/clang/test/CodeGen/stack-protector.c @@ -2,12 +2,20 @@ // RUN: %clang_cc1 -no-opaque-pointers -emit-llvm -o - %s -stack-protector 1 | FileCheck -check-prefix=DEF -check-prefix=SSP %s // RUN: %clang_cc1 -no-opaque-pointers -emit-llvm -o - %s -stack-protector 2 | FileCheck -check-prefix=DEF -check-prefix=SSPSTRONG %s // RUN: %clang_cc1 -no-opaque-pointers -emit-llvm -o - %s -stack-protector 3 | FileCheck -check-prefix=DEF -check-prefix=SSPREQ %s +// OHOS_LOCAL begin +// RUN: %clang_cc1 -no-opaque-pointers -emit-llvm -o - %s -stack-protector 4 | FileCheck -check-prefix=DEF -check-prefix=SSPRETSTRONG %s +// RUN: %clang_cc1 -no-opaque-pointers -emit-llvm -o - %s -stack-protector 5 | FileCheck -check-prefix=DEF -check-prefix=SSPRETREQ %s +// OHOS_LOCAL end // RUN: %clang_cc1 -no-opaque-pointers -emit-llvm -o - %s -fsanitize=safe-stack | FileCheck -check-prefix=DEF -check-prefix=SAFESTACK-NOSSP %s // RUN: %clang_cc1 -no-opaque-pointers -emit-llvm -o - %s -fsanitize=safe-stack -stack-protector 0 | FileCheck -check-prefix=DEF -check-prefix=SAFESTACK-NOSSP %s // RUN: %clang_cc1 -no-opaque-pointers -emit-llvm -o - %s -fsanitize=safe-stack -stack-protector 1 | FileCheck -check-prefix=DEF -check-prefix=SAFESTACK-SSP %s // RUN: %clang_cc1 -no-opaque-pointers -emit-llvm -o - %s -fsanitize=safe-stack -stack-protector 2 | FileCheck -check-prefix=DEF -check-prefix=SAFESTACK-SSPSTRONG %s // RUN: %clang_cc1 -no-opaque-pointers -emit-llvm -o - %s -fsanitize=safe-stack -stack-protector 3 | FileCheck -check-prefix=DEF -check-prefix=SAFESTACK-SSPREQ %s +// OHOS_LOCAL begin +// RUN: %clang_cc1 -no-opaque-pointers -emit-llvm -o - %s -fsanitize=safe-stack -stack-protector 4 | FileCheck -check-prefix=DEF -check-prefix=SAFESTACK-SSPRETSTRONG %s +// RUN: %clang_cc1 -no-opaque-pointers -emit-llvm -o - %s -fsanitize=safe-stack -stack-protector 5 | FileCheck -check-prefix=DEF -check-prefix=SAFESTACK-SSPRETREQ %s +// OHOS_LOCAL end typedef __SIZE_TYPE__ size_t; @@ -34,6 +42,10 @@ void test2(const char *msg) { // SSP: attributes #[[A]] = {{.*}} ssp{{ }} // SSPSTRONG: attributes #[[A]] = {{.*}} sspstrong // SSPREQ: attributes #[[A]] = {{.*}} sspreq +// OHOS_LOCAL begin +// SSPRETSTRONG: attributes #[[A]] = {{.*}} sspretstrong +// SSPRETREQ: attributes #[[A]] = {{.*}} sspretreq +// OHOS_LOCAL end // SAFESTACK-NOSSP: attributes #[[A]] = {{.*}} safestack // SAFESTACK-NOSSP-NOT: ssp @@ -41,6 +53,10 @@ void test2(const char *msg) { // SAFESTACK-SSP: attributes #[[A]] = {{.*}} safestack ssp{{ }} // SAFESTACK-SSPSTRONG: attributes #[[A]] = {{.*}} safestack sspstrong // SAFESTACK-SSPREQ: attributes #[[A]] = {{.*}} safestack sspreq +// OHOS_LOCAL begin +// SAFESTACK-SSPRETSTRONG: attributes #[[A]] = {{.*}} safestack sspretstrong +// SAFESTACK-SSPRETREQ: attributes #[[A]] = {{.*}} safestack sspretreq +// OHOS_LOCAL end // NOSSP-NOT: attributes #[[B]] = {{.*}} ssp // SSP-NOT: attributes #[[B]] = {{.*}} ssp{{ }} @@ -53,3 +69,9 @@ void test2(const char *msg) { // SAFESTACK-SSPSTRONG-NOT: attributes #[[B]] = {{.*}} safestack sspstrong // SAFESTACK-SSPREQ: attributes #[[B]] = {{.*}} safestack // SAFESTACK-SSPREQ-NOT: attributes #[[B]] = {{.*}} safestack sspreq +// OHOS_LOCAL begin +// SAFESTACK-SSPRETSTRONG: attributes #[[B]] = {{.*}} safestack +// SAFESTACK-SSPRETSTRONG-NOT: attributes #[[B]] = {{.*}} safestack sspretstrong +// SAFESTACK-SSPRETREQ: attributes #[[B]] = {{.*}} safestack +// SAFESTACK-SSPRETREQ-NOT: attributes #[[B]] = {{.*}} safestack sspretreq +// OHOS_LOCAL end diff --git a/clang/test/Driver/claim-unused.c b/clang/test/Driver/claim-unused.c index c7b798934b3c..19ad9a4d38f6 100644 --- a/clang/test/Driver/claim-unused.c +++ b/clang/test/Driver/claim-unused.c @@ -1,3 +1,7 @@ // RUN: touch %t.o // RUN: %clang --param ssp-buffer-size=1 %t.o -### 2>&1 | FileCheck %s // CHECK-NOT: warning: argument unused during compilation: '--param ssp-buffer-size=1' +// OHOS_LOCAL begin +// RUN: %clang --param ssp-ret-cookie-size=1 %t.o -### 2>&1 | FileCheck %s +// CHECK-NOT: warning: argument unused during compilation: '--param ssp-ret-cookie-size=1' +// OHOS_LOCAL end diff --git a/clang/test/Driver/stack-protector.c b/clang/test/Driver/stack-protector.c index 169376919a71..db3172d7e869 100644 --- a/clang/test/Driver/stack-protector.c +++ b/clang/test/Driver/stack-protector.c @@ -24,6 +24,24 @@ // SSP-ALL: "-stack-protector" "3" // SSP-ALL-NOT: "-stack-protector-buffer-size" +// OHOS_LOCAL begin +// RUN: %clang -fstack-protector-ret-strong -### %s 2>&1 | FileCheck %s -check-prefix=SSP-RET-STRONG +// SSP-RET-STRONG: "-stack-protector" "4" +// SSP-RET-STRONG-NOT: "-stack-protector-buffer-size" + +// RUN: %clang -fstack-protector-ret-all -### %s 2>&1 | FileCheck %s -check-prefix=SSP-RET-ALL +// SSP-RET-ALL: "-stack-protector" "5" +// SSP-RET-ALL-NOT: "-stack-protector-buffer-size" + +// RUN: %clang -target aarch64-linux-ohos -fstack-protector-ret-strong --param ssp-ret-cookie-size=10 -### %s 2>&1 | FileCheck %s -check-prefix=SSP-RET-COOKIE-STRONG +// SSP-RET-COOKIE-STRONG: "-stack-protector" "4" +// SSP-RET-COOKIE-STRONG: "-stack-protector-ret-cookie-size" "10" + +// RUN: %clang -target aarch64-linux-ohos -fstack-protector-ret-all --param ssp-ret-cookie-size=-1 -### %s 2>&1 | FileCheck %s -check-prefix=SSP-RET-COOKIE-ALL +// SSP-RET-COOKIE-ALL: invalid integral value +// SSP-RET-COOKIE-ALL: "-stack-protector" "5" +// OHOS_LOCAL end + // RUN: %clang -target x86_64-scei-ps4 -### %s 2>&1 | FileCheck %s -check-prefix=SSP-PS4 // RUN: %clang -target x86_64-scei-ps4 -fstack-protector -### %s 2>&1 | FileCheck %s -check-prefix=SSP-PS4 // SSP-PS4: "-stack-protector" "2" diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp index 9f30117c0279..51c505d159d5 100644 --- a/lld/ELF/LinkerScript.cpp +++ b/lld/ELF/LinkerScript.cpp @@ -103,7 +103,7 @@ static StringRef getOutputSectionName(const InputSectionBase *s) { for (StringRef v : {".data.rel.ro", ".data", ".rodata", ".bss.rel.ro", ".bss", ".gcc_except_table", ".init_array", ".fini_array", ".tbss", ".tdata", - ".ARM.exidx", ".ARM.extab", ".ctors", ".dtors"}) + ".ARM.exidx", ".ARM.extab", ".ctors", ".dtors", ".ohos.randomdata"}) // OHOS_LOCAL if (isSectionPrefix(v, s->name)) return v; diff --git a/lld/ELF/ScriptParser.cpp b/lld/ELF/ScriptParser.cpp index 0576c6e66f4d..e37faf90e132 100644 --- a/lld/ELF/ScriptParser.cpp +++ b/lld/ELF/ScriptParser.cpp @@ -1578,7 +1578,7 @@ unsigned ScriptParser::readPhdrType() { .Case("PT_OPENBSD_RANDOMIZE", PT_OPENBSD_RANDOMIZE) .Case("PT_OPENBSD_WXNEEDED", PT_OPENBSD_WXNEEDED) .Case("PT_OPENBSD_BOOTDATA", PT_OPENBSD_BOOTDATA) - .Case("PT_OHOS_RANDOMDATA", PT_OHOS_RANDOMDATA) + .Case("PT_OHOS_RANDOMDATA", PT_OHOS_RANDOMDATA) // OHOS_LOCAL .Default(-1); if (ret == (unsigned)-1) { diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index bf213b199d4f..e27e656d43c7 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -833,7 +833,7 @@ static bool isRelroSection(const OutputSection *sec) { s == ".dtors" || s == ".jcr" || s == ".eh_frame" || s == ".fini_array" || s == ".init_array" || s == ".openbsd.randomdata" || s == ".preinit_array" || - s == ".ohos.randomdata"; + s == ".ohos.randomdata"; // OHOS_LOCAL } // We compute a rank for each section. The rank indicates where the @@ -2428,8 +2428,10 @@ SmallVector Writer::createPhdrs(Partition &part) { if (OutputSection *cmd = findSection(".note.gnu.property", partNo)) addHdr(PT_GNU_PROPERTY, PF_R)->add(cmd); + // OHOS_LOCAL if (OutputSection *cmd = findSection(".ohos.randomdata", partNo)) addHdr(PT_OHOS_RANDOMDATA, cmd->getPhdrFlags())->add(cmd); + // OHOS_LOCAL // Create one PT_NOTE per a group of contiguous SHT_NOTE sections with the // same alignment. diff --git a/lld/wasm/Writer.cpp b/lld/wasm/Writer.cpp index f98c95526c9e..d98ea1d71b7a 100644 --- a/lld/wasm/Writer.cpp +++ b/lld/wasm/Writer.cpp @@ -868,6 +868,10 @@ static StringRef getOutputDataSegmentName(const InputChunk &seg) { return ".bss"; if (seg.name.startswith(".rodata.")) return ".rodata"; + // OHOS_LOCAL begin + if (seg.name.startswith(".ohos.randomdata.")) + return ".ohos.randomdata"; + // OHOS_LOCAL end return seg.name; } diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst index bc1f63f272f3..9d6ad6699fbf 100644 --- a/llvm/docs/LangRef.rst +++ b/llvm/docs/LangRef.rst @@ -2126,6 +2126,67 @@ example: function which has an ``ssp`` or ``sspstrong`` attribute, the calling function's attribute will be upgraded to ``sspreq``. +.. OHOS_LOCAL begin +``sspretstrong`` + This attribute indicates that the function should emit a stack smashing + protector with return address check for backward cfi. This attribute + causes a strong heuristic to be used when determining if a function needs + stack protectors. This overrides the ``sspstrong`` function attributes. + + Variables that are identified as requiring a protector will be arranged + on the stack such that they are adjacent to the stack protector guard. + The specific layout rules are: + + #. Large arrays and structures containing large arrays + (``>= ssp-buffer-size``) are closest to the stack protector. + #. Small arrays and structures containing small arrays + (``< ssp-buffer-size``) are 2nd closest to the protector. + #. Variables that have had their address taken are 3rd closest to the + protector. + + The rules for the number of cookies used by additional backward cfi + protection are: + + #. If ``ssp-ret-cookie-size`` is not specified, the functions protected + by ``sspretstrong`` in each object share the one cookie. + #. The maximum number of cookies used by ``sspretstrong`` in each object + does not exceed ``ssp-ret-cookie-size``. + + This overrides the ``ssp`` function attribute. + + If a function with an ``sspretstrong`` attribute is inlined into a calling + function which has an ``ssp`` or ``sspstrong`` attribute, the calling function's attribute + will be upgraded to ``sspretstrong``. + +``sspretreq`` + This attribute indicates that the function should *always* emit a stack + smashing protector with return address check for backward cfi. This + overrides the ``sspreq`` and ``sspstrong`` function attributes. + + Variables that are identified as requiring a protector will be arranged + on the stack such that they are adjacent to the stack protector guard. + The specific layout rules are: + + #. Large arrays and structures containing large arrays + (``>= ssp-buffer-size``) are closest to the stack protector. + #. Small arrays and structures containing small arrays + (``< ssp-buffer-size``) are 2nd closest to the protector. + #. Variables that have had their address taken are 3rd closest to the + protector. + + The rules for the number of cookies used by additional backward cfi + protection are: + + #. If ``ssp-ret-cookie-size`` is not specified, the functions protected + by ``sspretreq`` in each object share the one cookie. + #. The maximum number of cookies used by ``sspretreq`` in each object + does not exceed ``ssp-ret-cookie-size``. + + If a function with an ``sspretreq`` attribute is inlined into a calling + function which has an ``sspreq`` or ``sspretstrong`` attribute, the calling + function's attribute will be upgraded to ``sspretreq``. +.. OHOS_LOCAL end + ``strictfp`` This attribute indicates that the function was called from a scope that requires strict floating-point semantics. LLVM will not attempt any diff --git a/llvm/include/llvm/BinaryFormat/ELF.h b/llvm/include/llvm/BinaryFormat/ELF.h index 9d4b9e9878de..556fe9c6a1a0 100644 --- a/llvm/include/llvm/BinaryFormat/ELF.h +++ b/llvm/include/llvm/BinaryFormat/ELF.h @@ -1381,7 +1381,7 @@ enum { PT_OPENBSD_WXNEEDED = 0x65a3dbe7, // Program does W^X violations. PT_OPENBSD_BOOTDATA = 0x65a41be6, // Section for boot arguments. - PT_OHOS_RANDOMDATA = 0x6788FC60, // Fill with random data. + PT_OHOS_RANDOMDATA = 0x6788FC60, // Fill with random data. OHOS_LOCAL // ARM program header types. PT_ARM_ARCHEXT = 0x70000000, // Platform architecture compatibility info diff --git a/llvm/include/llvm/Bitcode/LLVMBitCodes.h b/llvm/include/llvm/Bitcode/LLVMBitCodes.h index 104068e0c2a0..6cd0011085e0 100644 --- a/llvm/include/llvm/Bitcode/LLVMBitCodes.h +++ b/llvm/include/llvm/Bitcode/LLVMBitCodes.h @@ -689,7 +689,10 @@ enum AttributeKindCodes { ATTR_KIND_ALLOC_KIND = 82, ATTR_KIND_PRESPLIT_COROUTINE = 83, ATTR_KIND_FNRETTHUNK_EXTERN = 84, - ATTR_KIND_STACK_PROTECT_RET = 85, + /// OHOS_LOCAL begin + ATTR_KIND_STACK_PROTECT_RET_REQ = 85, + ATTR_KIND_STACK_PROTECT_RET_STRONG = 86, + /// OHOS_LOCAL end }; enum ComdatSelectionKindCodes { diff --git a/llvm/include/llvm/CodeGen/MachineFrameInfo.h b/llvm/include/llvm/CodeGen/MachineFrameInfo.h index 1c603e2ccdb2..c5adc1b254bb 100644 --- a/llvm/include/llvm/CodeGen/MachineFrameInfo.h +++ b/llvm/include/llvm/CodeGen/MachineFrameInfo.h @@ -272,12 +272,14 @@ private: /// The frame index for the stack protector. int StackProtectorIdx = -1; + /// OHOS_LOCAL begin struct StackProtectorRet { /// The register to use for stack protector & backwrad cfi calculations unsigned Register = 0; /// Set to true if this function needs stack-protector-ret bool Needed = false; } SPR; + /// OHOS_LOCAL end /// The frame index for the function context. Used for SjLj exceptions. int FunctionContextIdx = -1; @@ -365,6 +367,7 @@ public: void setStackProtectorIndex(int I) { StackProtectorIdx = I; } bool hasStackProtectorIndex() const { return StackProtectorIdx != -1; } + /// OHOS_LOCAL begin /// Get / Set stack protector ret calculation register unsigned getStackProtectorRetRegister() const { return SPR.Register; } void setStackProtectorRetRegister(unsigned I) { SPR.Register = I; } @@ -372,6 +375,7 @@ public: /// Get / Set if this frame needs backward cfi protect. void setStackProtectorRetNeeded(bool I) { SPR.Needed = I; } bool getStackProtectorRetNeeded() const { return SPR.Needed; } + /// OHOS_LOCAL end /// Return the index for the function context object. /// This object is used for SjLj exceptions. diff --git a/llvm/include/llvm/CodeGen/StackProtector.h b/llvm/include/llvm/CodeGen/StackProtector.h index aac31eafc65d..555c8ac8a271 100644 --- a/llvm/include/llvm/CodeGen/StackProtector.h +++ b/llvm/include/llvm/CodeGen/StackProtector.h @@ -60,6 +60,11 @@ private: /// protection when -fstack-protection is used. unsigned SSPBufferSize = 0; + /// OHOS_LOCAL begin + /// The total of cookies that -fstack-protector-ret used. + unsigned SSPRetCookieSize = 1; + /// OHOS_LOCAL end + /// VisitedPHIs - The set of PHI nodes visited when determining /// if a variable's reference has been taken. This set /// is maintained to ensure we don't visit the same PHI node multiple @@ -100,7 +105,7 @@ private: /// stack protector based upon the stack protector level. bool RequiresStackProtector(); - bool CreateSSPRetCookie(); + bool CreateSSPRetCookie(); // OHOS_LOCAL public: static char ID; // Pass identification, replacement for typeid. diff --git a/llvm/include/llvm/CodeGen/StackProtectorRetLowering.h b/llvm/include/llvm/CodeGen/StackProtectorRetLowering.h index 667d0f04ceea..f6048d826568 100644 --- a/llvm/include/llvm/CodeGen/StackProtectorRetLowering.h +++ b/llvm/include/llvm/CodeGen/StackProtectorRetLowering.h @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +/// OHOS_LOCAL begin #ifndef LLVM_CODEGEN_STACKPROTECTORRETLOWERING_H #define LLVM_CODEGEN_STACKPROTECTORRETLOWERING_H @@ -55,3 +56,4 @@ public: } // namespace llvm #endif +/// OHOS_LOCAL end diff --git a/llvm/include/llvm/CodeGen/TargetFrameLowering.h b/llvm/include/llvm/CodeGen/TargetFrameLowering.h index 9a8bc4bd517a..e37c118c2124 100644 --- a/llvm/include/llvm/CodeGen/TargetFrameLowering.h +++ b/llvm/include/llvm/CodeGen/TargetFrameLowering.h @@ -14,7 +14,7 @@ #define LLVM_CODEGEN_TARGETFRAMELOWERING_H #include "llvm/CodeGen/MachineBasicBlock.h" -#include "llvm/CodeGen/StackProtectorRetLowering.h" +#include "llvm/CodeGen/StackProtectorRetLowering.h" // OHOS_LOCAL #include "llvm/Support/TypeSize.h" #include @@ -218,9 +218,12 @@ public: virtual void emitZeroCallUsedRegs(BitVector RegsToZero, MachineBasicBlock &MBB) const {} + /// OHOS_LOCAL begin + /// Instances about backward cfi and stack protection provided by different architectures. virtual const StackProtectorRetLowering *getStackProtectorRet() const { return nullptr; } + /// OHOS_LOCAL begin /// With basic block sections, emit callee saved frame moves for basic blocks /// that are in a different section. diff --git a/llvm/include/llvm/IR/Attributes.td b/llvm/include/llvm/IR/Attributes.td index ce99b289bdbd..a10d9d9c6b23 100644 --- a/llvm/include/llvm/IR/Attributes.td +++ b/llvm/include/llvm/IR/Attributes.td @@ -244,8 +244,13 @@ def Speculatable : EnumAttr<"speculatable", [FnAttr]>; /// Stack protection. def StackProtect : EnumAttr<"ssp", [FnAttr]>; -/// Stack protection for return address. -def StackProtectRet : EnumAttr<"sspret", [FnAttr]>; +/// OHOS_LOCAL begin +/// Stack protection required with return address check. +def StackProtectRetReq : EnumAttr<"sspretreq", [FnAttr]>; + +/// Strong Stack protection with return address check. +def StackProtectRetStrong : EnumAttr<"sspretstrong", [FnAttr]>; +/// OHOS_LOCAL end /// Stack protection required. def StackProtectReq : EnumAttr<"sspreq", [FnAttr]>; diff --git a/llvm/include/llvm/IR/Function.h b/llvm/include/llvm/IR/Function.h index e661a11a7b75..f423e3832514 100644 --- a/llvm/include/llvm/IR/Function.h +++ b/llvm/include/llvm/IR/Function.h @@ -418,9 +418,11 @@ public: return AttributeSets.getFnStackAlignment(); } - /// Returns true if the function has ssp, sspstrong, sspret or sspreq fn - /// attrs. + /// OHOS_LOCAL begin + /// Returns true if the function has ssp, sspstrong, sspretstrong, + /// sspretreq or sspreq fn attrs. bool hasStackProtectorFnAttr() const; + /// OHOS_LOCAL end /// adds the dereferenceable attribute to the list of attributes for /// the given arg. diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp index 106d2b78170f..4e88d10e7f65 100644 --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -1725,8 +1725,6 @@ static uint64_t getRawAttributeMask(Attribute::AttrKind Val) { return 1ULL << 62; case Attribute::NoFree: return 1ULL << 63; - case Attribute::StackProtectRet: - return 1ULL << 64; default: // Other attributes are not supported in the raw format, // as we ran out of space. @@ -1951,8 +1949,12 @@ static Attribute::AttrKind getAttrFromCode(uint64_t Code) { return Attribute::StackAlignment; case bitc::ATTR_KIND_STACK_PROTECT: return Attribute::StackProtect; - case bitc::ATTR_KIND_STACK_PROTECT_RET: - return Attribute::StackProtectRet; + /// OHOS_LOCAL begin + case bitc::ATTR_KIND_STACK_PROTECT_RET_REQ: + return Attribute::StackProtectRetReq; + case bitc::ATTR_KIND_STACK_PROTECT_RET_STRONG: + return Attribute::StackProtectRetStrong; + /// OHOS_LOCAL end case bitc::ATTR_KIND_STACK_PROTECT_REQ: return Attribute::StackProtectReq; case bitc::ATTR_KIND_STACK_PROTECT_STRONG: diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp index 4fac16a7491d..5e05ff26647e 100644 --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -728,8 +728,12 @@ static uint64_t getAttrKindEncoding(Attribute::AttrKind Kind) { return bitc::ATTR_KIND_STACK_ALIGNMENT; case Attribute::StackProtect: return bitc::ATTR_KIND_STACK_PROTECT; - case Attribute::StackProtectRet: - return bitc::ATTR_KIND_STACK_PROTECT_RET; + /// OHOS_LOCAL begin + case Attribute::StackProtectRetReq: + return bitc::ATTR_KIND_STACK_PROTECT_RET_REQ; + case Attribute::StackProtectRetStrong: + return bitc::ATTR_KIND_STACK_PROTECT_RET_STRONG; + /// OHOS_LOCAL end case Attribute::StackProtectReq: return bitc::ATTR_KIND_STACK_PROTECT_REQ; case Attribute::StackProtectStrong: diff --git a/llvm/lib/CodeGen/CMakeLists.txt b/llvm/lib/CodeGen/CMakeLists.txt index 5f0a919f97a1..530d5c1decc2 100644 --- a/llvm/lib/CodeGen/CMakeLists.txt +++ b/llvm/lib/CodeGen/CMakeLists.txt @@ -206,7 +206,7 @@ add_llvm_component_library(LLVMCodeGen StackMapLivenessAnalysis.cpp StackMaps.cpp StackProtector.cpp - StackProtectorRetLowering.cpp + StackProtectorRetLowering.cpp # OHOS_LOCAL StackSlotColoring.cpp SwiftErrorValueTracking.cpp SwitchLoweringUtils.cpp diff --git a/llvm/lib/CodeGen/LocalStackSlotAllocation.cpp b/llvm/lib/CodeGen/LocalStackSlotAllocation.cpp index cbde664ef459..e2d3349938b7 100644 --- a/llvm/lib/CodeGen/LocalStackSlotAllocation.cpp +++ b/llvm/lib/CodeGen/LocalStackSlotAllocation.cpp @@ -27,7 +27,7 @@ #include "llvm/CodeGen/TargetOpcodes.h" #include "llvm/CodeGen/TargetRegisterInfo.h" #include "llvm/CodeGen/TargetSubtargetInfo.h" -#include "llvm/IR/Function.h" +#include "llvm/IR/Function.h" // OHOS_LOCAL #include "llvm/InitializePasses.h" #include "llvm/Pass.h" #include "llvm/Support/Debug.h" @@ -195,7 +195,7 @@ void LocalStackSlotPass::calculateFrameObjectOffsets(MachineFunction &Fn) { // Make sure that the stack protector comes before the local variables on the // stack. - Function &F = Fn.getFunction(); + Function &F = Fn.getFunction(); // OHOS_LOCAL SmallSet ProtectedObjs; if (MFI.hasStackProtectorIndex()) { @@ -248,7 +248,9 @@ void LocalStackSlotPass::calculateFrameObjectOffsets(MachineFunction &Fn) { Offset, MaxAlign); AssignProtectedObjSet(AddrOfObjs, ProtectedObjs, MFI, StackGrowsDown, Offset, MaxAlign); - } else if (F.hasFnAttribute(Attribute::StackProtectRet)) { + /// OHOS_LOCAL begin + } else if (F.hasFnAttribute(Attribute::StackProtectRetReq) || + F.hasFnAttribute(Attribute::StackProtectRetStrong)) { StackObjSet LargeArrayObjs; StackObjSet SmallArrayObjs; StackObjSet AddrOfObjs; @@ -279,6 +281,7 @@ void LocalStackSlotPass::calculateFrameObjectOffsets(MachineFunction &Fn) { Offset, MaxAlign); AssignProtectedObjSet(AddrOfObjs, ProtectedObjs, MFI, StackGrowsDown, Offset, MaxAlign); + /// OHOS_LOCAL end } // Then assign frame offsets to stack objects that are not used to spill diff --git a/llvm/lib/CodeGen/PrologEpilogInserter.cpp b/llvm/lib/CodeGen/PrologEpilogInserter.cpp index 2d831819791e..504861c7c7c7 100644 --- a/llvm/lib/CodeGen/PrologEpilogInserter.cpp +++ b/llvm/lib/CodeGen/PrologEpilogInserter.cpp @@ -212,10 +212,12 @@ bool PEI::runOnMachineFunction(MachineFunction &MF) { const Function &F = MF.getFunction(); const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo(); const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering(); - const StackProtectorRetLowering *SPRL = TFI->getStackProtectorRet(); + // OHOS_LOCAL begin + const StackProtectorRetLowering *SPRL = TFI->getStackProtectorRet(); if (SPRL) SPRL->setupStackProtectorRet(MF); + // OHOS_LOCAL end RS = TRI->requiresRegisterScavenging(MF) ? new RegScavenger() : nullptr; FrameIndexVirtualScavenging = TRI->requiresFrameIndexScavenging(MF); @@ -254,9 +256,11 @@ bool PEI::runOnMachineFunction(MachineFunction &MF) { if (!F.hasFnAttribute(Attribute::Naked)) insertPrologEpilogCode(MF); + // OHOS_LOCAL begin // Add StackProtectorRets if using them if (SPRL) SPRL->insertStackProtectorRets(MF); + // OHOS_LOCAL end // Reinsert stashed debug values at the start of the entry blocks. for (auto &I : EntryDbgValues) @@ -367,9 +371,11 @@ void PEI::calculateCallFrameInfo(MachineFunction &MF) { /// Compute the sets of entry and return blocks for saving and restoring /// callee-saved registers, and placing prolog and epilog code. void PEI::calculateSaveRestoreBlocks(MachineFunction &MF) { + // OHOS_LOCAL begin MachineFrameInfo &MFI = MF.getFrameInfo(); const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering(); const StackProtectorRetLowering *SPRL = TFI->getStackProtectorRet(); + // OHOS_LOCAL end // Even when we do not change any CSR, we still want to insert the // prologue and epilogue of the function. @@ -386,6 +392,7 @@ void PEI::calculateSaveRestoreBlocks(MachineFunction &MF) { if (!RestoreBlock->succ_empty() || RestoreBlock->isReturnBlock()) RestoreBlocks.push_back(RestoreBlock); + // OHOS_LOCAL begin // If we are adding stack-protector-rets ensure we can find a available // register for CFI verification. if (SPRL && !SPRL->determineStackProtectorRetRegister(MF)) { @@ -395,8 +402,9 @@ void PEI::calculateSaveRestoreBlocks(MachineFunction &MF) { MFI.setSavePoint(nullptr); MFI.setRestorePoint(nullptr); } else { + // OHOS_LOCAL end return; - } + } // OHOS_LOCAL } // Save refs to entry and return blocks. @@ -408,8 +416,10 @@ void PEI::calculateSaveRestoreBlocks(MachineFunction &MF) { RestoreBlocks.push_back(&MBB); } + // OHOS_LOCAL begin if (SPRL) SPRL->determineStackProtectorRetRegister(MF); + // OHOS_LOCAL end } static void assignCalleeSavedSpillSlots(MachineFunction &F, @@ -446,9 +456,11 @@ static void assignCalleeSavedSpillSlots(MachineFunction &F, } const TargetFrameLowering *TFI = F.getSubtarget().getFrameLowering(); + MachineFrameInfo &MFI = F.getFrameInfo(); + // OHOS_LOCAL begin if (TFI->getStackProtectorRet()) TFI->getStackProtectorRet()->saveStackProtectorRetRegister(F, CSI); - MachineFrameInfo &MFI = F.getFrameInfo(); + // OHOS_LOCAL end if (!TFI->assignCalleeSavedSpillSlots(F, RegInfo, CSI, MinCSFrameIndex, MaxCSFrameIndex)) { // If target doesn't implement this, use generic code. @@ -957,7 +969,7 @@ void PEI::calculateFrameObjectOffsets(MachineFunction &MF) { // Make sure that the stack protector comes before the local variables on the // stack. - Function &F = MF.getFunction(); + Function &F = MF.getFunction(); // OHOS_LOCAL SmallSet ProtectedObjs; if (MFI.hasStackProtectorIndex()) { int StackProtectorFI = MFI.getStackProtectorIndex(); @@ -1027,13 +1039,15 @@ void PEI::calculateFrameObjectOffsets(MachineFunction &MF) { llvm_unreachable("Found protected stack objects not pre-allocated by " "LocalStackSlotPass."); + // OHOS_LOCAL begin AssignProtectedObjSet(LargeArrayObjs, ProtectedObjs, MFI, StackGrowsDown, Offset, MaxAlign, Skew); AssignProtectedObjSet(SmallArrayObjs, ProtectedObjs, MFI, StackGrowsDown, Offset, MaxAlign, Skew); AssignProtectedObjSet(AddrOfObjs, ProtectedObjs, MFI, StackGrowsDown, Offset, MaxAlign, Skew); - } else if (F.hasFnAttribute(Attribute::StackProtectRet)) { + } else if (F.hasFnAttribute(Attribute::StackProtectRetReq) || + F.hasFnAttribute(Attribute::StackProtectRetStrong)) { StackObjSet LargeArrayObjs; StackObjSet SmallArrayObjs; StackObjSet AddrOfObjs; @@ -1067,6 +1081,7 @@ void PEI::calculateFrameObjectOffsets(MachineFunction &MF) { } llvm_unreachable("Unexpected SSPLayoutKind."); } + // OHOS_LOCAL end AssignProtectedObjSet(LargeArrayObjs, ProtectedObjs, MFI, StackGrowsDown, Offset, MaxAlign, Skew); diff --git a/llvm/lib/CodeGen/SafeStack.cpp b/llvm/lib/CodeGen/SafeStack.cpp index 4afe09b62181..6ec99ed8631e 100644 --- a/llvm/lib/CodeGen/SafeStack.cpp +++ b/llvm/lib/CodeGen/SafeStack.cpp @@ -809,7 +809,10 @@ bool SafeStack::run() { if (F.hasFnAttribute(Attribute::StackProtect) || F.hasFnAttribute(Attribute::StackProtectStrong) || F.hasFnAttribute(Attribute::StackProtectReq) || - F.hasFnAttribute(Attribute::StackProtectRet)) { + // OHOS_LOCAL begin + F.hasFnAttribute(Attribute::StackProtectRetStrong) || + F.hasFnAttribute(Attribute::StackProtectRetReq)) { + // OHOS_LOCAL end Value *StackGuard = getStackGuard(IRB, F); StackGuardSlot = IRB.CreateAlloca(StackPtrTy, nullptr); IRB.CreateStore(StackGuard, StackGuardSlot); diff --git a/llvm/lib/CodeGen/StackProtector.cpp b/llvm/lib/CodeGen/StackProtector.cpp index 1a9e8f54461e..bf48cee310ff 100644 --- a/llvm/lib/CodeGen/StackProtector.cpp +++ b/llvm/lib/CodeGen/StackProtector.cpp @@ -96,6 +96,14 @@ bool StackProtector::runOnFunction(Function &Fn) { Attr.getValueAsString().getAsInteger(10, SSPBufferSize)) return false; // Invalid integer string + // OHOS_LOCAL begin + Attr = Fn.getFnAttribute("stack-protector-ret-cookie-size"); + if (Attr.isStringAttribute()) { + if ((Attr.getValueAsString().getAsInteger(10, SSPRetCookieSize)) || (!SSPRetCookieSize)) + return false; // Invalid integer string + } + // OHOS_LOCAL end + if (!RequiresStackProtector()) return false; @@ -109,20 +117,26 @@ bool StackProtector::runOnFunction(Function &Fn) { ++NumFunProtected; - if (Fn.hasFnAttribute(Attribute::StackProtectRet)) { + // OHOS_LOCAL begin + if (Fn.hasFnAttribute(Attribute::StackProtectRetReq) || + Fn.hasFnAttribute(Attribute::StackProtectRetStrong)) { HasIRCheck = true; CreateSSPRetCookie(); // StackProtectRet requires special code generation methods for backward // cfi. return false; } + // OHOS_LOCAL end return InsertStackProtectors(); } +// OHOS_LOCAL begin bool StackProtector::CreateSSPRetCookie() { - std::string cookiename = "__sspret_cookie"; Type *cookietype = Type::getInt8PtrTy(M->getContext()); + std::hash hasher; + std::string hash = std::to_string(hasher((M->getName() + F->getName()).str()) % SSPRetCookieSize); + std::string cookiename = "__sspret_cookie_" + hash; GlobalVariable *cookie = dyn_cast_or_null( M->getOrInsertGlobal(cookiename, cookietype)); @@ -137,6 +151,7 @@ bool StackProtector::CreateSSPRetCookie() { return true; } +// OHOS_LOCAL end /// \param [out] IsLarge is set to true if a protectable array is found and /// it is "large" ( >= ssp-buffer-size). In the case of a structure with @@ -323,9 +338,13 @@ bool StackProtector::RequiresStackProtector() { }); NeedsProtector = true; Strong = true; // Use the same heuristic as strong to determine SSPLayout - } else if (F->hasFnAttribute(Attribute::StackProtectRet)) { + // OHOS_LOCAL begin + } else if (F->hasFnAttribute(Attribute::StackProtectRetReq)) { NeedsProtector = true; Strong = true; + } else if (F->hasFnAttribute(Attribute::StackProtectRetStrong)) { + Strong = true; + // OHOS_LOCAL end } else if (F->hasFnAttribute(Attribute::StackProtectStrong)) Strong = true; else if (!F->hasFnAttribute(Attribute::StackProtect)) diff --git a/llvm/lib/CodeGen/StackProtectorRetLowering.cpp b/llvm/lib/CodeGen/StackProtectorRetLowering.cpp index 4b068995c743..e299a24ab9a4 100644 --- a/llvm/lib/CodeGen/StackProtectorRetLowering.cpp +++ b/llvm/lib/CodeGen/StackProtectorRetLowering.cpp @@ -5,7 +5,15 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// +// +// This is an enhanced function of OHOS for the stack protection. It has made +// special backward cfi protection measures against ROP attacks by adding LR/FP +// checks in the function's prologue and epilogue. It can greatly reduce the +// number of ROP gadgets in the object. +// +//===----------------------------------------------------------------------===// +/// OHOS_LOCAL begin #include "llvm/CodeGen/StackProtectorRetLowering.h" #include "llvm/ADT/SmallSet.h" #include "llvm/CodeGen/MachineFrameInfo.h" @@ -23,7 +31,7 @@ using namespace llvm; /// Check if backward CFI protection is required. void StackProtectorRetLowering::setupStackProtectorRet(MachineFunction &MF) const { - if (MF.getFunction().hasFnAttribute(Attribute::StackProtectRet)) { + if (MF.getFunction().hasFnAttribute("sspret-randomdata")) { for (auto &MBB : MF) { for (auto &T : MBB.terminators()) { if (instrIsRet(T.getOpcode())) { @@ -109,3 +117,4 @@ void StackProtectorRetLowering::insertStackProtectorRets(MachineFunction &MF) co MF.front().addLiveIn(Reg); } } +/// OHOS_LOCAL end diff --git a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp index 2badbe34ae6a..56308d780862 100644 --- a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp +++ b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp @@ -498,6 +498,12 @@ static unsigned getELFSectionType(StringRef Name, SectionKind K) { if (hasPrefix(Name, ".preinit_array")) return ELF::SHT_PREINIT_ARRAY; + // OHOS_LOCAL begin + // ohos customized section, does not occupy ROM in ELF. + if (Name == ".ohos.randomdata") + return ELF::SHT_NOBITS; + // OHOS_LOCAL end + if (hasPrefix(Name, ".llvm.offloading")) return ELF::SHT_LLVM_OFFLOADING; diff --git a/llvm/lib/IR/Attributes.cpp b/llvm/lib/IR/Attributes.cpp index 0143f625903c..b70b6fafe8ec 100644 --- a/llvm/lib/IR/Attributes.cpp +++ b/llvm/lib/IR/Attributes.cpp @@ -1910,26 +1910,37 @@ static void adjustCallerSSPLevel(Function &Caller, const Function &Callee) { AttributeMask OldSSPAttr; OldSSPAttr.addAttribute(Attribute::StackProtect) .addAttribute(Attribute::StackProtectStrong) + .addAttribute(Attribute::StackProtectRetStrong) // OHOS_LOCAL .addAttribute(Attribute::StackProtectReq) - .addAttribute(Attribute::StackProtectRet); + .addAttribute(Attribute::StackProtectRetReq); // OHOS_LOCAL - if (Callee.hasFnAttribute(Attribute::StackProtectRet) && - !Caller.hasFnAttribute(Attribute::StackProtect) && - !Caller.hasFnAttribute(Attribute::StackProtectReq) && - !Caller.hasFnAttribute(Attribute::StackProtectStrong)) { + // OHOS_LOCAL begin + // sspretreq > sspreq > sspretstrong > sspstrong > ssp + if (Callee.hasFnAttribute(Attribute::StackProtectRetReq)) { Caller.removeFnAttrs(OldSSPAttr); - Caller.addFnAttr(Attribute::StackProtectRet); - } else if (Callee.hasFnAttribute(Attribute::StackProtectReq)) { + Caller.addFnAttr(Attribute::StackProtectRetReq); + } else if (Callee.hasFnAttribute(Attribute::StackProtectReq) && + !Caller.hasFnAttribute(Attribute::StackProtectRetReq)) { Caller.removeFnAttrs(OldSSPAttr); Caller.addFnAttr(Attribute::StackProtectReq); - } else if (Callee.hasFnAttribute(Attribute::StackProtectStrong) && + } else if (Callee.hasFnAttribute(Attribute::StackProtectRetStrong) && + !Caller.hasFnAttribute(Attribute::StackProtectRetReq) && !Caller.hasFnAttribute(Attribute::StackProtectReq)) { Caller.removeFnAttrs(OldSSPAttr); + Caller.addFnAttr(Attribute::StackProtectRetStrong); + } else if (Callee.hasFnAttribute(Attribute::StackProtectStrong) && + !Caller.hasFnAttribute(Attribute::StackProtectRetReq) && + !Caller.hasFnAttribute(Attribute::StackProtectReq) && + !Caller.hasFnAttribute(Attribute::StackProtectRetStrong)) { + Caller.removeFnAttrs(OldSSPAttr); Caller.addFnAttr(Attribute::StackProtectStrong); } else if (Callee.hasFnAttribute(Attribute::StackProtect) && !Caller.hasFnAttribute(Attribute::StackProtectReq) && - !Caller.hasFnAttribute(Attribute::StackProtectStrong)) + !Caller.hasFnAttribute(Attribute::StackProtectStrong) && + !Caller.hasFnAttribute(Attribute::StackProtectRetReq) && + !Caller.hasFnAttribute(Attribute::StackProtectRetStrong)) Caller.addFnAttr(Attribute::StackProtect); + // OHOS_LOCAL end } /// If the inlined function required stack probes, then ensure that diff --git a/llvm/lib/IR/Function.cpp b/llvm/lib/IR/Function.cpp index 300592a38b16..5a073632d385 100644 --- a/llvm/lib/IR/Function.cpp +++ b/llvm/lib/IR/Function.cpp @@ -707,7 +707,10 @@ bool Function::hasStackProtectorFnAttr() const { return hasFnAttribute(Attribute::StackProtect) || hasFnAttribute(Attribute::StackProtectStrong) || hasFnAttribute(Attribute::StackProtectReq) || - hasFnAttribute(Attribute::StackProtectRet); + /// OHOS_LOCAL begin + hasFnAttribute(Attribute::StackProtectRetStrong) || + hasFnAttribute(Attribute::StackProtectRetReq); + /// OHOS_LOCAL end } /// Copy all additional attributes (those not needed to create a Function) from diff --git a/llvm/lib/MC/MCParser/ELFAsmParser.cpp b/llvm/lib/MC/MCParser/ELFAsmParser.cpp index 38977b7641a0..758a29bc10b7 100644 --- a/llvm/lib/MC/MCParser/ELFAsmParser.cpp +++ b/llvm/lib/MC/MCParser/ELFAsmParser.cpp @@ -549,7 +549,8 @@ bool ELFAsmParser::ParseSectionArguments(bool IsPush, SMLoc loc) { hasPrefix(SectionName, ".bss") || hasPrefix(SectionName, ".init_array") || hasPrefix(SectionName, ".fini_array") || - hasPrefix(SectionName, ".preinit_array")) + hasPrefix(SectionName, ".preinit_array") || + SectionName == ".ohos.randomdata") // OHOS_LOCAL Flags |= ELF::SHF_ALLOC | ELF::SHF_WRITE; else if (hasPrefix(SectionName, ".tdata") || hasPrefix(SectionName, ".tbss")) Flags |= ELF::SHF_ALLOC | ELF::SHF_WRITE | ELF::SHF_TLS; @@ -632,6 +633,10 @@ EndStmt: Type = ELF::SHT_FINI_ARRAY; else if (hasPrefix(SectionName, ".preinit_array")) Type = ELF::SHT_PREINIT_ARRAY; + // OHOS_LOCAL begin + else if (hasPrefix(SectionName, ".ohos.randomdata")) + Type = ELF::SHT_NOBITS; + // OHOS_LOCAL end } else { if (TypeName == "init_array") Type = ELF::SHT_INIT_ARRAY; diff --git a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp index 8ed54a6703cf..68ae9b5b41f7 100644 --- a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp +++ b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp @@ -1402,6 +1402,7 @@ void AArch64AsmPrinter::emitInstruction(const MachineInstr *MI) { return; } + // OHOS_LOCAL begin case AArch64::SSP_RET_TRAP: { MCSymbol *TempSymbol = OutContext.createTempSymbol(); /* Compare and branch */ @@ -1413,6 +1414,7 @@ void AArch64AsmPrinter::emitInstruction(const MachineInstr *MI) { OutStreamer->emitLabel(TempSymbol); return; } + // OHOS_LOCAL end case AArch64::JumpTableDest32: case AArch64::JumpTableDest16: diff --git a/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp b/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp index a7a1c969faf5..bed7aa3d9ca6 100644 --- a/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp @@ -189,7 +189,7 @@ #include "AArch64InstrInfo.h" #include "AArch64MachineFunctionInfo.h" #include "AArch64RegisterInfo.h" -#include "AArch64StackProtectorRetLowering.h" +#include "AArch64StackProtectorRetLowering.h" // OHOS_LOCAL #include "AArch64Subtarget.h" #include "AArch64TargetMachine.h" #include "MCTargetDesc/AArch64AddressingModes.h" @@ -2969,9 +2969,11 @@ void AArch64FrameLowering::determineCalleeSaves(MachineFunction &MF, ? RegInfo->getBaseRegister() : (unsigned)AArch64::NoRegister; + // OHOS_LOCAL begin if (MFI.hasStackProtectorRetRegister()) { SavedRegs.set(MFI.getStackProtectorRetRegister()); } + // OHOS_LOCAL end unsigned ExtraCSSpill = 0; // Figure out which callee-saved registers to save/restore. @@ -3787,10 +3789,12 @@ unsigned AArch64FrameLowering::getWinEHFuncletFrameSize( getStackAlign()); } +/// OHOS_LOCAL begin const StackProtectorRetLowering * AArch64FrameLowering::getStackProtectorRet() const { return &SPRL; } +/// OHOS_LOCAL end namespace { struct FrameObject { diff --git a/llvm/lib/Target/AArch64/AArch64FrameLowering.h b/llvm/lib/Target/AArch64/AArch64FrameLowering.h index 3bfecc6cc768..bab56e9f8645 100644 --- a/llvm/lib/Target/AArch64/AArch64FrameLowering.h +++ b/llvm/lib/Target/AArch64/AArch64FrameLowering.h @@ -13,7 +13,7 @@ #ifndef LLVM_LIB_TARGET_AARCH64_AARCH64FRAMELOWERING_H #define LLVM_LIB_TARGET_AARCH64_AARCH64FRAMELOWERING_H -#include "AArch64StackProtectorRetLowering.h" +#include "AArch64StackProtectorRetLowering.h" // OHOS_LOCAL #include "llvm/CodeGen/TargetFrameLowering.h" #include "llvm/Support/TypeSize.h" @@ -23,12 +23,11 @@ class MCCFIInstruction; class AArch64FrameLowering : public TargetFrameLowering { public: - const AArch64StackProtectorRetLowering SPRL; + const AArch64StackProtectorRetLowering SPRL; // OHOS_LOCAL explicit AArch64FrameLowering() : TargetFrameLowering(StackGrowsDown, Align(16), 0, Align(16), - true /*StackRealignable*/), - SPRL() {} + true /*StackRealignable*/), SPRL() {} // OHOS_LOCAL void emitCalleeSavedFrameMoves(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI) const; @@ -44,7 +43,7 @@ public: void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override; void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override; - const StackProtectorRetLowering *getStackProtectorRet() const override; + const StackProtectorRetLowering *getStackProtectorRet() const override; // OHOS_LOCAL bool canUseAsPrologue(const MachineBasicBlock &MBB) const override; diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td index 4976f51b82e1..312999eda793 100644 --- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td +++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td @@ -853,6 +853,7 @@ def ADDlowTLS } // isReMaterializable, isCodeGenOnly +// OHOS_LOCAL begin //===----------------------------------------------------------------------===// // Pseudo instruction used by stack protector ret for backward cfi let isCodeGenOnly = 1, hasNoSchedulingInfo = 1 in { @@ -860,6 +861,7 @@ let isCodeGenOnly = 1, hasNoSchedulingInfo = 1 in { def SSP_RET_TRAP: Pseudo<(outs), (ins GPR64:$reg), []>; } } +// OHOS_LOCAL end def : Pat<(AArch64LOADgot tglobaltlsaddr:$addr), (LOADgot tglobaltlsaddr:$addr)>; diff --git a/llvm/lib/Target/AArch64/AArch64StackProtectorRetLowering.cpp b/llvm/lib/Target/AArch64/AArch64StackProtectorRetLowering.cpp index c5f67968a212..06e6ed56aec0 100644 --- a/llvm/lib/Target/AArch64/AArch64StackProtectorRetLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64StackProtectorRetLowering.cpp @@ -5,7 +5,13 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// +// +// This file contains a stack-protector-ret function to insert code to mitigate +// against ROP attacks. +// +//===----------------------------------------------------------------------===// +/// OHOS_LOCAL begin #include "AArch64InstrInfo.h" #include "AArch64MachineFunctionInfo.h" #include "AArch64RegisterInfo.h" @@ -37,7 +43,10 @@ void AArch64StackProtectorRetLowering::insertStackProtectorRetPrologue( BuildMI(MBB, MI, MBBDL, TII->get(AArch64::LDRXui), REG) .addReg(REG) .addGlobalAddress(cookie, 0, AArch64II::MO_PAGEOFF | AArch64II::MO_NC); - BuildMI(MBB, MI, MBBDL, TII->get(AArch64::ANDXrr), REG) + BuildMI(MBB, MI, MBBDL, TII->get(AArch64::EORXrr), REG) + .addReg(REG) + .addReg(AArch64::FP); + BuildMI(MBB, MI, MBBDL, TII->get(AArch64::EORXrr), REG) .addReg(REG) .addReg(AArch64::LR); } @@ -56,7 +65,10 @@ void AArch64StackProtectorRetLowering::insertStackProtectorRetEpilogue( BuildMI(MBB, MI, MBBDL, TII->get(AArch64::LDRXui), AArch64::X9) .addReg(AArch64::X9) .addGlobalAddress(cookie, 0, AArch64II::MO_PAGEOFF | AArch64II::MO_NC); - BuildMI(MBB, MI, MBBDL, TII->get(AArch64::ANDXrr), AArch64::X9) + BuildMI(MBB, MI, MBBDL, TII->get(AArch64::EORXrr), AArch64::X9) + .addReg(AArch64::X9) + .addReg(AArch64::FP); + BuildMI(MBB, MI, MBBDL, TII->get(AArch64::EORXrr), AArch64::X9) .addReg(AArch64::X9) .addReg(AArch64::LR); BuildMI(MBB, MI, MBBDL, TII->get(AArch64::SUBSXrr), REG) @@ -97,3 +109,4 @@ void AArch64StackProtectorRetLowering::saveStackProtectorRetRegister( CSI.insert(CSI.begin(), CalleeSavedInfo(Reg)); } +/// OHOS_LOCAL end diff --git a/llvm/lib/Target/AArch64/AArch64StackProtectorRetLowering.h b/llvm/lib/Target/AArch64/AArch64StackProtectorRetLowering.h index 835b4b90fd2a..29a22a3d2f0b 100644 --- a/llvm/lib/Target/AArch64/AArch64StackProtectorRetLowering.h +++ b/llvm/lib/Target/AArch64/AArch64StackProtectorRetLowering.h @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +/// OHOS_LOCAL begin #ifndef LLVM_LIB_TARGET_AARCH64_AARCH64STACKPROTECTORRETLOWERING_H #define LLVM_LIB_TARGET_AARCH64_AARCH64STACKPROTECTORRETLOWERING_H @@ -37,3 +38,4 @@ public: } // namespace llvm #endif +/// OHOS_LOCAL end diff --git a/llvm/lib/Target/AArch64/CMakeLists.txt b/llvm/lib/Target/AArch64/CMakeLists.txt index e7aba115d6a6..1104955f16be 100644 --- a/llvm/lib/Target/AArch64/CMakeLists.txt +++ b/llvm/lib/Target/AArch64/CMakeLists.txt @@ -75,7 +75,7 @@ add_llvm_target(AArch64CodeGen AArch64SLSHardening.cpp AArch64SelectionDAGInfo.cpp AArch64SpeculationHardening.cpp - AArch64StackProtectorRetLowering.cpp + AArch64StackProtectorRetLowering.cpp # OHOS_LOCAL AArch64StackTagging.cpp AArch64StackTaggingPreRA.cpp AArch64StorePairSuppress.cpp diff --git a/llvm/lib/Transforms/Utils/CodeExtractor.cpp b/llvm/lib/Transforms/Utils/CodeExtractor.cpp index 47366f0f2f2f..10134e26671f 100644 --- a/llvm/lib/Transforms/Utils/CodeExtractor.cpp +++ b/llvm/lib/Transforms/Utils/CodeExtractor.cpp @@ -955,7 +955,10 @@ Function *CodeExtractor::constructFunction(const ValueSet &inputs, case Attribute::SanitizeMemTag: case Attribute::SpeculativeLoadHardening: case Attribute::StackProtect: - case Attribute::StackProtectRet: + // OHOS_LOCAL begin + case Attribute::StackProtectRetReq: + case Attribute::StackProtectRetStrong: + // OHOS_LOCAL end case Attribute::StackProtectReq: case Attribute::StackProtectStrong: case Attribute::StrictFP: diff --git a/llvm/test/Bitcode/attributes.ll b/llvm/test/Bitcode/attributes.ll index 78b54a5cf5c3..2b8883f6c82e 100644 --- a/llvm/test/Bitcode/attributes.ll +++ b/llvm/test/Bitcode/attributes.ll @@ -535,6 +535,20 @@ define void @f86() nosanitize_bounds ; CHECK: define void @f87() [[FNRETTHUNKEXTERN:#[0-9]+]] define void @f87() fn_ret_thunk_extern { ret void } +; OHOS_LOCAL begin +define void @f88() sspretreq +; CHECK: define void @f88() #54 +{ + ret void; +} + +define void @f89() sspretstrong +; CHECK: define void @f89() #55 +{ + ret void; +} +; OHOS_LOCAL end + ; CHECK: attributes #0 = { noreturn } ; CHECK: attributes #1 = { nounwind } ; CHECK: attributes #2 = { readnone } @@ -589,4 +603,8 @@ define void @f87() fn_ret_thunk_extern { ret void } ; CHECK: attributes #51 = { uwtable(sync) } ; CHECK: attributes #52 = { nosanitize_bounds } ; CHECK: attributes [[FNRETTHUNKEXTERN]] = { fn_ret_thunk_extern } +; OHOS_LOCAL begin +; CHECK: attributes #54 = { sspretreq } +; CHECK: attributes #55 = { sspretstrong } +; OHOS_LOCAL end ; CHECK: attributes #[[NOBUILTIN]] = { nobuiltin } diff --git a/llvm/test/CodeGen/AArch64/stack-protector-ret-target.ll b/llvm/test/CodeGen/AArch64/stack-protector-ret-target.ll new file mode 100644 index 000000000000..9dec7a195943 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/stack-protector-ret-target.ll @@ -0,0 +1,31 @@ +; OHOS_LOCAL +; Test target-specific stack cookie location. +; RUN: llc -mtriple=aarch64-linux-ohos < %s -o - | FileCheck --check-prefix=OHOS-AARCH64 %s + +define void @_Z1fv() sspretreq { +entry: + %x = alloca i32, align 4 + %0 = bitcast i32* %x to i8* + call void @_Z7CapturePi(i32* nonnull %x) + ret void +} + +declare void @_Z7CapturePi(i32*) + +; OHOS-AARCH64: adrp x15, __sspret_cookie_ +; OHOS-AARCH64: ldr x15, [x15, :lo12:__sspret_cookie_ +; OHOS-AARCH64: eor x15, x15, x29 +; OHOS-AARCH64: eor x15, x15, x30 +; OHOS-AARCH64: sub sp, sp, +; OHOS-AARCH64: stp x30, x15, [sp, +; OHOS-AARCH64: ] +; OHOS-AARCH64: ldp x30, x15, [sp, +; OHOS-AARCH64: add sp, +; OHOS-AARCH64: adrp x9, __sspret_cookie_ +; OHOS-AARCH64: ldr x9, [x9, :lo12:__sspret_cookie_ +; OHOS-AARCH64: eor x9, x9, x29 +; OHOS-AARCH64: eor x9, x9, x30 +; OHOS-AARCH64: subs x15, x15, x9 +; OHOS-AARCH64: cbz x15, +; OHOS-AARCH64: brk #0x1 +; OHOS-AARCH64: ret diff --git a/llvm/test/Transforms/Inline/inline_sspret.ll b/llvm/test/Transforms/Inline/inline_sspret.ll new file mode 100644 index 000000000000..3f7d4bea0d45 --- /dev/null +++ b/llvm/test/Transforms/Inline/inline_sspret.ll @@ -0,0 +1,176 @@ +; OHOS_LOCAL +; RUN: opt -inline %s -S | FileCheck %s +; RUN: opt -passes='cgscc(inline)' %s -S | FileCheck %s +; Ensure SSPRET attributes are propagated correctly when inlining. + +@.str = private unnamed_addr constant [11 x i8] c"fun_nossp\0A\00", align 1 +@.str1 = private unnamed_addr constant [9 x i8] c"fun_ssp\0A\00", align 1 +@.str2 = private unnamed_addr constant [18 x i8] c"fun_sspretstrong\0A\00", align 1 +@.str3 = private unnamed_addr constant [15 x i8] c"fun_sspretreq\0A\00", align 1 + +; These first four functions (@fun_sspretreq, @fun_sspretstrong, @fun_ssp, @fun_nossp) +; are used by the remaining functions to ensure that the SSP attributes are +; propagated correctly. If the caller had an SSP attribute before inlining, it +; should have its new SSP attribute set as: +; strictest(caller-ssp-attr, callee-ssp-attr), where strictness is ordered as: +; sspretreq > sspretstrong > ssp + +define internal void @fun_sspretreq() sspretreq { +entry: + %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.str3, i32 0, i32 0)) + ret void +} + +define internal void @fun_sspretreq_alwaysinline() sspretreq alwaysinline { +entry: + %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.str3, i32 0, i32 0)) + ret void +} + +define internal void @fun_sspretstrong() sspretstrong { +entry: + %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([18 x i8], [18 x i8]* @.str2, i32 0, i32 0)) + ret void +} + +define internal void @fun_ssp() ssp { +entry: + %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str1, i32 0, i32 0)) + ret void +} + +define internal void @fun_nossp() { +entry: + %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str, i32 0, i32 0)) + ret void +} + +; Tests start below. + +define void @inline_retreq_retreq() sspretreq { +entry: +; CHECK: @inline_retreq_retreq() #[[SSPRETREQ:[0-9]]] + call void @fun_sspretreq() + ret void +} + +define void @inline_retreq_retstrong() sspretstrong { +entry: +; CHECK: @inline_retreq_retstrong() #[[SSPRETREQ]] + call void @fun_sspretreq() + ret void +} + +define void @inline_retreq_ssp() ssp { +entry: +; CHECK: @inline_retreq_ssp() #[[SSPRETREQ]] + call void @fun_sspretreq() + ret void +} + +define void @inline_retreq_nossp() { +entry: +; CHECK: @inline_retreq_nossp() { + call void @fun_sspretreq() + ret void +} + +define void @alwaysinline_retreq_nossp() { +entry: +; CHECK: @alwaysinline_retreq_nossp() { + call void @fun_sspretreq_alwaysinline() + ret void +} + +define void @inline_retstrong_retreq() sspretreq { +entry: +; CHECK: @inline_retstrong_retreq() #[[SSPRETREQ]] + call void @fun_sspretstrong() + ret void +} + + +define void @inline_retstrong_retstrong() sspretstrong { +entry: +; CHECK: @inline_retstrong_retstrong() #[[SSPRETSTRONG:[0-9]]] + call void @fun_sspretstrong() + ret void +} + +define void @inline_retstrong_ssp() ssp { +entry: +; CHECK: @inline_retstrong_ssp() #[[SSPRETSTRONG]] + call void @fun_sspretstrong() + ret void +} + +define void @inline_retstrong_nossp() { +entry: +; CHECK: @inline_retstrong_nossp() { + call void @fun_sspretstrong() + ret void +} + +define void @inline_ssp_retreq() sspretreq { +entry: +; CHECK: @inline_ssp_retreq() #[[SSPRETREQ]] + call void @fun_ssp() + ret void +} + + +define void @inline_ssp_retstrong() sspretstrong { +entry: +; CHECK: @inline_ssp_retstrong() #[[SSPRETSTRONG]] + call void @fun_ssp() + ret void +} + +define void @inline_ssp_ssp() ssp { +entry: +; CHECK: @inline_ssp_ssp() #[[SSP:[0-9]]] + call void @fun_ssp() + ret void +} + +define void @inline_ssp_nossp() { +entry: +; CHECK: @inline_ssp_nossp() { + call void @fun_ssp() + ret void +} + +define void @inline_nossp_retreq() sspretreq { +entry: +; CHECK: @inline_nossp_retreq() #[[SSPRETREQ]] + call void @fun_nossp() + ret void +} + + +define void @inline_nossp_retstrong() sspretstrong { +entry: +; CHECK: @inline_nossp_retstrong() #[[SSPRETSTRONG]] + call void @fun_nossp() + ret void +} + +define void @inline_nossp_ssp() ssp { +entry: +; CHECK: @inline_nossp_ssp() #[[SSP]] + call void @fun_nossp() + ret void +} + +define void @inline_nossp_nossp() { +entry: +; CHECK: @inline_nossp_nossp() { + call void @fun_nossp() + ret void +} + +declare i32 @printf(i8*, ...) + +; CHECK: attributes #[[SSPRETREQ]] = { sspretreq } +; CHECK: attributes #[[SSPRETSTRONG]] = { sspretstrong } +; CHECK: attributes #[[SSP]] = { ssp } diff --git a/llvm/test/tools/llvm-objdump/ohos-headers.test b/llvm/test/tools/llvm-objdump/ohos-headers.test index 045f54fac359..b9e7e8c225d6 100644 --- a/llvm/test/tools/llvm-objdump/ohos-headers.test +++ b/llvm/test/tools/llvm-objdump/ohos-headers.test @@ -1,3 +1,4 @@ +## OHOS_LOCAL ## Check that llvm-objdump dumps OHOS program headers correctly. # RUN: yaml2obj %s -o %t diff --git a/llvm/tools/llvm-objdump/ELFDump.cpp b/llvm/tools/llvm-objdump/ELFDump.cpp index dcc851ad1650..68c635abf99c 100644 --- a/llvm/tools/llvm-objdump/ELFDump.cpp +++ b/llvm/tools/llvm-objdump/ELFDump.cpp @@ -256,9 +256,11 @@ static void printProgramHeaders(const ELFFile &Obj, StringRef FileName) { case ELF::PT_OPENBSD_WXNEEDED: outs() << " OPENBSD_WXNEEDED "; break; + // OHOS_LOCAL begin case ELF::PT_OHOS_RANDOMDATA: outs() << " OHOS_RANDOMDATA "; break; + // OHOS_LOCAL end case ELF::PT_PHDR: outs() << " PHDR "; break; diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp index 37810feabc11..c9a239f785d2 100644 --- a/llvm/tools/llvm-readobj/ELFDumper.cpp +++ b/llvm/tools/llvm-readobj/ELFDumper.cpp @@ -1415,7 +1415,7 @@ static StringRef segmentTypeToString(unsigned Arch, unsigned Type) { LLVM_READOBJ_ENUM_CASE(ELF, PT_OPENBSD_WXNEEDED); LLVM_READOBJ_ENUM_CASE(ELF, PT_OPENBSD_BOOTDATA); - LLVM_READOBJ_ENUM_CASE(ELF, PT_OHOS_RANDOMDATA); + LLVM_READOBJ_ENUM_CASE(ELF, PT_OHOS_RANDOMDATA); // OHOS_LOCAL default: return ""; } -- Gitee