Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

efi: Add missing __nocfi annotations to runtime wrappers

The EFI runtime wrappers are a sandbox for calling into EFI runtime
services, which are invoked using indirect calls. When running with kCFI
enabled, the compiler will require the target of any indirect call to be
type annotated.

Given that the EFI runtime services prototypes and calling convention
are governed by the EFI spec, not the Linux kernel, adding such type
annotations for firmware routines is infeasible, and so the compiler
must be informed that prototype validation should be omitted.

Add the __nocfi annotation at the appropriate places in the EFI runtime
wrapper code to achieve this.

Note that this currently only affects 32-bit ARM, given that other
architectures that support both kCFI and EFI use an asm wrapper to call
EFI runtime services, and this hides the indirect call from the
compiler.

Fixes: 1a4fec49efe5 ("ARM: 9392/2: Support CLANG CFI")
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Tested-by: Nathan Chancellor <nathan@kernel.org>
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>

+6 -7
+6 -7
drivers/firmware/efi/runtime-wrappers.c
··· 213 213 * Calls the appropriate efi_runtime_service() with the appropriate 214 214 * arguments. 215 215 */ 216 - static void efi_call_rts(struct work_struct *work) 216 + static void __nocfi efi_call_rts(struct work_struct *work) 217 217 { 218 218 const union efi_rts_args *args = efi_rts_work.args; 219 219 efi_status_t status = EFI_NOT_FOUND; ··· 435 435 return status; 436 436 } 437 437 438 - static efi_status_t 438 + static efi_status_t __nocfi 439 439 virt_efi_set_variable_nb(efi_char16_t *name, efi_guid_t *vendor, u32 attr, 440 440 unsigned long data_size, void *data) 441 441 { ··· 469 469 return status; 470 470 } 471 471 472 - static efi_status_t 472 + static efi_status_t __nocfi 473 473 virt_efi_query_variable_info_nb(u32 attr, u64 *storage_space, 474 474 u64 *remaining_space, u64 *max_variable_size) 475 475 { ··· 499 499 return status; 500 500 } 501 501 502 - static void virt_efi_reset_system(int reset_type, 503 - efi_status_t status, 504 - unsigned long data_size, 505 - efi_char16_t *data) 502 + static void __nocfi 503 + virt_efi_reset_system(int reset_type, efi_status_t status, 504 + unsigned long data_size, efi_char16_t *data) 506 505 { 507 506 if (down_trylock(&efi_runtime_lock)) { 508 507 pr_warn("failed to invoke the reset_system() runtime service:\n"