Re: [PATCH 0/7] CFI for ARM32 using LLVM

Linus Walleij
2024-02-27T14:16:19Z

On Tue, Feb 27, 2024 at 5:21 AM Nathan Chancellor <nathan@kernel.org> wrote:

> I went to take this for a spin in QEMU using the virt platform. When
> booting via EFI using edk2 in a manner similar to [1] but with 32-bit
> ARM virtual firmware (which I implemented in our boot utility scripts
> at [2]), I get a panic on boot even with CONFIG_CFI_PERMISSIVE=y:
(...)
> [ 0.247907] PC is at efi_call_rts+0x30c/0x330
> [ 0.248158] LR is at efi_call_rts+0x1c/0x330
(...)
> [ 0.257986] efi_call_rts from process_scheduled_works+0x298/0x3d0
(...)

> It is not immediately obvious what EFI runtime call is triggering this,

Not to me either...

> I assume that has something to do with the lack of traps due to the
> generic implementation. I'll see if I can dig more into this tomorrow
> but don't hesitate to jump in too :P

I think it's Ard Biesheuvel territory, he's always on top of EFI stuff :)

What I see is that efi_call_rts() calls
arch_efi_call_virt_setup/efi_call_virt_save_flags/
efi_call_virt (dispatch to arch_efi_call_virt)
/arch_efi_call_virt_teardown

arch_efi_call_virt_setup and arch_efi_call_virt_teardown
is there. So the default becomes arch_efi_call_virt from
include/linux/efi.h which is:

#define arch_efi_call_virt(p, f, args...) ((p)->f(args))

CFI is not going to like that because it just dereferences this random
function pointer and calls it, I suppose?

I *think* that in arch/arm/include/asm/efi.h we need something
like...

#undef arch_efi_call_virt
#define arch_efi_call_virt(p, f, args...) \
__efi_arm_wrapper((p)->f, #f, args)

Then __efi_arm_wrapper() can be a static inline to call the
function f, with the right arguments, tagged __nocfi?
The details beats me, I'm not good with variadic functions,
but if the solution is not obvious to you or Ard I can try to
dig into it.

Yours,
Linus Walleij