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

efi/runtime-wrappers: Keep track of the efi_runtime_lock owner

The EFI runtime wrappers use a file local semaphore to serialize access
to the EFI runtime services. This means that any calls to the arch
wrappers around the runtime services will also be serialized, removing
the need for redundant locking.

For robustness, add a facility that allows those arch wrappers to assert
that the semaphore was taken by the current task.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Acked-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>

authored by

Ard Biesheuvel and committed by
Catalin Marinas
a2860501 40374d30

+18 -1
+16 -1
drivers/firmware/efi/runtime-wrappers.c
··· 202 202 */ 203 203 static DEFINE_SEMAPHORE(efi_runtime_lock, 1); 204 204 205 + static struct task_struct *efi_runtime_lock_owner; 206 + 205 207 /* 206 208 * Expose the EFI runtime lock to the UV platform 207 209 */ ··· 220 218 const union efi_rts_args *args = efi_rts_work.args; 221 219 efi_status_t status = EFI_NOT_FOUND; 222 220 unsigned long flags; 221 + 222 + efi_runtime_lock_owner = current; 223 223 224 224 arch_efi_call_virt_setup(); 225 225 flags = efi_call_virt_save_flags(); ··· 314 310 315 311 efi_rts_work.status = status; 316 312 complete(&efi_rts_work.efi_rts_comp); 313 + efi_runtime_lock_owner = NULL; 317 314 } 318 315 319 316 static efi_status_t __efi_queue_work(enum efi_rts_ids id, ··· 449 444 if (down_trylock(&efi_runtime_lock)) 450 445 return EFI_NOT_READY; 451 446 447 + efi_runtime_lock_owner = current; 452 448 status = efi_call_virt_pointer(efi.runtime, set_variable, name, vendor, 453 449 attr, data_size, data); 450 + efi_runtime_lock_owner = NULL; 454 451 up(&efi_runtime_lock); 455 452 return status; 456 453 } ··· 488 481 if (down_trylock(&efi_runtime_lock)) 489 482 return EFI_NOT_READY; 490 483 484 + efi_runtime_lock_owner = current; 491 485 status = efi_call_virt_pointer(efi.runtime, query_variable_info, attr, 492 486 storage_space, remaining_space, 493 487 max_variable_size); 488 + efi_runtime_lock_owner = NULL; 494 489 up(&efi_runtime_lock); 495 490 return status; 496 491 } ··· 518 509 return; 519 510 } 520 511 512 + efi_runtime_lock_owner = current; 521 513 arch_efi_call_virt_setup(); 522 514 efi_rts_work.efi_rts_id = EFI_RESET_SYSTEM; 523 515 arch_efi_call_virt(efi.runtime, reset_system, reset_type, status, 524 516 data_size, data); 525 517 arch_efi_call_virt_teardown(); 526 - 518 + efi_runtime_lock_owner = NULL; 527 519 up(&efi_runtime_lock); 528 520 } 529 521 ··· 597 587 } 598 588 599 589 #endif 590 + 591 + void efi_runtime_assert_lock_held(void) 592 + { 593 + WARN_ON(efi_runtime_lock_owner != current); 594 + }
+2
include/linux/efi.h
··· 1126 1126 extern void efi_call_virt_check_flags(unsigned long flags, const void *caller); 1127 1127 extern unsigned long efi_call_virt_save_flags(void); 1128 1128 1129 + void efi_runtime_assert_lock_held(void); 1130 + 1129 1131 enum efi_secureboot_mode { 1130 1132 efi_secureboot_mode_unset, 1131 1133 efi_secureboot_mode_unknown,