Skip to content

Commit 9074fad

Browse files
committed
Add a separate scanner category: pauth
1 parent 2d82b35 commit 9074fad

File tree

7 files changed

+43
-21
lines changed

7 files changed

+43
-21
lines changed

bolt/include/bolt/Passes/PAuthGadgetScanner.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,9 @@ struct FunctionAnalysisResult {
248248
};
249249

250250
class Analysis : public BinaryFunctionPass {
251+
/// Only search for pac-ret violations.
252+
bool PacRetGadgetsOnly;
253+
251254
void runOnFunction(BinaryFunction &Function,
252255
MCPlusBuilder::AllocatorIdTy AllocatorId);
253256
FunctionAnalysisResult findGadgets(BinaryFunction &BF,
@@ -261,7 +264,8 @@ class Analysis : public BinaryFunctionPass {
261264
std::mutex AnalysisResultsMutex;
262265

263266
public:
264-
explicit Analysis() : BinaryFunctionPass(false) {}
267+
explicit Analysis(bool PacRetGadgetsOnly)
268+
: BinaryFunctionPass(false), PacRetGadgetsOnly(PacRetGadgetsOnly) {}
265269

266270
const char *getName() const override { return "pauth-gadget-scanner"; }
267271

bolt/include/bolt/Utils/CommandLineOpts.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,9 +81,9 @@ extern llvm::cl::opt<unsigned> Verbosity;
8181
/// Return true if we should process all functions in the binary.
8282
bool processAllFunctions();
8383

84-
enum GadgetScannerKind { GS_PACRET, GS_ALL };
84+
enum GadgetScannerKind { GS_PACRET, GS_PAUTH, GS_ALL };
8585

86-
extern llvm::cl::list<GadgetScannerKind> GadgetScannersToRun;
86+
extern llvm::cl::bits<GadgetScannerKind> GadgetScannersToRun;
8787

8888
} // namespace opts
8989

bolt/lib/Passes/PAuthGadgetScanner.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -504,6 +504,10 @@ Analysis::findGadgets(BinaryFunction &BF,
504504

505505
if (auto Report = shouldReportReturnGadget(BC, Inst, S))
506506
Result.Diagnostics.push_back(Report);
507+
508+
if (PacRetGadgetsOnly)
509+
continue;
510+
507511
if (auto Report = shouldReportCallGadget(BC, Inst, S))
508512
Result.Diagnostics.push_back(Report);
509513
}

bolt/lib/Rewrite/RewriteInstance.cpp

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -247,12 +247,14 @@ static cl::opt<bool> WriteBoltInfoSection(
247247
"bolt-info", cl::desc("write bolt info section in the output binary"),
248248
cl::init(true), cl::Hidden, cl::cat(BoltOutputCategory));
249249

250-
cl::list<GadgetScannerKind>
251-
GadgetScannersToRun("scanners", cl::desc("which gadget scanners to run"),
252-
cl::values(clEnumValN(GS_PACRET, "pacret", "pac-ret"),
253-
clEnumValN(GS_ALL, "all", "all")),
254-
cl::ZeroOrMore, cl::CommaSeparated,
255-
cl::cat(BinaryAnalysisCategory));
250+
cl::bits<GadgetScannerKind> GadgetScannersToRun(
251+
"scanners", cl::desc("which gadget scanners to run"),
252+
cl::values(clEnumValN(GS_PACRET, "pacret",
253+
"Return address protection (subset of \"pauth\")"),
254+
clEnumValN(GS_PAUTH, "pauth",
255+
"All Pointer Authentication scanners"),
256+
clEnumValN(GS_ALL, "all", "All implemented scanners")),
257+
cl::ZeroOrMore, cl::CommaSeparated, cl::cat(BinaryAnalysisCategory));
256258

257259
} // namespace opts
258260

@@ -3539,12 +3541,18 @@ void RewriteInstance::runBinaryAnalyses() {
35393541
// FIXME: add a pass that warns about which functions do not have CFG,
35403542
// and therefore, analysis is most likely to be less accurate.
35413543
using GSK = opts::GadgetScannerKind;
3542-
// if no command line option was given, act as if "all" was specified.
3543-
if (opts::GadgetScannersToRun.empty())
3544-
opts::GadgetScannersToRun.addValue(GSK::GS_ALL);
3545-
for (GSK ScannerToRun : opts::GadgetScannersToRun) {
3546-
if (ScannerToRun == GSK::GS_PACRET || ScannerToRun == GSK::GS_ALL)
3547-
Manager.registerPass(std::make_unique<PAuthGadgetScanner::Analysis>());
3544+
using PAuthScanner = PAuthGadgetScanner::Analysis;
3545+
3546+
// If no command line option was given, act as if "all" was specified.
3547+
bool RunAll = !opts::GadgetScannersToRun.getBits() ||
3548+
opts::GadgetScannersToRun.isSet(GSK::GS_ALL);
3549+
3550+
if (RunAll || opts::GadgetScannersToRun.isSet(GSK::GS_PAUTH)) {
3551+
Manager.registerPass(
3552+
std::make_unique<PAuthScanner>(/*OnlyPacRetChecks=*/false));
3553+
} else if (RunAll || opts::GadgetScannersToRun.isSet(GSK::GS_PACRET)) {
3554+
Manager.registerPass(
3555+
std::make_unique<PAuthScanner>(/*OnlyPacRetChecks=*/true));
35483556
}
35493557

35503558
BC->logBOLTErrorsAndQuitOnFatal(Manager.runPasses());

bolt/test/binary-analysis/AArch64/cmdline-args.test

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ HELP-EMPTY:
3333
HELP-NEXT: BinaryAnalysis options:
3434
HELP-EMPTY:
3535
HELP-NEXT: --scanners=<value> - which gadget scanners to run
36-
HELP-NEXT: =pacret - pac-ret
37-
HELP-NEXT: =all - all
36+
HELP-NEXT: =pacret - Return address protection (subset of "pauth")
37+
HELP-NEXT: =pauth - All Pointer Authentication scanners
38+
HELP-NEXT: =all - All implemented scanners
3839
HELP-EMPTY:
3940
HELP-NEXT: Generic Options:

bolt/test/binary-analysis/AArch64/gs-pauth-calls.s

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
// RUN: %clang %cflags -march=armv8.3-a %s -o %t.exe
2-
// RUN: llvm-bolt-binary-analysis --scanners=pacret %t.exe 2>&1 | FileCheck %s
2+
// RUN: llvm-bolt-binary-analysis --scanners=pacret %t.exe 2>&1 | FileCheck -check-prefix=PACRET %s
3+
// RUN: llvm-bolt-binary-analysis --scanners=pauth %t.exe 2>&1 | FileCheck %s
4+
5+
// PACRET-NOT: non-protected call found in function
36

47
// FIXME In the below test cases, LR is usually not spilled as needed, as it is
58
// not checked by BOLT.

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

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
// RUN: %clang %cflags -march=armv8.3-a %s -o %t.exe
44
// RUN: llvm-bolt-binary-analysis --scanners=pacret -no-threads \
55
// RUN: -debug-only bolt-pauth-scanner %t.exe 2>&1 | FileCheck %s
6+
// RUN: llvm-bolt-binary-analysis --scanners=pauth -no-threads \
7+
// RUN: -debug-only bolt-pauth-scanner %t.exe 2>&1 | FileCheck -check-prefixes=CHECK,PAUTH %s
68

79
// Check the debug output generated by PAuth gadget scanner to make sure the
810
// that output is kept meaningful and to provide an overview of what happens
@@ -108,9 +110,9 @@ simple:
108110
// CHECK-NEXT: <empty>
109111
// CHECK-NEXT: End of Function "simple"
110112
// CHECK-EMPTY:
111-
// CHECK-NEXT: Found call inst: 00000000: blr x0 # PacRetAnalysis: pacret-state<SafeToDerefRegs: BitVector, Insts: >
112-
// CHECK-NEXT: Call destination reg: X0
113-
// CHECK-NEXT: SafeToDerefRegs: W0 X0 W0_HI{{[ \t]*$}}
113+
// PAUTH-NEXT: Found call inst: 00000000: blr x0 # PacRetAnalysis: pacret-state<SafeToDerefRegs: BitVector, Insts: >
114+
// PAUTH-NEXT: Call destination reg: X0
115+
// PAUTH-NEXT: SafeToDerefRegs: W0 X0 W0_HI{{[ \t]*$}}
114116
// CHECK-NEXT: Found RET inst: 00000000: ret # PacRetAnalysis: pacret-state<SafeToDerefRegs: BitVector, Insts: >
115117
// CHECK-NEXT: RetReg: LR
116118
// CHECK-NEXT: Authenticated reg: (none)

0 commit comments

Comments
 (0)