Skip to content

Commit f8b47c5

Browse files
committed
Address review comments
1 parent d9dbf0a commit f8b47c5

File tree

2 files changed

+42
-27
lines changed

2 files changed

+42
-27
lines changed

bolt/include/bolt/Passes/PAuthGadgetScanner.h

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -199,18 +199,25 @@ struct Report {
199199
virtual void generateReport(raw_ostream &OS,
200200
const BinaryContext &BC) const = 0;
201201

202+
// The two methods below are called by Analysis::computeDetailedInfo when
203+
// iterating over the reports.
202204
virtual const ArrayRef<MCPhysReg> getAffectedRegisters() const { return {}; }
203-
virtual void
204-
setOverwritingInstrs(const std::vector<MCInstReference> &Instrs) {}
205+
virtual void setOverwritingInstrs(const ArrayRef<MCInstReference> Instrs) {}
205206

206207
void printBasicInfo(raw_ostream &OS, const BinaryContext &BC,
207208
StringRef IssueKind) const;
208209
};
209210

210211
struct GadgetReport : public Report {
212+
// The particular kind of gadget that is detected.
211213
const GadgetKind &Kind;
214+
// The set of registers related to this gadget report (possibly empty).
212215
SmallVector<MCPhysReg> AffectedRegisters;
213-
std::vector<MCInstReference> OverwritingInstrs;
216+
// The instructions that clobber the affected registers.
217+
// There is no one-to-one correspondence with AffectedRegisters: for example,
218+
// the same register can be overwritten by different instructions in different
219+
// preceding basic blocks.
220+
SmallVector<MCInstReference> OverwritingInstrs;
214221

215222
GadgetReport(const GadgetKind &Kind, MCInstReference Location,
216223
const BitVector &AffectedRegisters)
@@ -223,9 +230,8 @@ struct GadgetReport : public Report {
223230
return AffectedRegisters;
224231
}
225232

226-
void
227-
setOverwritingInstrs(const std::vector<MCInstReference> &Instrs) override {
228-
OverwritingInstrs = Instrs;
233+
void setOverwritingInstrs(const ArrayRef<MCInstReference> Instrs) override {
234+
OverwritingInstrs.assign(Instrs.begin(), Instrs.end());
229235
}
230236
};
231237

@@ -245,8 +251,12 @@ struct FunctionAnalysisResult {
245251
class Analysis : public BinaryFunctionPass {
246252
void runOnFunction(BinaryFunction &Function,
247253
MCPlusBuilder::AllocatorIdTy AllocatorId);
248-
FunctionAnalysisResult
249-
computeDfState(BinaryFunction &BF, MCPlusBuilder::AllocatorIdTy AllocatorId);
254+
FunctionAnalysisResult findGadgets(BinaryFunction &BF,
255+
MCPlusBuilder::AllocatorIdTy AllocatorId);
256+
257+
void computeDetailedInfo(BinaryFunction &BF,
258+
MCPlusBuilder::AllocatorIdTy AllocatorId,
259+
FunctionAnalysisResult &Result);
250260

251261
std::map<const BinaryFunction *, FunctionAnalysisResult> AnalysisResults;
252262
std::mutex AnalysisResultsMutex;

bolt/lib/Passes/PAuthGadgetScanner.cpp

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -376,9 +376,9 @@ class PacRetAnalysis
376376
}
377377
};
378378

379-
static std::shared_ptr<Report> tryCheckReturn(const BinaryContext &BC,
380-
const MCInstReference &Inst,
381-
const State &S) {
379+
static std::shared_ptr<Report>
380+
shouldReportReturnGadget(const BinaryContext &BC, const MCInstReference &Inst,
381+
const State &S) {
382382
static const GadgetKind RetKind("non-protected ret found");
383383
if (!BC.MIB->isReturn(Inst))
384384
return nullptr;
@@ -408,8 +408,8 @@ static std::shared_ptr<Report> tryCheckReturn(const BinaryContext &BC,
408408
}
409409

410410
FunctionAnalysisResult
411-
Analysis::computeDfState(BinaryFunction &BF,
412-
MCPlusBuilder::AllocatorIdTy AllocatorId) {
411+
Analysis::findGadgets(BinaryFunction &BF,
412+
MCPlusBuilder::AllocatorIdTy AllocatorId) {
413413
FunctionAnalysisResult Result;
414414

415415
PacRetAnalysis PRA(BF, AllocatorId, {});
@@ -425,40 +425,39 @@ Analysis::computeDfState(BinaryFunction &BF,
425425
MCInstReference Inst(&BB, I);
426426
const State &S = *PRA.getStateAt(Inst);
427427

428-
if (auto Report = tryCheckReturn(BC, Inst, S))
428+
if (auto Report = shouldReportReturnGadget(BC, Inst, S))
429429
Result.Diagnostics.push_back(Report);
430430
}
431431
}
432+
return Result;
433+
}
432434

433-
if (Result.Diagnostics.empty())
434-
return Result;
435-
436-
// Redo the analysis, but now also track which instructions last wrote
437-
// to any of the registers in RetRegsWithGadgets, so that better
438-
// diagnostics can be produced.
435+
void Analysis::computeDetailedInfo(BinaryFunction &BF,
436+
MCPlusBuilder::AllocatorIdTy AllocatorId,
437+
FunctionAnalysisResult &Result) {
438+
BinaryContext &BC = BF.getBinaryContext();
439439

440+
// Collect the affected registers across all gadgets found in this function.
440441
SmallSet<MCPhysReg, 4> RegsToTrack;
441442
for (auto Report : Result.Diagnostics)
442-
for (MCPhysReg Reg : Report->getAffectedRegisters())
443-
RegsToTrack.insert(Reg);
444-
443+
RegsToTrack.insert_range(Report->getAffectedRegisters());
445444
std::vector<MCPhysReg> RegsToTrackVec(RegsToTrack.begin(), RegsToTrack.end());
446445

446+
// Re-compute the analysis with register tracking.
447447
PacRetAnalysis PRWIA(BF, AllocatorId, RegsToTrackVec);
448448
PRWIA.run();
449449
LLVM_DEBUG({
450450
dbgs() << " After detailed PacRetAnalysis:\n";
451451
BF.dump();
452452
});
453453

454+
// Augment gadget reports.
454455
for (auto Report : Result.Diagnostics) {
455456
LLVM_DEBUG(
456457
{ traceInst(BC, "Attaching clobbering info to", Report->Location); });
457458
Report->setOverwritingInstrs(PRWIA.getLastClobberingInsts(
458459
Report->Location, BF, Report->getAffectedRegisters()));
459460
}
460-
461-
return Result;
462461
}
463462

464463
void Analysis::runOnFunction(BinaryFunction &BF,
@@ -472,10 +471,16 @@ void Analysis::runOnFunction(BinaryFunction &BF,
472471
if (!BF.hasCFG())
473472
return;
474473

475-
FunctionAnalysisResult FAR = computeDfState(BF, AllocatorId);
474+
FunctionAnalysisResult FAR = findGadgets(BF, AllocatorId);
476475
if (FAR.Diagnostics.empty())
477476
return;
478477

478+
// Redo the analysis, but now also track which instructions last wrote
479+
// to any of the registers in RetRegsWithGadgets, so that better
480+
// diagnostics can be produced.
481+
482+
computeDetailedInfo(BF, AllocatorId, FAR);
483+
479484
// `runOnFunction` is typically getting called from multiple threads in
480485
// parallel. Therefore, use a lock to avoid data races when storing the
481486
// result of the analysis in the `AnalysisResults` map.
@@ -540,7 +545,7 @@ void GadgetReport::generateReport(raw_ostream &OS,
540545
<< " instructions that write to the affected registers after any "
541546
"authentication are:\n";
542547
// Sort by address to ensure output is deterministic.
543-
std::vector<MCInstReference> OI = OverwritingInstrs;
548+
SmallVector<MCInstReference> OI = OverwritingInstrs;
544549
llvm::sort(OI, [](const MCInstReference &A, const MCInstReference &B) {
545550
return A.getAddress() < B.getAddress();
546551
});

0 commit comments

Comments
 (0)