You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This adds an initial pac-ret gadget scanner to the
llvm-bolt-binary-analysis-tool.
The scanner is taken from the prototype that was published last year at
main...kbeyls:llvm-project:bolt-gadget-scanner-prototype,
and has been discussed in RFC
https://discourse.llvm.org/t/rfc-bolt-based-binary-analysis-tool-to-verify-correctness-of-security-hardening/78148
and in the EuroLLVM 2024 keynote "Does LLVM implement security
hardenings correctly? A BOLT-based static analyzer to the rescue?"
[Video](https://youtu.be/Sn_Fxa0tdpY)
[Slides](https://llvm.org/devmtg/2024-04/slides/Keynote/Beyls_EuroLLVM2024_security_hardening_keynote.pdf)
In the spirit of incremental development, this PR aims to add a minimal
implementation that is "fully working" on its own, but has major
limitations, as described in the bolt/docs/BinaryAnalysis.md
documentation in this proposed commit. These and other limitations will
be fixed in follow-on PRs, mostly based on code already existing in the
prototype branch. I hope incrementally upstreaming will make it easier
to review the code.
Note that I believe that this could also form the basis of a scanner to
analyze correct implementation of PAuthABI.
in the upper bits of the pointer. This makes it substantially harder for
78
+
attackers to divert control flow by overwriting a return address with a
79
+
different value.
80
+
81
+
The hardening scheme relies on compilers producing appropriate code sequences when
82
+
processing return addresses, especially when these are stored to and retrieved
83
+
from memory.
84
+
85
+
The `pac-ret` binary analysis can be invoked using the command line option
86
+
`--scanners=pac-ret`. It makes `llvm-bolt-binary-analysis` scan through the
87
+
provided binary, checking each function for the following security property:
88
+
89
+
> For each procedure and exception return instruction, the destination register
90
+
> must have one of the following properties:
91
+
>
92
+
> 1. be immutable within the function, or
93
+
> 2. the last write to the register must be by an authenticating instruction. This
94
+
> includes combined authentication and return instructions such as `RETAA`.
95
+
96
+
##### Example 1
97
+
98
+
For example, a typical non-pac-ret-protected function looks as follows:
99
+
100
+
```
101
+
stp x29, x30, [sp, #-0x10]!
102
+
mov x29, sp
103
+
bl g@PLT
104
+
add x0, x0, #0x3
105
+
ldp x29, x30, [sp], #0x10
106
+
ret
107
+
```
108
+
109
+
The return instruction `ret` implicitly uses register `x30` as the address to
110
+
return to. Register `x30` was last written by instruction `ldp`, which is not an
111
+
authenticating instruction. `llvm-bolt-binary-analysis --scanners=pac-ret` will
112
+
report this as follows:
113
+
114
+
```
115
+
GS-PACRET: non-protected ret found in function f1, basic block .LBB00, at address 10310
116
+
The return instruction is 00010310: ret # pacret-gadget: pac-ret-gadget<Ret:MCInstBBRef<BB:.LBB00:6>, Overwriting:[MCInstBBRef<BB:.LBB00:5> ]>
117
+
The 1 instructions that write to the return register after any authentication are:
118
+
1. 0001030c: ldp x29, x30, [sp], #0x10
119
+
This happens in the following basic block:
120
+
000102fc: stp x29, x30, [sp, #-0x10]!
121
+
00010300: mov x29, sp
122
+
00010304: bl g@PLT
123
+
00010308: add x0, x0, #0x3
124
+
0001030c: ldp x29, x30, [sp], #0x10
125
+
00010310: ret # pacret-gadget: pac-ret-gadget<Ret:MCInstBBRef<BB:.LBB00:6>, Overwriting:[MCInstBBRef<BB:.LBB00:5> ]>
126
+
```
127
+
128
+
The exact format of how `llvm-bolt-binary-analysis` reports this is expected to
129
+
evolve over time.
130
+
131
+
##### Example 2: multiple "last-overwriting" instructions
132
+
133
+
A simple example that shows how there can be a set of "last overwriting"
134
+
instructions of a register follows:
135
+
136
+
```
137
+
paciasp
138
+
stp x29, x30, [sp, #-0x10]!
139
+
ldp x29, x30, [sp], #0x10
140
+
cbnz x0, 1f
141
+
autiasp
142
+
1:
143
+
ret
144
+
```
145
+
146
+
This will produce the following diagnostic:
147
+
148
+
```
149
+
GS-PACRET: non-protected ret found in function f_crossbb1, basic block .Ltmp0, at address 102dc
150
+
The return instruction is 000102dc: ret # pacret-gadget: pac-ret-gadget<Ret:MCInstBBRef<BB:.Ltmp0:0>, Overwriting:[MCInstBBRef<BB:.LFT0:0> MCInstBBRef<BB:.LBB00:2> ]>
151
+
The 2 instructions that write to the return register after any authentication are:
152
+
1. 000102d0: ldp x29, x30, [sp], #0x10
153
+
2. 000102d8: autiasp
154
+
```
155
+
156
+
(Yes, this diagnostic could be improved because the second "overwriting"
157
+
instruction, `autiasp`, is an authenticating instruction...)
158
+
159
+
##### Known false positives or negatives
160
+
161
+
The following are current known cases of false positives:
162
+
163
+
1. Not handling "no-return" functions. See issue
164
+
[#115154](https://github.com/llvm/llvm-project/issues/115154) for details and
165
+
pointers to open PRs to fix this.
166
+
2. Not recognizing that a move of a properly authenticated value between registers,
167
+
results in the destination register having a properly authenticated value.
168
+
For example, the scanner currently produces a false negative for the following
169
+
code sequence:
170
+
```
171
+
autiasp
172
+
mov x16, x30
173
+
ret x16
174
+
```
175
+
176
+
The following are current known cases of false negatives:
177
+
178
+
1. Not handling functions for which the CFG cannot be reconstructed by BOLT. The
179
+
plan is to implement support for this, picking up the implementation from the
0 commit comments