On Mon, 17 Feb 2025 14:13:21 +0100 Peter Zijlstra <[email protected]> wrote:
> On Mon, Feb 17, 2025 at 01:06:29PM +0000, David Laight wrote: > > On Sat, 15 Feb 2025 22:07:29 +0100 > > Peter Zijlstra <[email protected]> wrote: > > > > > On Fri, Feb 14, 2025 at 10:57:51AM +0100, Peter Zijlstra wrote: > > > > On Thu, Feb 13, 2025 at 12:53:28PM -0800, Kees Cook wrote: > > > > > > > > > Right, the "if they can control a function pointer" is the part I'm > > > > > focusing on. This attack depends on making an indirect call with a > > > > > controlled pointer. Non-FineIBT CFI will protect against that step, > > > > > so I think this is only an issue for IBT-only and FineIBT, but not CFI > > > > > nor CFI+IBT. > > > > > > > > Yes, the whole caller side validation should stop this. > > > > > > And I think we can retro-fit that in FineIBT. Notably the current call > > > sites look like: > > > > > > 0000000000000060 <fineibt_caller>: > > > 60: 41 ba 78 56 34 12 mov $0x12345678,%r10d > > > 66: 49 83 eb 10 sub $0x10,%r11 > > > 6a: 0f 1f 40 00 nopl 0x0(%rax) > > > 6e: 41 ff d3 call *%r11 > > > 71: 0f 1f 00 nopl (%rax) > > > > I tried building a fineibt kernel (without LTO) and that isn't what I > > see in the object files. > > (I not trying to run it, just do some analysis.) > > While the call targets have a 16 byte preamble it is all nops apart > > from a final 'mov $hash,%rax'. > > The call site loads $-hash and adds -4(target) and checks for zero. > > It is too small to be patchable into the above. > > Right after that comes the retpoline site, which is another 6 bytes > (assuming you have indirect-branch-cs-prefix, which all kCFI enabled > compilers should have). I'm building with clang 18.1.18 - should be new enough. I may not have retpolines enabled, a typical call site is (from vmlinux.o): 3628: 48 89 c6 mov %rax,%rsi 362b: 41 ba 83 c5 2c af mov $0xaf2cc583,%r10d 3631: 44 03 51 fc add -0x4(%rcx),%r10d 3635: 74 02 je 3639 <vc_handle_exitcode+0x739> 3637: 0f 0b ud2 3639: ff d1 call *%rcx 363b: 4c 89 f6 mov %r14,%rsi That one has three targets, one is: 000000000008a5c0 <__cfi_kvm_sev_es_hcall_prepare>: 8a5c0: 90 nop 8a5c1: 90 nop 8a5c2: 90 nop 8a5c3: 90 nop 8a5c4: 90 nop 8a5c5: 90 nop 8a5c6: 90 nop 8a5c7: 90 nop 8a5c8: 90 nop 8a5c9: 90 nop 8a5ca: 90 nop 8a5cb: b8 7d 3a d3 50 mov $0x50d33a7d,%eax 000000000008a5d0 <kvm_sev_es_hcall_prepare>: 8a5d0: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1) 8a5d1: R_X86_64_NONE __fentry__-0x4 8a5d5: 48 8b 46 28 mov 0x28(%rsi),%rax I think that if I had endbra enabled objtool would remove them from non-exported functions whose address isn't taken. But none of the 'mov $hash,%eax' get removed - and I think they should suffer the same fate. I'm not sure why I don't have endbra though. I did remove a lot of the mitigations from the config I copied to add the caller side fineibt (I think) hash checks. After all this is a local system I want to run fast, not a semi-public one someone might try to hack. > You need to go read arch/x86/kernel/alternative.c search for FineIBT I found some stuff in one of the docs. Didn't read that bit of source. What I was hoping to obtain was a list of the valid target functions for each indirect call site. With the stack offset of the call (which objtool knows) and a lot of 'shaking' an real estimate of max stack depth can be determined. (and recursive loops found.) David
