Skip to content

Commit 7181a6b

Browse files
committed
Fix handling of DstState::FirstInstLeakingReg
1 parent 25f44ec commit 7181a6b

File tree

3 files changed

+39
-29
lines changed

3 files changed

+39
-29
lines changed

bolt/lib/Passes/PAuthGadgetScanner.cpp

+19-12
Original file line numberDiff line numberDiff line change
@@ -232,12 +232,11 @@ struct SrcState {
232232
bool operator!=(const SrcState &RHS) const { return !((*this) == RHS); }
233233
};
234234

235-
static void
236-
printLastInsts(raw_ostream &OS,
237-
ArrayRef<SmallPtrSet<const MCInst *, 4>> LastInstWritingReg) {
235+
static void printInstsShort(raw_ostream &OS,
236+
ArrayRef<SmallPtrSet<const MCInst *, 4>> Insts) {
238237
OS << "Insts: ";
239-
for (unsigned I = 0; I < LastInstWritingReg.size(); ++I) {
240-
auto &Set = LastInstWritingReg[I];
238+
for (unsigned I = 0; I < Insts.size(); ++I) {
239+
auto &Set = Insts[I];
241240
OS << "[" << I << "](";
242241
for (const MCInst *MCInstP : Set)
243242
OS << MCInstP << " ";
@@ -252,7 +251,7 @@ raw_ostream &operator<<(raw_ostream &OS, const SrcState &S) {
252251
} else {
253252
OS << "SafeToDerefRegs: " << S.SafeToDerefRegs << ", ";
254253
OS << "TrustedRegs: " << S.TrustedRegs << ", ";
255-
printLastInsts(OS, S.LastInstWritingReg);
254+
printInstsShort(OS, S.LastInstWritingReg);
256255
}
257256
OS << ">";
258257
return OS;
@@ -281,7 +280,7 @@ void SrcStatePrinter::print(raw_ostream &OS, const SrcState &S) const {
281280
OS << ", TrustedRegs: ";
282281
RegStatePrinter.print(OS, S.TrustedRegs);
283282
OS << ", ";
284-
printLastInsts(OS, S.LastInstWritingReg);
283+
printInstsShort(OS, S.LastInstWritingReg);
285284
}
286285
OS << ">";
287286
}
@@ -752,7 +751,7 @@ SrcSafetyAnalysis::create(BinaryFunction &BF,
752751
struct DstState {
753752
/// The set of registers whose values cannot be inspected by an attacker in
754753
/// a way usable as an authentication oracle. The results of authentication
755-
/// instructions should be written to such registers.
754+
/// instructions should only be written to such registers.
756755
BitVector CannotEscapeUnchecked;
757756

758757
std::vector<SmallPtrSet<const MCInst *, 4>> FirstInstLeakingReg;
@@ -770,6 +769,9 @@ struct DstState {
770769
return (*this = StateIn);
771770

772771
CannotEscapeUnchecked &= StateIn.CannotEscapeUnchecked;
772+
for (unsigned I = 0; I < FirstInstLeakingReg.size(); ++I)
773+
for (const MCInst *J : StateIn.FirstInstLeakingReg[I])
774+
FirstInstLeakingReg[I].insert(J);
773775
return *this;
774776
}
775777

@@ -778,7 +780,8 @@ struct DstState {
778780
bool empty() const { return CannotEscapeUnchecked.empty(); }
779781

780782
bool operator==(const DstState &RHS) const {
781-
return CannotEscapeUnchecked == RHS.CannotEscapeUnchecked;
783+
return CannotEscapeUnchecked == RHS.CannotEscapeUnchecked &&
784+
FirstInstLeakingReg == RHS.FirstInstLeakingReg;
782785
}
783786
bool operator!=(const DstState &RHS) const { return !((*this) == RHS); }
784787
};
@@ -788,7 +791,8 @@ raw_ostream &operator<<(raw_ostream &OS, const DstState &S) {
788791
if (S.empty()) {
789792
OS << "empty";
790793
} else {
791-
OS << "CannotEscapeUnchecked: " << S.CannotEscapeUnchecked;
794+
OS << "CannotEscapeUnchecked: " << S.CannotEscapeUnchecked << ", ";
795+
printInstsShort(OS, S.FirstInstLeakingReg);
792796
}
793797
OS << ">";
794798
return OS;
@@ -808,10 +812,13 @@ void DstStatePrinter::print(raw_ostream &OS, const DstState &S) const {
808812
OS << "dst-state<";
809813
if (S.empty()) {
810814
assert(S.CannotEscapeUnchecked.empty());
815+
assert(S.FirstInstLeakingReg.empty());
811816
OS << "empty";
812817
} else {
813818
OS << "CannotEscapeUnchecked: ";
814819
RegStatePrinter.print(OS, S.CannotEscapeUnchecked);
820+
OS << ", ";
821+
printInstsShort(OS, S.FirstInstLeakingReg);
815822
}
816823
OS << ">";
817824
}
@@ -841,6 +848,7 @@ class DstSafetyAnalysis {
841848
const unsigned NumRegs;
842849

843850
const TrackedRegisters RegsToTrackInstsFor;
851+
844852
/// Stores information about the detected instruction sequences emitted to
845853
/// check an authenticated pointer. Specifically, if such sequence is detected
846854
/// in a basic block, it maps the first instruction of that sequence to the
@@ -897,7 +905,6 @@ class DstSafetyAnalysis {
897905
const BitVector &LeakedRegs,
898906
const DstState &Cur) const {
899907
SmallVector<MCPhysReg> Regs;
900-
const MCPhysReg NoReg = BC.MIB->getNoRegister();
901908

902909
// A pointer can be checked, or
903910
if (auto CheckedReg =
@@ -911,7 +918,7 @@ class DstSafetyAnalysis {
911918
bool IsAuthenticated;
912919
MCPhysReg BranchDestReg =
913920
BC.MIB->getRegUsedAsIndirectBranchDest(Inst, IsAuthenticated);
914-
assert(BranchDestReg != NoReg);
921+
assert(BranchDestReg != BC.MIB->getNoRegister());
915922
if (!IsAuthenticated)
916923
Regs.push_back(BranchDestReg);
917924
}

bolt/test/binary-analysis/AArch64/gs-pauth-authentication-oracles.s

+6-3
Original file line numberDiff line numberDiff line change
@@ -350,7 +350,8 @@ bad_leaked_to_subroutine_multi_bb:
350350
bad_unknown_usage_read_multi_bb:
351351
// CHECK-LABEL: GS-PAUTH: authentication oracle found in function bad_unknown_usage_read_multi_bb, basic block {{[^,]+}}, at address
352352
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: autia x0, x1
353-
// CHECK-NEXT: The 0 instructions that leak the affected registers are:
353+
// CHECK-NEXT: The 1 instructions that leak the affected registers are:
354+
// CHECK-NEXT: 1. {{[0-9a-f]+}}: mul x3, x0, x1
354355
autia x0, x1
355356
cbz x3, 1f
356357
mul x3, x0, x1
@@ -364,7 +365,8 @@ bad_unknown_usage_read_multi_bb:
364365
bad_unknown_usage_subreg_read_multi_bb:
365366
// CHECK-LABEL: GS-PAUTH: authentication oracle found in function bad_unknown_usage_subreg_read_multi_bb, basic block {{[^,]+}}, at address
366367
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: autia x0, x1
367-
// CHECK-NEXT: The 0 instructions that leak the affected registers are:
368+
// CHECK-NEXT: The 1 instructions that leak the affected registers are:
369+
// CHECK-NEXT: 1. {{[0-9a-f]+}}: mul w3, w0, w1
368370
autia x0, x1
369371
cbz x3, 1f
370372
mul w3, w0, w1
@@ -378,7 +380,8 @@ bad_unknown_usage_subreg_read_multi_bb:
378380
bad_unknown_usage_update_multi_bb:
379381
// CHECK-LABEL: GS-PAUTH: authentication oracle found in function bad_unknown_usage_update_multi_bb, basic block {{[^,]+}}, at address
380382
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: autia x0, x1
381-
// CHECK-NEXT: The 0 instructions that leak the affected registers are:
383+
// CHECK-NEXT: The 1 instructions that leak the affected registers are:
384+
// CHECK-NEXT: 1. {{[0-9a-f]+}}: movk x0, #0x2a, lsl #16
382385
autia x0, x1
383386
cbz x3, 1f
384387
movk x0, #42, lsl #16 // does not overwrite x0 completely

bolt/test/binary-analysis/AArch64/gs-pauth-debug-output.s

+14-14
Original file line numberDiff line numberDiff line change
@@ -282,10 +282,10 @@ auth_oracle:
282282
// CHECK: End of Function "auth_oracle"
283283
// ...
284284
// PAUTH: Running dst register safety analysis...
285-
// PAUTH-NEXT: DstSafetyAnalysis::ComputeNext( ret x30, dst-state<CannotEscapeUnchecked: >)
286-
// PAUTH-NEXT: .. result: (dst-state<CannotEscapeUnchecked: LR W30 W30_HI >)
287-
// PAUTH-NEXT: DstSafetyAnalysis::ComputeNext( autia x0, x1, dst-state<CannotEscapeUnchecked: LR W30 W30_HI >)
288-
// PAUTH-NEXT: .. result: (dst-state<CannotEscapeUnchecked: LR W30 W30_HI >)
285+
// PAUTH-NEXT: DstSafetyAnalysis::ComputeNext( ret x30, dst-state<CannotEscapeUnchecked: , Insts: >)
286+
// PAUTH-NEXT: .. result: (dst-state<CannotEscapeUnchecked: LR W30 W30_HI , Insts: >)
287+
// PAUTH-NEXT: DstSafetyAnalysis::ComputeNext( autia x0, x1, dst-state<CannotEscapeUnchecked: LR W30 W30_HI , Insts: >)
288+
// PAUTH-NEXT: .. result: (dst-state<CannotEscapeUnchecked: LR W30 W30_HI , Insts: >)
289289
// PAUTH-NEXT: After dst register safety analysis:
290290
// PAUTH-NEXT: Binary Function "auth_oracle" {
291291
// PAUTH-NEXT: Number : 4
@@ -295,22 +295,22 @@ auth_oracle:
295295
// PAUTH-NEXT: }
296296
// PAUTH-NEXT: [[BB0]] (2 instructions, align : 1)
297297
// PAUTH-NEXT: Entry Point
298-
// PAUTH-NEXT: 00000000: autia x0, x1 # DataflowDstSafetyAnalysis: dst-state<CannotEscapeUnchecked: BitVector>
299-
// PAUTH-NEXT: 00000004: ret # DataflowDstSafetyAnalysis: dst-state<CannotEscapeUnchecked: BitVector>
298+
// PAUTH-NEXT: 00000000: autia x0, x1 # DataflowDstSafetyAnalysis: dst-state<CannotEscapeUnchecked: BitVector, Insts: >
299+
// PAUTH-NEXT: 00000004: ret # DataflowDstSafetyAnalysis: dst-state<CannotEscapeUnchecked: BitVector, Insts: >
300300
// PAUTH-EMPTY:
301301
// PAUTH-NEXT: DWARF CFI Instructions:
302302
// PAUTH-NEXT: <empty>
303303
// PAUTH-NEXT: End of Function "auth_oracle"
304304
// PAUTH-EMPTY:
305-
// PAUTH-NEXT: Found auth inst: 00000000: autia x0, x1 # DataflowDstSafetyAnalysis: dst-state<CannotEscapeUnchecked: BitVector>
305+
// PAUTH-NEXT: Found auth inst: 00000000: autia x0, x1 # DataflowDstSafetyAnalysis: dst-state<CannotEscapeUnchecked: BitVector, Insts: >
306306
// PAUTH-NEXT: Authenticated reg: X0
307307
// PAUTH-NEXT: safe output registers: LR W30 W30_HI
308308
// PAUTH-EMPTY:
309309
// PAUTH-NEXT: Running detailed dst register safety analysis...
310-
// PAUTH-NEXT: DstSafetyAnalysis::ComputeNext( ret x30, dst-state<CannotEscapeUnchecked: >)
311-
// PAUTH-NEXT: .. result: (dst-state<CannotEscapeUnchecked: LR W30 W30_HI >)
312-
// PAUTH-NEXT: DstSafetyAnalysis::ComputeNext( autia x0, x1, dst-state<CannotEscapeUnchecked: LR W30 W30_HI >)
313-
// PAUTH-NEXT: .. result: (dst-state<CannotEscapeUnchecked: LR W30 W30_HI >)
310+
// PAUTH-NEXT: DstSafetyAnalysis::ComputeNext( ret x30, dst-state<CannotEscapeUnchecked: , Insts: [0]()>)
311+
// PAUTH-NEXT: .. result: (dst-state<CannotEscapeUnchecked: LR W30 W30_HI , Insts: [0]()>)
312+
// PAUTH-NEXT: DstSafetyAnalysis::ComputeNext( autia x0, x1, dst-state<CannotEscapeUnchecked: LR W30 W30_HI , Insts: [0]()>)
313+
// PAUTH-NEXT: .. result: (dst-state<CannotEscapeUnchecked: LR W30 W30_HI , Insts: [0](0x{{[0-9a-f]+}} )>)
314314
// PAUTH-NEXT: After detailed dst register safety analysis:
315315
// PAUTH-NEXT: Binary Function "auth_oracle" {
316316
// PAUTH-NEXT: Number : 4
@@ -320,14 +320,14 @@ auth_oracle:
320320
// PAUTH-NEXT: }
321321
// PAUTH-NEXT: [[BB0]] (2 instructions, align : 1)
322322
// PAUTH-NEXT: Entry Point
323-
// PAUTH-NEXT: 00000000: autia x0, x1 # DataflowDstSafetyAnalysis: dst-state<CannotEscapeUnchecked: BitVector>
324-
// PAUTH-NEXT: 00000004: ret # DataflowDstSafetyAnalysis: dst-state<CannotEscapeUnchecked: BitVector>
323+
// PAUTH-NEXT: 00000000: autia x0, x1 # DataflowDstSafetyAnalysis: dst-state<CannotEscapeUnchecked: BitVector, Insts: [0](0x{{[0-9a-f]+}} )>
324+
// PAUTH-NEXT: 00000004: ret # DataflowDstSafetyAnalysis: dst-state<CannotEscapeUnchecked: BitVector, Insts: [0]()>
325325
// PAUTH-EMPTY:
326326
// PAUTH-NEXT: DWARF CFI Instructions:
327327
// PAUTH-NEXT: <empty>
328328
// PAUTH-NEXT: End of Function "auth_oracle"
329329
// PAUTH-EMPTY:
330-
// PAUTH-NEXT: Attaching leakage info to: 00000000: autia x0, x1 # DataflowDstSafetyAnalysis: dst-state<CannotEscapeUnchecked: BitVector>
330+
// PAUTH-NEXT: Attaching leakage info to: 00000000: autia x0, x1 # DataflowDstSafetyAnalysis: dst-state<CannotEscapeUnchecked: BitVector, Insts: [0](0x{{[0-9a-f]+}} )>
331331

332332
// CHECK-LABEL:Analyzing function main, AllocatorId = 1
333333
.globl main

0 commit comments

Comments
 (0)