Re: [patch 00/38] x86/retbleed: Call depth tracking mitigation

From: Joao Moreira
Date: Mon Jul 18 2022 - 18:47:44 EST


On 2022-07-18 15:22, Thomas Gleixner wrote:
On Mon, Jul 18 2022 at 23:18, Peter Zijlstra wrote:
On Mon, Jul 18, 2022 at 10:44:14PM +0200, Thomas Gleixner wrote:
And we need input from the Clang folks because their CFI work also puts
stuff in front of the function entry, which nicely collides.

Right, I need to go look at the latest kCFI patches, that sorta got
side-tracked for working on all the retbleed muck :/

Basically kCFI wants to preface every (indirect callable) function with:

__cfi_\func:
int3
movl $0x12345678, %rax
int3
int3
\func:
endbr
\func_direct:

Ofc, we can still put the whole:

sarq $5, PER_CPU_VAR(__x86_call_depth);
jmp \func_direct

thing in front of that. But it does somewhat destroy the version I had
that only needs the 10 bytes padding for the sarq.

Right, because it needs the jump. I was just chatting with Jaoa about
that over IRC.

The jump slow things down. Jaoa has ideas and will reply soonish.

So, IIRC, kCFI will do something like this to validate call targets based on the hash as described on Peter's e-mail:

func_whatever:
...
cmpl $0x\hash, -6(%rax)
je 1f
ud2
1:
call *%rax
...

Thus the hash will be 6 bytes before the function entry point. Then we can get the compiler to emit a padding area before the __cfi_\func snippet and, during boot, if the CPU needs the call depth tracking mitigation, we:
- move the __cfi_func into the padding area
- patch the call depth tracking snippet ahead of it (overwriting the old __cfi_\func:)
- fix the cmpl offset in the caller

func_whatever:
...
cmpl $0x\hash, -FIXED_OFFSET(%rax)
je 1f
ud2
1:
call *%rax
...

This approach is very similar to what we discussed in the past for replacing kCFI with FineIBT if CET is available. Also, it would prevent the need for any jump and would keep the additional padding area in 10 bytes.

Tks,
Joao