[PATCH] efistub/x86: Fix the size type of the Apple properties protocol

From: Nicolas Brainez

Date: Mon Sep 28 2026 - 03:37:23 EST


The size argument of the get(), set() and get_all() methods of the
Apple device properties protocol is a UINTN, not a u32. The reverse
engineered declaration added by commit 58c5475aba67 ("x86/efi: Retrieve
and assign Apple device properties") uses u32, and
retrieve_apple_device_properties() passes the address of a u32 on the
stack to get_all(). 64-bit Apple firmware writes 8 bytes through that
pointer, so the upper half of the store lands on whatever the compiler
placed next to the variable. OpenCore's
Include/Apple/Protocol/DevicePathPropertyDatabase.h declares the same
methods with UINTN, and a u32 canary placed right after the u32 size
is zeroed by both get_all() calls on a Mac mini 2018 (Macmini8,1).

With clang and CONFIG_EFI_MIXED=n, the neighbour is the protocol
pointer p: the first get_all() call zeroes its low half, the second
call jumps through the corrupted pointer, and the machine powers off
before printing anything. A GCC build leaves padding in that slot, and
a clang build with CONFIG_EFI_MIXED=y places the setup_data pointer
there; neither crashes, so the bug went unnoticed since 2016. Talos
Linux, which builds its kernel with clang, reported it on several Mac
generations.

Declare the size as unsigned long, as the stub does for every other
UINTN. No mixed mode argument mapping is needed: 32-bit firmware
writes the low 32 bits of the zero-initialised value, and the upper
half stays zero across both calls.

Tested on a Macmini8,1 with v6.18.51, clang 22.1.8 and LLD,
CONFIG_EFI_MIXED=n, booted as EFI/BOOT/BOOTX64.EFI: the machine powers
off without the patch and boots with it. Builds with clang and GCC,
with and without CONFIG_EFI_MIXED. Mixed mode was not boot tested (no
32-bit EFI Mac at hand).

Claude Code assisted with reading the disassembly, writing the debug
patches and drafting this changelog; the tests ran on the hardware
above.

Fixes: 58c5475aba67 ("x86/efi: Retrieve and assign Apple device properties")
Cc: stable@xxxxxxxxxxxxxxx
Cc: Lukas Wunner <lukas@xxxxxxxxx>
Link: https://github.com/siderolabs/talos/issues/13231
Link: https://github.com/siderolabs/talos/issues/13579
Assisted-by: LLM
Signed-off-by: Nicolas Brainez <nicolas@xxxxxxxxxxx>
---
drivers/firmware/efi/libstub/efistub.h | 8 +++++---
drivers/firmware/efi/libstub/x86-stub.c | 2 +-
2 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h
index fd91fc15e..1002c17a8 100644
--- a/drivers/firmware/efi/libstub/efistub.h
+++ b/drivers/firmware/efi/libstub/efistub.h
@@ -838,15 +838,17 @@ union apple_properties_protocol {
unsigned long version;
efi_status_t (__efiapi *get)(apple_properties_protocol_t *,
struct efi_dev_path *,
- efi_char16_t *, void *, u32 *);
+ efi_char16_t *, void *,
+ unsigned long *);
efi_status_t (__efiapi *set)(apple_properties_protocol_t *,
struct efi_dev_path *,
- efi_char16_t *, void *, u32);
+ efi_char16_t *, void *,
+ unsigned long);
efi_status_t (__efiapi *del)(apple_properties_protocol_t *,
struct efi_dev_path *,
efi_char16_t *);
efi_status_t (__efiapi *get_all)(apple_properties_protocol_t *,
- void *buffer, u32 *);
+ void *buffer, unsigned long *);
};
struct {
u32 version;
diff --git a/drivers/firmware/efi/libstub/x86-stub.c b/drivers/firmware/efi/libstub/x86-stub.c
index cef32e2c8..87e142cae 100644
--- a/drivers/firmware/efi/libstub/x86-stub.c
+++ b/drivers/firmware/efi/libstub/x86-stub.c
@@ -158,7 +158,7 @@ static void retrieve_apple_device_properties(struct boot_params *boot_params)
efi_guid_t guid = APPLE_PROPERTIES_PROTOCOL_GUID;
struct setup_data *data, *new;
efi_status_t status;
- u32 size = 0;
+ unsigned long size = 0;
apple_properties_protocol_t *p;

status = efi_bs_call(locate_protocol, &guid, NULL, (void **)&p);
--
2.47.3