[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250217183827.41da5f52@pumpkin>
Date: Mon, 17 Feb 2025 18:38:27 +0000
From: David Laight <david.laight.linux@...il.com>
To: Peter Zijlstra <peterz@...radead.org>
Cc: Kees Cook <kees@...nel.org>, Andrew Cooper <andrew.cooper3@...rix.com>,
jannh@...gle.com, jmill@....edu, joao@...rdrivepizza.com,
linux-hardening@...r.kernel.org, linux-kernel@...r.kernel.org,
luto@...nel.org, samitolvanen@...gle.com, scott.d.constable@...el.com,
x86@...nel.org
Subject: Re: [RFC] Circumventing FineIBT Via Entrypoints
On Mon, 17 Feb 2025 14:13:21 +0100
Peter Zijlstra <peterz@...radead.org> 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 <peterz@...radead.org> 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
Powered by blists - more mailing lists