diff --git a/bolt/include/bolt/Passes/PAuthGadgetScanner.h b/bolt/include/bolt/Passes/PAuthGadgetScanner.h index cb865a725d72..1a8c74272391 100644 --- a/bolt/include/bolt/Passes/PAuthGadgetScanner.h +++ b/bolt/include/bolt/Passes/PAuthGadgetScanner.h @@ -13,6 +13,7 @@ #include "bolt/Core/BinaryFunction.h" #include "bolt/Core/MCInstUtils.h" #include "bolt/Passes/BinaryPasses.h" +#include "bolt/Utils/CommandLineOpts.h" #include "llvm/Support/raw_ostream.h" #include @@ -161,7 +162,8 @@ class FunctionAnalysisContext { MCPlusBuilder::AllocatorIdTy AllocatorId; FunctionAnalysisResult Result; - bool PacRetGadgetsOnly; + /// Bitmask of detectors to run (only GS_PTRAUTH_* are allowed). + opts::GadgetKindBitmask EnabledDetectors; void findUnsafeUses(SmallVector> &Reports); void augmentUnsafeUseReports(ArrayRef> Reports); @@ -176,9 +178,7 @@ class FunctionAnalysisContext { public: FunctionAnalysisContext(BinaryFunction &BF, MCPlusBuilder::AllocatorIdTy AllocatorId, - bool PacRetGadgetsOnly) - : BC(BF.getBinaryContext()), BF(BF), AllocatorId(AllocatorId), - PacRetGadgetsOnly(PacRetGadgetsOnly) {} + opts::GadgetKindBitmask EnabledDetectors); void run(); @@ -186,8 +186,8 @@ public: }; class Analysis : public BinaryFunctionPass { - /// Only search for pac-ret violations. - bool PacRetGadgetsOnly; + /// Bitmask of detectors to run (only GS_PTRAUTH_* are allowed). + opts::GadgetKindBitmask EnabledDetectors; void runOnFunction(BinaryFunction &Function, MCPlusBuilder::AllocatorIdTy AllocatorId); @@ -196,8 +196,7 @@ class Analysis : public BinaryFunctionPass { std::mutex AnalysisResultsMutex; public: - explicit Analysis(bool PacRetGadgetsOnly) - : BinaryFunctionPass(false), PacRetGadgetsOnly(PacRetGadgetsOnly) {} + explicit Analysis(opts::GadgetKindBitmask EnabledDetectors); const char *getName() const override { return "pauth-gadget-scanner"; } diff --git a/bolt/include/bolt/Utils/CommandLineOpts.h b/bolt/include/bolt/Utils/CommandLineOpts.h index 5c7f1b94315f..fcea952919f1 100644 --- a/bolt/include/bolt/Utils/CommandLineOpts.h +++ b/bolt/include/bolt/Utils/CommandLineOpts.h @@ -130,9 +130,27 @@ bool processAllFunctions(); /// Return true if we should dump dot graphs for the given function. bool shouldDumpDot(const llvm::bolt::BinaryFunction &Function); -enum GadgetScannerKind { GS_PACRET, GS_PAUTH, GS_ALL }; +/// Bitmask representing a subset of possible gadget kinds. +enum GadgetKindBitmask : unsigned { + /// Scan for unprotected backward control-flow (return instructions). + GS_PTRAUTH_RETURN_TARGETS = (1 << 0), + /// Scan for tail calls performed with untrusted link register. + GS_PTRAUTH_TAIL_CALLS = (1 << 1), + /// Scan for unprotected forward control-flow (branch and call instructions). + GS_PTRAUTH_BRANCH_AND_CALL_TARGETS = (1 << 2), + /// Scan for signing oracles. + GS_PTRAUTH_SIGN_ORACLES = (1 << 3), + /// Scan for authentication oracles. + GS_PTRAUTH_AUTH_ORACLES = (1 << 4), -extern llvm::cl::bits GadgetScannersToRun; + /// Scan for all Pointer Authentication issues. + GS_PTRAUTH_ALL_MASK = GS_PTRAUTH_RETURN_TARGETS | GS_PTRAUTH_TAIL_CALLS | + GS_PTRAUTH_BRANCH_AND_CALL_TARGETS | + GS_PTRAUTH_SIGN_ORACLES | GS_PTRAUTH_AUTH_ORACLES, + + /// Run all implemented scanners. + GS_ALL_MASK = GS_PTRAUTH_ALL_MASK, +}; } // namespace opts diff --git a/bolt/lib/Passes/PAuthGadgetScanner.cpp b/bolt/lib/Passes/PAuthGadgetScanner.cpp index 22ceeabe36c6..542af49e2620 100644 --- a/bolt/lib/Passes/PAuthGadgetScanner.cpp +++ b/bolt/lib/Passes/PAuthGadgetScanner.cpp @@ -1553,6 +1553,11 @@ collectRegsToTrack(ArrayRef> Reports) { void FunctionAnalysisContext::findUnsafeUses( SmallVector> &Reports) { + const auto HandledDetectors = + opts::GS_PTRAUTH_ALL_MASK & ~opts::GS_PTRAUTH_AUTH_ORACLES; + if (!(EnabledDetectors & HandledDetectors)) + return; + auto Analysis = SrcSafetyAnalysis::create(BF, AllocatorId, {}); LLVM_DEBUG(dbgs() << "Running src register safety analysis...\n"); Analysis->run(); @@ -1617,19 +1622,22 @@ void FunctionAnalysisContext::findUnsafeUses( return; } - if (auto Report = shouldReportReturnGadget(BC, Inst, S)) - Reports.push_back(*Report); - - if (PacRetGadgetsOnly) - return; - - if (auto Report = shouldReportUnsafeTailCall(BC, BF, Inst, S)) - Reports.push_back(*Report); - - if (auto Report = shouldReportCallGadget(BC, Inst, S)) - Reports.push_back(*Report); - if (auto Report = shouldReportSigningOracle(BC, Inst, S)) - Reports.push_back(*Report); + if (EnabledDetectors & opts::GS_PTRAUTH_RETURN_TARGETS) { + if (auto Report = shouldReportReturnGadget(BC, Inst, S)) + Reports.push_back(*Report); + } + if (EnabledDetectors & opts::GS_PTRAUTH_TAIL_CALLS) { + if (auto Report = shouldReportUnsafeTailCall(BC, BF, Inst, S)) + Reports.push_back(*Report); + } + if (EnabledDetectors & opts::GS_PTRAUTH_BRANCH_AND_CALL_TARGETS) { + if (auto Report = shouldReportCallGadget(BC, Inst, S)) + Reports.push_back(*Report); + } + if (EnabledDetectors & opts::GS_PTRAUTH_SIGN_ORACLES) { + if (auto Report = shouldReportSigningOracle(BC, Inst, S)) + Reports.push_back(*Report); + } }); } @@ -1660,8 +1668,10 @@ void FunctionAnalysisContext::augmentUnsafeUseReports( void FunctionAnalysisContext::findUnsafeDefs( SmallVector> &Reports) { - if (PacRetGadgetsOnly) + const auto HandledDetectors = opts::GS_PTRAUTH_AUTH_ORACLES; + if (!(EnabledDetectors & HandledDetectors)) return; + if (AuthTrapsOnFailure) return; @@ -1719,6 +1729,15 @@ void FunctionAnalysisContext::handleSimpleReports( llvm::erase_if(Reports, [](const auto &R) { return !R.RequestedDetails; }); } +FunctionAnalysisContext::FunctionAnalysisContext( + BinaryFunction &BF, MCPlusBuilder::AllocatorIdTy AllocatorId, + opts::GadgetKindBitmask EnabledDetectors) + : BC(BF.getBinaryContext()), BF(BF), AllocatorId(AllocatorId), + EnabledDetectors(EnabledDetectors) { + assert(!(EnabledDetectors & ~opts::GS_PTRAUTH_ALL_MASK) && + "Unrelated detectors requested"); +} + void FunctionAnalysisContext::run() { LLVM_DEBUG({ dbgs() << "Analyzing function " << BF.getPrintName() @@ -1741,7 +1760,7 @@ void FunctionAnalysisContext::run() { void Analysis::runOnFunction(BinaryFunction &BF, MCPlusBuilder::AllocatorIdTy AllocatorId) { - FunctionAnalysisContext FA(BF, AllocatorId, PacRetGadgetsOnly); + FunctionAnalysisContext FA(BF, AllocatorId, EnabledDetectors); FA.run(); const FunctionAnalysisResult &FAR = FA.getResult(); @@ -1849,6 +1868,12 @@ void GenericDiagnostic::generateReport(raw_ostream &OS, printBasicInfo(OS, BC, Text); } +Analysis::Analysis(opts::GadgetKindBitmask EnabledDetectors) + : BinaryFunctionPass(false), EnabledDetectors(EnabledDetectors) { + assert(!(EnabledDetectors & ~opts::GS_PTRAUTH_ALL_MASK) && + "Unrelated detectors requested"); +} + Error Analysis::runOnFunctions(BinaryContext &BC) { ParallelUtilities::WorkFuncWithAllocTy WorkFun = [&](BinaryFunction &BF, MCPlusBuilder::AllocatorIdTy AllocatorId) { diff --git a/bolt/lib/Rewrite/RewriteInstance.cpp b/bolt/lib/Rewrite/RewriteInstance.cpp index cd99b04057a1..b3208ac024ae 100644 --- a/bolt/lib/Rewrite/RewriteInstance.cpp +++ b/bolt/lib/Rewrite/RewriteInstance.cpp @@ -286,13 +286,23 @@ static cl::opt WriteBoltInfoSection( "bolt-info", cl::desc("write bolt info section in the output binary"), cl::init(true), cl::Hidden, cl::cat(BoltOutputCategory)); -cl::bits GadgetScannersToRun( - "scanners", cl::desc("which gadget scanners to run"), +static cl::list GadgetScannersToRun( + "scanners", cl::desc("Which gadget scanners to run"), cl::values( - clEnumValN(GS_PACRET, "pacret", - "pac-ret: return address protection (subset of \"pauth\")"), - clEnumValN(GS_PAUTH, "pauth", "All Pointer Authentication scanners"), - clEnumValN(GS_ALL, "all", "All implemented scanners")), + clEnumValN(GS_PTRAUTH_RETURN_TARGETS, "ptrauth-pac-ret", + "Unprotected returns (pac-ret)"), + clEnumValN(GS_PTRAUTH_TAIL_CALLS, "ptrauth-tail-calls", + "Tail calls performed with unprotected link register"), + clEnumValN(GS_PTRAUTH_BRANCH_AND_CALL_TARGETS, "ptrauth-forward-cf", + "Unprotected calls and branches (forward control-flow)"), + clEnumValN(GS_PTRAUTH_SIGN_ORACLES, "ptrauth-sign-oracles", + "Signing of untrusted pointers (signing oracles)"), + clEnumValN(GS_PTRAUTH_AUTH_ORACLES, "ptrauth-auth-oracles", + "Authentication oracles"), + + clEnumValN(GS_PTRAUTH_ALL_MASK, "ptrauth-all", + "All Pointer Authentication scanners"), + clEnumValN(GS_ALL_MASK, "all", "All implemented scanners")), cl::ZeroOrMore, cl::CommaSeparated, cl::cat(BinaryAnalysisCategory)); // Primary targets for hooking runtime library initialization hooking @@ -3868,20 +3878,21 @@ void RewriteInstance::runBinaryAnalyses() { BinaryFunctionPassManager Manager(*BC); // FIXME: add a pass that warns about which functions do not have CFG, // and therefore, analysis is most likely to be less accurate. - using GSK = opts::GadgetScannerKind; - using PAuthScanner = PAuthGadgetScanner::Analysis; + using PtrAuthScanner = PAuthGadgetScanner::Analysis; + + // Accumulate all enabled analyses. + decltype(~opts::GS_ALL_MASK) EnabledAnalyses = 0; + for (auto NamedOptionSubmask : opts::GadgetScannersToRun) + EnabledAnalyses |= NamedOptionSubmask; // If no command line option was given, act as if "all" was specified. - bool RunAll = !opts::GadgetScannersToRun.getBits() || - opts::GadgetScannersToRun.isSet(GSK::GS_ALL); + if (opts::GadgetScannersToRun.empty()) + EnabledAnalyses = opts::GS_ALL_MASK; - if (RunAll || opts::GadgetScannersToRun.isSet(GSK::GS_PAUTH)) { - Manager.registerPass( - std::make_unique(/*OnlyPacRetChecks=*/false)); - } else if (RunAll || opts::GadgetScannersToRun.isSet(GSK::GS_PACRET)) { - Manager.registerPass( - std::make_unique(/*OnlyPacRetChecks=*/true)); - } + const auto PtrAuthAnalyses = static_cast( + EnabledAnalyses & opts::GS_PTRAUTH_ALL_MASK); + if (PtrAuthAnalyses) + Manager.registerPass(std::make_unique(PtrAuthAnalyses)); BC->logBOLTErrorsAndQuitOnFatal(Manager.runPasses()); } diff --git a/bolt/test/binary-analysis/AArch64/cmdline-args.test b/bolt/test/binary-analysis/AArch64/cmdline-args.test index 9660ad3bf80f..3221078951ab 100644 --- a/bolt/test/binary-analysis/AArch64/cmdline-args.test +++ b/bolt/test/binary-analysis/AArch64/cmdline-args.test @@ -34,9 +34,14 @@ HELP-EMPTY: HELP-NEXT: BinaryAnalysis options: HELP-EMPTY: HELP-NEXT: --auth-traps-on-failure - Assume authentication instructions always trap on failure -HELP-NEXT: --scanners= - which gadget scanners to run -HELP-NEXT: =pacret - pac-ret: return address protection (subset of "pauth") -HELP-NEXT: =pauth - All Pointer Authentication scanners -HELP-NEXT: =all - All implemented scanners +HELP-NEXT: --scanners= - Which gadget scanners to run +HELP-NEXT: =ptrauth-pac-ret - Unprotected returns (pac-ret) +HELP-NEXT: =ptrauth-tail-calls - Tail calls performed with unprotected link register +HELP-NEXT: =ptrauth-forward-cf - Unprotected calls and branches (forward control-flow) +HELP-NEXT: =ptrauth-sign-oracles - Signing of untrusted pointers (signing oracles) +HELP-NEXT: =ptrauth-auth-oracles - Authentication oracles +HELP-NEXT: =ptrauth-all - All Pointer Authentication scanners +HELP-NEXT: =all - All implemented scanners + HELP-EMPTY: HELP-NEXT: Generic Options: diff --git a/bolt/test/binary-analysis/AArch64/gs-pacret-autiasp.s b/bolt/test/binary-analysis/AArch64/gs-pacret-autiasp.s index 8e991fade2c8..c0aa91ce2193 100644 --- a/bolt/test/binary-analysis/AArch64/gs-pacret-autiasp.s +++ b/bolt/test/binary-analysis/AArch64/gs-pacret-autiasp.s @@ -1,5 +1,5 @@ // RUN: %clang %cflags -march=armv9.5-a+pauth-lr -mbranch-protection=pac-ret %s %p/../../Inputs/asm_main.c -o %t.exe -// RUN: llvm-bolt-binary-analysis --scanners=pacret %t.exe 2>&1 | FileCheck %s +// RUN: llvm-bolt-binary-analysis --scanners=ptrauth-pac-ret %t.exe 2>&1 | FileCheck %s .text diff --git a/bolt/test/binary-analysis/AArch64/gs-pacret-multi-bb.s b/bolt/test/binary-analysis/AArch64/gs-pacret-multi-bb.s index bd8edbc676c3..89fdf9f20a74 100644 --- a/bolt/test/binary-analysis/AArch64/gs-pacret-multi-bb.s +++ b/bolt/test/binary-analysis/AArch64/gs-pacret-multi-bb.s @@ -1,5 +1,5 @@ // RUN: %clang %cflags -march=armv8.3-a -mbranch-protection=pac-ret %s %p/../../Inputs/asm_main.c -o %t.exe -// RUN: llvm-bolt-binary-analysis --scanners=pacret %t.exe 2>&1 | FileCheck %s +// RUN: llvm-bolt-binary-analysis --scanners=ptrauth-pac-ret %t.exe 2>&1 | FileCheck %s // Verify that we can also detect gadgets across basic blocks diff --git a/bolt/test/binary-analysis/AArch64/gs-pauth-address-checks.s b/bolt/test/binary-analysis/AArch64/gs-pauth-address-checks.s index 74f276197923..84063960a31f 100644 --- a/bolt/test/binary-analysis/AArch64/gs-pauth-address-checks.s +++ b/bolt/test/binary-analysis/AArch64/gs-pauth-address-checks.s @@ -1,5 +1,5 @@ // RUN: %clang %cflags -march=armv8.3-a %s -o %t.exe -Wl,--emit-relocs -// RUN: llvm-bolt-binary-analysis --scanners=pauth %t.exe 2>&1 | FileCheck %s +// RUN: llvm-bolt-binary-analysis --scanners=ptrauth-all %t.exe 2>&1 | FileCheck %s .text diff --git a/bolt/test/binary-analysis/AArch64/gs-pauth-address-materialization.s b/bolt/test/binary-analysis/AArch64/gs-pauth-address-materialization.s index 6648f96ad7d0..1c160f47468d 100644 --- a/bolt/test/binary-analysis/AArch64/gs-pauth-address-materialization.s +++ b/bolt/test/binary-analysis/AArch64/gs-pauth-address-materialization.s @@ -1,6 +1,6 @@ // -Wl,--no-relax prevents converting ADRP+ADD pairs into NOP+ADR. // RUN: %clang %cflags -march=armv8.3-a -Wl,--no-relax %s -o %t.exe -// RUN: llvm-bolt-binary-analysis --scanners=pauth %t.exe 2>&1 | FileCheck %s +// RUN: llvm-bolt-binary-analysis --scanners=ptrauth-all %t.exe 2>&1 | FileCheck %s // Test various patterns that should or should not be considered safe // materialization of PC-relative addresses. diff --git a/bolt/test/binary-analysis/AArch64/gs-pauth-authentication-oracles.s b/bolt/test/binary-analysis/AArch64/gs-pauth-authentication-oracles.s index 9f580b66f47c..69ae9a086b99 100644 --- a/bolt/test/binary-analysis/AArch64/gs-pauth-authentication-oracles.s +++ b/bolt/test/binary-analysis/AArch64/gs-pauth-authentication-oracles.s @@ -1,14 +1,12 @@ // RUN: %clang %cflags -march=armv8.3-a %s -o %t.exe -// RUN: llvm-bolt-binary-analysis --scanners=pacret %t.exe 2>&1 | FileCheck -check-prefix=PACRET %s -// RUN: llvm-bolt-binary-analysis --scanners=pauth --auth-traps-on-failure %t.exe 2>&1 | FileCheck -check-prefix=FPAC %s -// RUN: llvm-bolt-binary-analysis --scanners=pauth %t.exe 2>&1 | FileCheck %s +// RUN: llvm-bolt-binary-analysis --scanners=ptrauth-auth-oracles --auth-traps-on-failure %t.exe 2>&1 | FileCheck -check-prefix=FPAC %s +// RUN: llvm-bolt-binary-analysis --scanners=ptrauth-auth-oracles %t.exe 2>&1 | FileCheck %s // The detection of compiler-generated explicit pointer checks is tested in // gs-pauth-address-checks.s, for that reason only test here "dummy-load" and // "high-bits-notbi" checkers, as the shortest examples of checkers that are // detected per-instruction and per-BB. -// PACRET-NOT: authentication oracle found in function // FPAC-NOT: authentication oracle found in function .text diff --git a/bolt/test/binary-analysis/AArch64/gs-pauth-calls.s b/bolt/test/binary-analysis/AArch64/gs-pauth-calls.s index 5e88e105a33f..c270fcaa26aa 100644 --- a/bolt/test/binary-analysis/AArch64/gs-pauth-calls.s +++ b/bolt/test/binary-analysis/AArch64/gs-pauth-calls.s @@ -1,9 +1,6 @@ // RUN: %clang %cflags -march=armv8.3-a %s -o %t.exe -// RUN: llvm-bolt-binary-analysis --scanners=pacret %t.exe 2>&1 | FileCheck -check-prefix=PACRET %s -// RUN: llvm-bolt-binary-analysis --scanners=pauth --auth-traps-on-failure %t.exe 2>&1 | FileCheck %s -// RUN: llvm-bolt-binary-analysis --scanners=pauth %t.exe 2>&1 | FileCheck %s - -// PACRET-NOT: non-protected call found in function +// RUN: llvm-bolt-binary-analysis --scanners=ptrauth-forward-cf --auth-traps-on-failure %t.exe 2>&1 | FileCheck %s +// RUN: llvm-bolt-binary-analysis --scanners=ptrauth-forward-cf %t.exe 2>&1 | FileCheck %s .text diff --git a/bolt/test/binary-analysis/AArch64/gs-pauth-debug-output.s b/bolt/test/binary-analysis/AArch64/gs-pauth-debug-output.s index a3ad7effe4b0..77ccec73f5fc 100644 --- a/bolt/test/binary-analysis/AArch64/gs-pauth-debug-output.s +++ b/bolt/test/binary-analysis/AArch64/gs-pauth-debug-output.s @@ -1,13 +1,13 @@ // REQUIRES: asserts // // RUN: %clang %cflags -march=armv8.3-a %s -o %t.exe -// RUN: llvm-bolt-binary-analysis --scanners=pacret --no-threads \ +// RUN: llvm-bolt-binary-analysis --scanners=ptrauth-pac-ret --no-threads \ // RUN: -debug-only bolt-pauth-scanner %t.exe 2>&1 | FileCheck -check-prefixes=CHECK,NOFPAC %s -// RUN: llvm-bolt-binary-analysis --scanners=pacret --no-threads --auth-traps-on-failure \ +// RUN: llvm-bolt-binary-analysis --scanners=ptrauth-pac-ret --no-threads --auth-traps-on-failure \ // RUN: -debug-only bolt-pauth-scanner %t.exe 2>&1 | FileCheck -check-prefixes=CHECK,FPAC %s -// RUN: llvm-bolt-binary-analysis --scanners=pauth --no-threads \ +// RUN: llvm-bolt-binary-analysis --scanners=ptrauth-all --no-threads \ // RUN: -debug-only bolt-pauth-scanner %t.exe 2>&1 | FileCheck -check-prefixes=CHECK,NOFPAC,AUTH-ORACLES,PAUTH %s -// RUN: llvm-bolt-binary-analysis --scanners=pauth --no-threads --auth-traps-on-failure \ +// RUN: llvm-bolt-binary-analysis --scanners=ptrauth-all --no-threads --auth-traps-on-failure \ // RUN: -debug-only bolt-pauth-scanner %t.exe 2>&1 | FileCheck -check-prefixes=CHECK,FPAC,PAUTH %s // Check the debug output generated by PAuth gadget scanner to make sure the diff --git a/bolt/test/binary-analysis/AArch64/gs-pauth-scanners.s b/bolt/test/binary-analysis/AArch64/gs-pauth-scanners.s new file mode 100644 index 000000000000..d6c96a671f9d --- /dev/null +++ b/bolt/test/binary-analysis/AArch64/gs-pauth-scanners.s @@ -0,0 +1,130 @@ +// RUN: %clang %cflags -march=armv8.3-a %s -o %t.exe + +// Select single detector: +// +// RUN: llvm-bolt-binary-analysis --scanners=ptrauth-pac-ret %t.exe 2>&1 | \ +// RUN: FileCheck %s --implicit-check-not="found in function" \ +// RUN: --check-prefixes=PACRET +// RUN: llvm-bolt-binary-analysis --scanners=ptrauth-tail-calls %t.exe 2>&1 | \ +// RUN: FileCheck %s --implicit-check-not="found in function" \ +// RUN: --check-prefixes=TAIL-CALLS-COMMON,TAIL-CALLS-NOFPAC +// RUN: llvm-bolt-binary-analysis --scanners=ptrauth-forward-cf %t.exe 2>&1 | \ +// RUN: FileCheck %s --implicit-check-not="found in function" \ +// RUN: --check-prefixes=FORWARD-CF +// RUN: llvm-bolt-binary-analysis --scanners=ptrauth-sign-oracles %t.exe 2>&1 | \ +// RUN: FileCheck %s --implicit-check-not="found in function" \ +// RUN: --check-prefixes=SIGN-ORACLES-COMMON,SIGN-ORACLES-NOFPAC +// RUN: llvm-bolt-binary-analysis --scanners=ptrauth-auth-oracles %t.exe 2>&1 | \ +// RUN: FileCheck %s --implicit-check-not="found in function" \ +// RUN: --check-prefixes=AUTH-ORACLES-NOFPAC + +// Select multiple options (either disjoint or not): +// +// RUN: llvm-bolt-binary-analysis --scanners=ptrauth-pac-ret,ptrauth-forward-cf %t.exe 2>&1 | \ +// RUN: FileCheck %s --implicit-check-not="found in function" \ +// RUN: --check-prefixes=PACRET,FORWARD-CF +// RUN: llvm-bolt-binary-analysis --scanners=ptrauth-pac-ret,ptrauth-all %t.exe 2>&1 | \ +// RUN: FileCheck %s --implicit-check-not="found in function" \ +// RUN: --check-prefixes=PACRET,TAIL-CALLS-COMMON,TAIL-CALLS-NOFPAC,FORWARD-CF,SIGN-ORACLES-COMMON,SIGN-ORACLES-NOFPAC,AUTH-ORACLES-NOFPAC + +// Select one of "all" options: +// +// RUN: llvm-bolt-binary-analysis --scanners=ptrauth-all %t.exe 2>&1 | \ +// RUN: FileCheck %s --implicit-check-not="found in function" \ +// RUN: --check-prefixes=PACRET,TAIL-CALLS-COMMON,TAIL-CALLS-NOFPAC,FORWARD-CF,SIGN-ORACLES-COMMON,SIGN-ORACLES-NOFPAC,AUTH-ORACLES-NOFPAC +// RUN: llvm-bolt-binary-analysis --scanners=all %t.exe 2>&1 | \ +// RUN: FileCheck %s --implicit-check-not="found in function" \ +// RUN: --check-prefixes=PACRET,TAIL-CALLS-COMMON,TAIL-CALLS-NOFPAC,FORWARD-CF,SIGN-ORACLES-COMMON,SIGN-ORACLES-NOFPAC,AUTH-ORACLES-NOFPAC + +// Implicitly select all scanners by omitting --scanners=... argument. +// +// RUN: llvm-bolt-binary-analysis %t.exe 2>&1 | \ +// RUN: FileCheck %s --implicit-check-not="found in function" \ +// RUN: --check-prefixes=PACRET,TAIL-CALLS-COMMON,TAIL-CALLS-NOFPAC,FORWARD-CF,SIGN-ORACLES-COMMON,SIGN-ORACLES-NOFPAC,AUTH-ORACLES-NOFPAC + +// Test FPAC handling: +// +// RUN: llvm-bolt-binary-analysis --auth-traps-on-failure --scanners=ptrauth-all %t.exe 2>&1 | \ +// RUN: FileCheck %s --implicit-check-not="found in function" \ +// RUN: --check-prefixes=PACRET,TAIL-CALLS-COMMON,FORWARD-CF,SIGN-ORACLES-COMMON +// RUN: llvm-bolt-binary-analysis --auth-traps-on-failure --scanners=ptrauth-auth-oracles %t.exe 2>&1 | \ +// RUN: FileCheck %s --check-prefixes=NO-REPORTS + +// NO-REPORTS-NOT: found in function + + .text + + .globl callee + .type callee,@function +callee: + ret + .size callee, .-callee + + .globl bad_pacret + .type bad_pacret,@function +bad_pacret: +// PACRET: GS-PAUTH: non-protected ret found in function bad_pacret + stp x29, x30, [sp, #-16]! + mov x29, sp + + ldp x29, x30, [sp], #16 + ret + .size bad_pacret, .-bad_pacret + + .globl bad_tail_call_common + .type bad_tail_call_common,@function +bad_tail_call_common: +// TAIL-CALLS-COMMON: GS-PAUTH: untrusted link register found before tail call in function bad_tail_call_common + stp x29, x30, [sp, #-16]! + mov x29, sp + + ldp x29, x30, [sp], #16 + b callee + .size bad_tail_call_common, .-bad_tail_call_common + + .globl bad_tail_call_nofpac + .type bad_tail_call_nofpac,@function +bad_tail_call_nofpac: +// TAIL-CALLS-NOFPAC: GS-PAUTH: untrusted link register found before tail call in function bad_tail_call_nofpac +// AUTH-ORACLES-NOFPAC: GS-PAUTH: authentication oracle found in function bad_tail_call_nofpac + paciasp + stp x29, x30, [sp, #-16]! + mov x29, sp + + ldp x29, x30, [sp], #16 + autiasp + b callee + .size bad_tail_call_nofpac, .-bad_tail_call_nofpac + + .globl bad_call + .type bad_call,@function +bad_call: +// FORWARD-CF: GS-PAUTH: non-protected call found in function bad_call + br x0 + .size bad_call, .-bad_call + + .globl bad_signing_oracle_common + .type bad_signing_oracle_common,@function +bad_signing_oracle_common: +// SIGN-ORACLES-COMMON: GS-PAUTH: signing oracle found in function bad_signing_oracle_common + pacda x0, x1 + ret + .size bad_signing_oracle_common, .-bad_signing_oracle_common + + .globl bad_signing_oracle_nofpac + .type bad_signing_oracle_nofpac,@function +bad_signing_oracle_nofpac: +// SIGN-ORACLES-NOFPAC: GS-PAUTH: signing oracle found in function bad_signing_oracle_nofpac +// AUTH-ORACLES-NOFPAC: GS-PAUTH: authentication oracle found in function bad_signing_oracle_nofpac + autda x0, x1 + pacdb x0, x1 + ret + .size bad_signing_oracle_nofpac, .-bad_signing_oracle_nofpac + + .globl bad_auth_oracle + .type bad_auth_oracle,@function +bad_auth_oracle: +// AUTH-ORACLES-NOFPAC: GS-PAUTH: authentication oracle found in function bad_auth_oracle + autda x0, x1 + ret + .size bad_auth_oracle, .-bad_auth_oracle diff --git a/bolt/test/binary-analysis/AArch64/gs-pauth-signing-oracles.s b/bolt/test/binary-analysis/AArch64/gs-pauth-signing-oracles.s index 7d908f234d85..920782bbacab 100644 --- a/bolt/test/binary-analysis/AArch64/gs-pauth-signing-oracles.s +++ b/bolt/test/binary-analysis/AArch64/gs-pauth-signing-oracles.s @@ -1,15 +1,12 @@ // RUN: %clang %cflags -march=armv8.3-a+pauth-lr -Wl,--no-relax %s -o %t.exe -// RUN: llvm-bolt-binary-analysis --scanners=pacret %t.exe 2>&1 | FileCheck -check-prefix=PACRET %s -// RUN: llvm-bolt-binary-analysis --scanners=pauth %t.exe 2>&1 | FileCheck -check-prefixes=CHECK,NOFPAC %s -// RUN: llvm-bolt-binary-analysis --scanners=pauth --auth-traps-on-failure %t.exe 2>&1 | FileCheck -check-prefixes=CHECK,FPAC %s +// RUN: llvm-bolt-binary-analysis --scanners=ptrauth-sign-oracles %t.exe 2>&1 | FileCheck -check-prefixes=CHECK,NOFPAC %s +// RUN: llvm-bolt-binary-analysis --scanners=ptrauth-sign-oracles --auth-traps-on-failure %t.exe 2>&1 | FileCheck -check-prefixes=CHECK,FPAC %s // The detection of compiler-generated explicit pointer checks is tested in // gs-pauth-address-checks.s, for that reason only test here "dummy-load" and // "high-bits-notbi" checkers, as the shortest examples of checkers that are // detected per-instruction and per-BB. -// PACRET-NOT: signing oracle found in function - .text .type sym,@function diff --git a/bolt/test/binary-analysis/AArch64/gs-pauth-tail-calls.s b/bolt/test/binary-analysis/AArch64/gs-pauth-tail-calls.s index 59b7d929275a..daef83c69cec 100644 --- a/bolt/test/binary-analysis/AArch64/gs-pauth-tail-calls.s +++ b/bolt/test/binary-analysis/AArch64/gs-pauth-tail-calls.s @@ -1,9 +1,6 @@ // RUN: %clang %cflags -Wl,--entry=_custom_start -march=armv8.3-a %s -o %t.exe -// RUN: llvm-bolt-binary-analysis --scanners=pacret %t.exe 2>&1 | FileCheck -check-prefix=PACRET %s -// RUN: llvm-bolt-binary-analysis --scanners=pauth --auth-traps-on-failure %t.exe 2>&1 | FileCheck -check-prefixes=CHECK,FPAC %s -// RUN: llvm-bolt-binary-analysis --scanners=pauth %t.exe 2>&1 | FileCheck -check-prefixes=CHECK,NOFPAC %s - -// PACRET-NOT: untrusted link register found before tail call +// RUN: llvm-bolt-binary-analysis --scanners=ptrauth-all --auth-traps-on-failure %t.exe 2>&1 | FileCheck -check-prefixes=CHECK,FPAC %s +// RUN: llvm-bolt-binary-analysis --scanners=ptrauth-all %t.exe 2>&1 | FileCheck -check-prefixes=CHECK,NOFPAC %s .text diff --git a/bolt/test/binary-analysis/AArch64/trap-instructions.s b/bolt/test/binary-analysis/AArch64/trap-instructions.s index 7810b2d3c362..0d61440a5ed5 100644 --- a/bolt/test/binary-analysis/AArch64/trap-instructions.s +++ b/bolt/test/binary-analysis/AArch64/trap-instructions.s @@ -1,5 +1,5 @@ // RUN: %clang %cflags -march=armv8.3-a %s -o %t.exe -Wl,--emit-relocs -// RUN: llvm-bolt-binary-analysis --scanners=pauth %t.exe 2>&1 | FileCheck %s +// RUN: llvm-bolt-binary-analysis --scanners=ptrauth-all %t.exe 2>&1 | FileCheck %s // Test what instructions can be used to terminate the program abnormally // on security violation.