-
Notifications
You must be signed in to change notification settings - Fork 13.5k
[BOLT] Gadget scanner: optionally assume auth traps on failure #139778
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: users/atrosinenko/bolt-gs-safe-jump-tables
Are you sure you want to change the base?
[BOLT] Gadget scanner: optionally assume auth traps on failure #139778
Conversation
@llvm/pr-subscribers-bolt Author: Anatoly Trosinenko (atrosinenko) ChangesOn AArch64 it is possible for an auth instruction to either return an This commit implements an --auth-traps-on-failure command line option, Patch is 53.54 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/139778.diff 8 Files Affected:
diff --git a/bolt/lib/Passes/PAuthGadgetScanner.cpp b/bolt/lib/Passes/PAuthGadgetScanner.cpp
index 4bd1ccb4520c1..592a1acce1bd4 100644
--- a/bolt/lib/Passes/PAuthGadgetScanner.cpp
+++ b/bolt/lib/Passes/PAuthGadgetScanner.cpp
@@ -14,6 +14,7 @@
#include "bolt/Passes/PAuthGadgetScanner.h"
#include "bolt/Core/ParallelUtilities.h"
#include "bolt/Passes/DataflowAnalysis.h"
+#include "bolt/Utils/CommandLineOpts.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/MC/MCInst.h"
@@ -26,6 +27,11 @@ namespace llvm {
namespace bolt {
namespace PAuthGadgetScanner {
+static cl::opt<bool> AuthTrapsOnFailure(
+ "auth-traps-on-failure",
+ cl::desc("Assume authentication instructions always trap on failure"),
+ cl::cat(opts::BinaryAnalysisCategory));
+
[[maybe_unused]] static void traceInst(const BinaryContext &BC, StringRef Label,
const MCInst &MI) {
dbgs() << " " << Label << ": ";
@@ -332,6 +338,34 @@ class SrcSafetyAnalysis {
return Clobbered;
}
+ std::optional<MCPhysReg> getRegMadeTrustedByChecking(const MCInst &Inst,
+ SrcState Cur) const {
+ // This functions cannot return multiple registers. This is never the case
+ // on AArch64.
+ std::optional<MCPhysReg> RegCheckedByInst =
+ BC.MIB->getAuthCheckedReg(Inst, /*MayOverwrite=*/false);
+ if (RegCheckedByInst && Cur.SafeToDerefRegs[*RegCheckedByInst])
+ return *RegCheckedByInst;
+
+ auto It = CheckerSequenceInfo.find(&Inst);
+ if (It == CheckerSequenceInfo.end())
+ return std::nullopt;
+
+ MCPhysReg RegCheckedBySequence = It->second.first;
+ const MCInst *FirstCheckerInst = It->second.second;
+
+ // FirstCheckerInst should belong to the same basic block (see the
+ // assertion in DataflowSrcSafetyAnalysis::run()), meaning it was
+ // deterministically processed a few steps before this instruction.
+ const SrcState &StateBeforeChecker = getStateBefore(*FirstCheckerInst);
+
+ // The sequence checks the register, but it should be authenticated before.
+ if (!StateBeforeChecker.SafeToDerefRegs[RegCheckedBySequence])
+ return std::nullopt;
+
+ return RegCheckedBySequence;
+ }
+
// Returns all registers that can be treated as if they are written by an
// authentication instruction.
SmallVector<MCPhysReg> getRegsMadeSafeToDeref(const MCInst &Point,
@@ -354,18 +388,38 @@ class SrcSafetyAnalysis {
Regs.push_back(DstAndSrc->first);
}
+ // Make sure explicit checker sequence keeps register safe-to-dereference
+ // when the register would be clobbered according to the regular rules:
+ //
+ // ; LR is safe to dereference here
+ // mov x16, x30 ; start of the sequence, LR is s-t-d right before
+ // xpaclri ; clobbers LR, LR is not safe anymore
+ // cmp x30, x16
+ // b.eq 1f ; end of the sequence: LR is marked as trusted
+ // brk 0x1234
+ // 1:
+ // ; at this point LR would be marked as trusted,
+ // ; but not safe-to-dereference
+ //
+ // or even just
+ //
+ // ; X1 is safe to dereference here
+ // ldr x0, [x1, #8]!
+ // ; X1 is trusted here, but it was clobbered due to address write-back
+ if (auto CheckedReg = getRegMadeTrustedByChecking(Point, Cur))
+ Regs.push_back(*CheckedReg);
+
return Regs;
}
// Returns all registers made trusted by this instruction.
SmallVector<MCPhysReg> getRegsMadeTrusted(const MCInst &Point,
const SrcState &Cur) const {
+ assert(!AuthTrapsOnFailure && "Use getRegsMadeSafeToDeref instead");
SmallVector<MCPhysReg> Regs;
// An authenticated pointer can be checked, or
- std::optional<MCPhysReg> CheckedReg =
- BC.MIB->getAuthCheckedReg(Point, /*MayOverwrite=*/false);
- if (CheckedReg && Cur.SafeToDerefRegs[*CheckedReg])
+ if (auto CheckedReg = getRegMadeTrustedByChecking(Point, Cur))
Regs.push_back(*CheckedReg);
// ... a pointer can be authenticated by an instruction that always checks
@@ -376,19 +430,6 @@ class SrcSafetyAnalysis {
if (AutReg && IsChecked)
Regs.push_back(*AutReg);
- if (CheckerSequenceInfo.contains(&Point)) {
- MCPhysReg CheckedReg;
- const MCInst *FirstCheckerInst;
- std::tie(CheckedReg, FirstCheckerInst) = CheckerSequenceInfo.at(&Point);
-
- // FirstCheckerInst should belong to the same basic block (see the
- // assertion in DataflowSrcSafetyAnalysis::run()), meaning it was
- // deterministically processed a few steps before this instruction.
- const SrcState &StateBeforeChecker = getStateBefore(*FirstCheckerInst);
- if (StateBeforeChecker.SafeToDerefRegs[CheckedReg])
- Regs.push_back(CheckedReg);
- }
-
// ... a safe address can be materialized, or
if (auto NewAddrReg = BC.MIB->getMaterializedAddressRegForPtrAuth(Point))
Regs.push_back(*NewAddrReg);
@@ -432,28 +473,11 @@ class SrcSafetyAnalysis {
BitVector Clobbered = getClobberedRegs(Point);
SmallVector<MCPhysReg> NewSafeToDerefRegs =
getRegsMadeSafeToDeref(Point, Cur);
- SmallVector<MCPhysReg> NewTrustedRegs = getRegsMadeTrusted(Point, Cur);
-
- // Ideally, being trusted is a strictly stronger property than being
- // safe-to-dereference. To simplify the computation of Next state, enforce
- // this for NewSafeToDerefRegs and NewTrustedRegs. Additionally, this
- // fixes the properly for "cumulative" register states in tricky cases
- // like the following:
- //
- // ; LR is safe to dereference here
- // mov x16, x30 ; start of the sequence, LR is s-t-d right before
- // xpaclri ; clobbers LR, LR is not safe anymore
- // cmp x30, x16
- // b.eq 1f ; end of the sequence: LR is marked as trusted
- // brk 0x1234
- // 1:
- // ; at this point LR would be marked as trusted,
- // ; but not safe-to-dereference
- //
- for (auto TrustedReg : NewTrustedRegs) {
- if (!is_contained(NewSafeToDerefRegs, TrustedReg))
- NewSafeToDerefRegs.push_back(TrustedReg);
- }
+ // If authentication instructions trap on failure, safe-to-dereference
+ // registers are always trusted.
+ SmallVector<MCPhysReg> NewTrustedRegs =
+ AuthTrapsOnFailure ? NewSafeToDerefRegs
+ : getRegsMadeTrusted(Point, Cur);
// Then, compute the state after this instruction is executed.
SrcState Next = Cur;
@@ -490,6 +514,11 @@ class SrcSafetyAnalysis {
dbgs() << ")\n";
});
+ // Being trusted is a strictly stronger property than being
+ // safe-to-dereference.
+ assert(!Next.TrustedRegs.test(Next.SafeToDerefRegs) &&
+ "SafeToDerefRegs should contain all TrustedRegs");
+
return Next;
}
@@ -1066,6 +1095,11 @@ class DataflowDstSafetyAnalysis
}
void run() override {
+ // As long as DstSafetyAnalysis is only computed to detect authentication
+ // oracles, it is a waste of time to compute it when authentication
+ // instructions are known to always trap on failure.
+ assert(!AuthTrapsOnFailure &&
+ "DstSafetyAnalysis is useless with faulting auth");
for (BinaryBasicBlock &BB : Func) {
if (auto CheckerInfo = BC.MIB->getAuthCheckedReg(BB)) {
LLVM_DEBUG({
@@ -1536,6 +1570,8 @@ void FunctionAnalysisContext::findUnsafeDefs(
SmallVector<PartialReport<MCPhysReg>> &Reports) {
if (PacRetGadgetsOnly)
return;
+ if (AuthTrapsOnFailure)
+ return;
auto Analysis = DstSafetyAnalysis::create(BF, AllocatorId, {});
LLVM_DEBUG({ dbgs() << "Running dst register safety analysis...\n"; });
diff --git a/bolt/test/binary-analysis/AArch64/cmdline-args.test b/bolt/test/binary-analysis/AArch64/cmdline-args.test
index 76f7c3ba0a1c7..27069436092b3 100644
--- a/bolt/test/binary-analysis/AArch64/cmdline-args.test
+++ b/bolt/test/binary-analysis/AArch64/cmdline-args.test
@@ -32,6 +32,7 @@ HELP-NEXT: OPTIONS:
HELP-EMPTY:
HELP-NEXT: BinaryAnalysis options:
HELP-EMPTY:
+HELP-NEXT: --auth-traps-on-failure - Assume authentication instructions always trap on failure
HELP-NEXT: --scanners=<value> - which gadget scanners to run
HELP-NEXT: =pacret - pac-ret: return address protection (subset of "pauth")
HELP-NEXT: =pauth - All Pointer Authentication scanners
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 5fdc223c43c6f..acec543b0aed4 100644
--- a/bolt/test/binary-analysis/AArch64/gs-pauth-authentication-oracles.s
+++ b/bolt/test/binary-analysis/AArch64/gs-pauth-authentication-oracles.s
@@ -1,6 +1,7 @@
// 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 %t.exe 2>&1 | FileCheck %s
+// 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
// 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
@@ -8,6 +9,7 @@
// 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 5f49918c39c94..26ebe2d2436a1 100644
--- a/bolt/test/binary-analysis/AArch64/gs-pauth-calls.s
+++ b/bolt/test/binary-analysis/AArch64/gs-pauth-calls.s
@@ -1,6 +1,7 @@
// 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 %t.exe 2>&1 | FileCheck %s
+// 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
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 75341063ab816..e99599c7463c6 100644
--- a/bolt/test/binary-analysis/AArch64/gs-pauth-debug-output.s
+++ b/bolt/test/binary-analysis/AArch64/gs-pauth-debug-output.s
@@ -1,10 +1,14 @@
// REQUIRES: asserts
//
// RUN: %clang %cflags -march=armv8.3-a %s -o %t.exe
-// RUN: llvm-bolt-binary-analysis --scanners=pacret -no-threads \
-// RUN: -debug-only bolt-pauth-scanner %t.exe 2>&1 | FileCheck %s
-// RUN: llvm-bolt-binary-analysis --scanners=pauth -no-threads \
-// RUN: -debug-only bolt-pauth-scanner %t.exe 2>&1 | FileCheck -check-prefixes=CHECK,PAUTH %s
+// RUN: llvm-bolt-binary-analysis --scanners=pacret --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: -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: -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: -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
// that output is kept meaningful and to provide an overview of what happens
@@ -61,30 +65,54 @@ simple:
// CHECK-NEXT: State 1: src-state<empty>
// CHECK-NEXT: State 2: src-state<SafeToDerefRegs: , TrustedRegs: , Insts: >)
// CHECK-NEXT: merged state: src-state<SafeToDerefRegs: , TrustedRegs: , Insts: >
-// CHECK-NEXT: SrcSafetyAnalysis::ComputeNext( autiza x0, src-state<SafeToDerefRegs: , TrustedRegs: , Insts: >)
-// CHECK-NEXT: .. result: (src-state<SafeToDerefRegs: W0 X0 W0_HI , TrustedRegs: , Insts: >)
-// CHECK-NEXT: SrcSafetyAnalysis::ComputeNext( blr x0, src-state<SafeToDerefRegs: W0 X0 W0_HI , TrustedRegs: , Insts: >)
-// CHECK-NEXT: .. result: (src-state<SafeToDerefRegs: , TrustedRegs: , Insts: >)
-// CHECK-NEXT: SrcSafetyAnalysis::ComputeNext( ldp x29, x30, [sp], #0x10, src-state<SafeToDerefRegs: , TrustedRegs: , Insts: >)
-// CHECK-NEXT: .. result: (src-state<SafeToDerefRegs: , TrustedRegs: , Insts: >)
-// CHECK-NEXT: SrcSafetyAnalysis::ComputeNext( hint #29, src-state<SafeToDerefRegs: , TrustedRegs: , Insts: >)
-// CHECK-NEXT: .. result: (src-state<SafeToDerefRegs: LR W30 W30_HI , TrustedRegs: , Insts: >)
-// CHECK-NEXT: SrcSafetyAnalysis::ComputeNext( ret x30, src-state<SafeToDerefRegs: LR W30 W30_HI , TrustedRegs: , Insts: >)
-// CHECK-NEXT: .. result: (src-state<SafeToDerefRegs: LR W30 W30_HI , TrustedRegs: , Insts: >)
-// CHECK-NEXT: DataflowSrcSafetyAnalysis::Confluence(
-// CHECK-NEXT: State 1: src-state<SafeToDerefRegs: , TrustedRegs: , Insts: >
-// CHECK-NEXT: State 2: src-state<SafeToDerefRegs: , TrustedRegs: , Insts: >)
-// CHECK-NEXT: merged state: src-state<SafeToDerefRegs: , TrustedRegs: , Insts: >
-// CHECK-NEXT: SrcSafetyAnalysis::ComputeNext( autiza x0, src-state<SafeToDerefRegs: , TrustedRegs: , Insts: >)
-// CHECK-NEXT: .. result: (src-state<SafeToDerefRegs: W0 X0 W0_HI , TrustedRegs: , Insts: >)
-// CHECK-NEXT: SrcSafetyAnalysis::ComputeNext( blr x0, src-state<SafeToDerefRegs: W0 X0 W0_HI , TrustedRegs: , Insts: >)
-// CHECK-NEXT: .. result: (src-state<SafeToDerefRegs: , TrustedRegs: , Insts: >)
-// CHECK-NEXT: SrcSafetyAnalysis::ComputeNext( ldp x29, x30, [sp], #0x10, src-state<SafeToDerefRegs: , TrustedRegs: , Insts: >)
-// CHECK-NEXT: .. result: (src-state<SafeToDerefRegs: , TrustedRegs: , Insts: >)
-// CHECK-NEXT: SrcSafetyAnalysis::ComputeNext( hint #29, src-state<SafeToDerefRegs: , TrustedRegs: , Insts: >)
-// CHECK-NEXT: .. result: (src-state<SafeToDerefRegs: LR W30 W30_HI , TrustedRegs: , Insts: >)
-// CHECK-NEXT: SrcSafetyAnalysis::ComputeNext( ret x30, src-state<SafeToDerefRegs: LR W30 W30_HI , TrustedRegs: , Insts: >)
-// CHECK-NEXT: .. result: (src-state<SafeToDerefRegs: LR W30 W30_HI , TrustedRegs: , Insts: >)
+// NOFPAC-NEXT: SrcSafetyAnalysis::ComputeNext( autiza x0, src-state<SafeToDerefRegs: , TrustedRegs: , Insts: >)
+// NOFPAC-NEXT: .. result: (src-state<SafeToDerefRegs: W0 X0 W0_HI , TrustedRegs: , Insts: >)
+// NOFPAC-NEXT: SrcSafetyAnalysis::ComputeNext( blr x0, src-state<SafeToDerefRegs: W0 X0 W0_HI , TrustedRegs: , Insts: >)
+// NOFPAC-NEXT: .. result: (src-state<SafeToDerefRegs: , TrustedRegs: , Insts: >)
+// NOFPAC-NEXT: SrcSafetyAnalysis::ComputeNext( ldp x29, x30, [sp], #0x10, src-state<SafeToDerefRegs: , TrustedRegs: , Insts: >)
+// NOFPAC-NEXT: .. result: (src-state<SafeToDerefRegs: , TrustedRegs: , Insts: >)
+// NOFPAC-NEXT: SrcSafetyAnalysis::ComputeNext( hint #29, src-state<SafeToDerefRegs: , TrustedRegs: , Insts: >)
+// NOFPAC-NEXT: .. result: (src-state<SafeToDerefRegs: LR W30 W30_HI , TrustedRegs: , Insts: >)
+// NOFPAC-NEXT: SrcSafetyAnalysis::ComputeNext( ret x30, src-state<SafeToDerefRegs: LR W30 W30_HI , TrustedRegs: , Insts: >)
+// NOFPAC-NEXT: .. result: (src-state<SafeToDerefRegs: LR W30 W30_HI , TrustedRegs: , Insts: >)
+// NOFPAC-NEXT: DataflowSrcSafetyAnalysis::Confluence(
+// NOFPAC-NEXT: State 1: src-state<SafeToDerefRegs: , TrustedRegs: , Insts: >
+// NOFPAC-NEXT: State 2: src-state<SafeToDerefRegs: , TrustedRegs: , Insts: >)
+// NOFPAC-NEXT: merged state: src-state<SafeToDerefRegs: , TrustedRegs: , Insts: >
+// NOFPAC-NEXT: SrcSafetyAnalysis::ComputeNext( autiza x0, src-state<SafeToDerefRegs: , TrustedRegs: , Insts: >)
+// NOFPAC-NEXT: .. result: (src-state<SafeToDerefRegs: W0 X0 W0_HI , TrustedRegs: , Insts: >)
+// NOFPAC-NEXT: SrcSafetyAnalysis::ComputeNext( blr x0, src-state<SafeToDerefRegs: W0 X0 W0_HI , TrustedRegs: , Insts: >)
+// NOFPAC-NEXT: .. result: (src-state<SafeToDerefRegs: , TrustedRegs: , Insts: >)
+// NOFPAC-NEXT: SrcSafetyAnalysis::ComputeNext( ldp x29, x30, [sp], #0x10, src-state<SafeToDerefRegs: , TrustedRegs: , Insts: >)
+// NOFPAC-NEXT: .. result: (src-state<SafeToDerefRegs: , TrustedRegs: , Insts: >)
+// NOFPAC-NEXT: SrcSafetyAnalysis::ComputeNext( hint #29, src-state<SafeToDerefRegs: , TrustedRegs: , Insts: >)
+// NOFPAC-NEXT: .. result: (src-state<SafeToDerefRegs: LR W30 W30_HI , TrustedRegs: , Insts: >)
+// NOFPAC-NEXT: SrcSafetyAnalysis::ComputeNext( ret x30, src-state<SafeToDerefRegs: LR W30 W30_HI , TrustedRegs: , Insts: >)
+// NOFPAC-NEXT: .. result: (src-state<SafeToDerefRegs: LR W30 W30_HI , TrustedRegs: , Insts: >)
+// FPAC-NEXT: SrcSafetyAnalysis::ComputeNext( autiza x0, src-state<SafeToDerefRegs: , TrustedRegs: , Insts: >)
+// FPAC-NEXT: .. result: (src-state<SafeToDerefRegs: W0 X0 W0_HI , TrustedRegs: W0 X0 W0_HI , Insts: >)
+// FPAC-NEXT: SrcSafetyAnalysis::ComputeNext( blr x0, src-state<SafeToDerefRegs: W0 X0 W0_HI , TrustedRegs: W0 X0 W0_HI , Insts: >)
+// FPAC-NEXT: .. result: (src-state<SafeToDerefRegs: , TrustedRegs: , Insts: >)
+// FPAC-NEXT: SrcSafetyAnalysis::ComputeNext( ldp x29, x30, [sp], #0x10, src-state<SafeToDerefRegs: , TrustedRegs: , Insts: >)
+// FPAC-NEXT: .. result: (src-state<SafeToDerefRegs: , TrustedRegs: , Insts: >)
+// FPAC-NEXT: SrcSafetyAnalysis::ComputeNext( hint #29, src-state<SafeToDerefRegs: , TrustedRegs: , Insts: >)
+// FPAC-NEXT: .. result: (src-state<SafeToDerefRegs: LR W30 W30_HI , TrustedRegs: LR W30 W30_HI , Insts: >)
+// FPAC-NEXT: SrcSafetyAnalysis::ComputeNext( ret x30, src-state<SafeToDerefRegs: LR W30 W30_HI , TrustedRegs: LR W30 W30_HI , Insts: >)
+// FPAC-NEXT: .. result: (src-state<SafeToDerefRegs: LR W30 W30_HI , TrustedRegs: LR W30 W30_HI , Insts: >)
+// FPAC-NEXT: DataflowSrcSafetyAnalysis::Confluence(
+// FPAC-NEXT: State 1: src-state<SafeToDerefRegs: , TrustedRegs: , Insts: >
+// FPAC-NEXT: State 2: src-state<SafeToDerefRegs: , TrustedRegs: , Insts: >)
+// FPAC-NEXT: merged state: src-state<SafeToDerefRegs: , TrustedRegs: , Insts: >
+// FPAC-NEXT: SrcSafetyAnalysis::ComputeNext( autiza x0, src-state<SafeToDerefRegs: , TrustedRegs: , Insts: >)
+// FPAC-NEXT: .. result: (src-state<SafeToDerefRegs: W0 X0 W0_HI , TrustedRegs: W0 X0 W0_HI , Insts: >)
+// FPAC-NEXT: SrcSafetyAnalysis::ComputeNext( blr x0, src-state<SafeToDerefRegs: W0 X0 W0_HI , TrustedRegs: W0 X0 W0_HI , Insts: >)
+// FPAC-NEXT: .. result: (src-state<SafeToDerefRegs: , TrustedRegs: , Insts: >)
+// FPAC-NEXT: SrcSafetyAnalysis::ComputeNext( ldp x29, x30, [sp], #0x10, src-state<SafeToDerefRegs: , TrustedRegs: , Insts: >)
+// FPAC-NEXT: .. result: (src-state<SafeToDerefRegs: , TrustedRegs: , Insts: >)
+// FPAC-NEXT: SrcSafetyAnalysis::ComputeNext( hint #29, src-state<SafeToDerefRegs: , TrustedRegs: , Insts: >)
+// FPAC-NEXT: .. result: (src-state<SafeToDerefRegs: LR W30 W30_HI , TrustedRegs: LR W30 W30_HI , Insts: >)
+// FPAC-NEXT: SrcSafetyAnalysis::ComputeNext( ret x30, src-state<SafeToDerefRegs: LR W30 W30_HI , TrustedRegs: LR W30 W30_HI , Insts: >)
+// FPAC-NEXT: .. result: (src-state<SafeToDerefRegs: LR W30 W30_HI , TrustedRegs: LR W30 W30_HI , Insts: >)
// CHECK-NEXT: After src register safety analysis:
// CHECK-NEXT: Binary Function "simple" {
// CHECK-NEXT: Number : 1
@@ -255,53 +283,56 @@ auth_oracle:
// ...
// CHECK: End of Function "auth_oracle"
// ...
-// PAUTH: ...
[truncated]
|
// Being trusted is a strictly stronger property than being | ||
// safe-to-dereference. | ||
assert(!Next.TrustedRegs.test(Next.SafeToDerefRegs) && | ||
"SafeToDerefRegs should contain all TrustedRegs"); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BitVector::test(const BitVector &)
name looks rather ambiguous to me, but here is its definition: BitVector.h.
3cb5667
to
3dd903c
Compare
b7db0ca
to
eae2c10
Compare
On AArch64 it is possible for an auth instruction to either return an invalid address value on failure (without FEAT_FPAC) or generate an error (with FEAT_FPAC). It thus may be possible to never emit explicit pointer checks, if the target CPU is known to support FEAT_FPAC. This commit implements an --auth-traps-on-failure command line option, which essentially makes "safe-to-dereference" and "trusted" register properties identical and disables scanning for authentication oracles completely.
eae2c10
to
cdc385a
Compare
3dd903c
to
8f99750
Compare
On AArch64 it is possible for an auth instruction to either return an
invalid address value on failure (without FEAT_FPAC) or generate an
error (with FEAT_FPAC). It thus may be possible to never emit explicit
pointer checks, if the target CPU is known to support FEAT_FPAC.
This commit implements an --auth-traps-on-failure command line option,
which essentially makes "safe-to-dereference" and "trusted" register
properties identical and disables scanning for authentication oracles
completely.