From 21a77e08921a13ac4adc523a136d829333a854f1 Mon Sep 17 00:00:00 2001 From: Chris Webb Date: Thu, 4 Jul 2024 12:33:15 +0100 Subject: [PATCH] fix(guid-partition): fix unaligned access in load_mbr_header() load_mbr_header() casts an unaligned pointer to (mbr_entry_t *) then dereferences struct members with non-trivial alignment requirements. This causes a bl2 with BOOT_DEVICE=emmc to hang when compiled with clang 18.1.5, although it works when compiled with gcc 14.1.0. Presumably gcc's -mstrict-align papers over the undefined behaviour whereas clang's doesn't. Replace the unaligned cast with a safe memcpy() into an mbr_entry_t. Signed-off-by: Chris Webb Change-Id: Iefd4dac7e390ddf369b8dacdbaf14e599118f91d --- drivers/partition/partition.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/partition/partition.c b/drivers/partition/partition.c index 888a82430..c4f749352 100644 --- a/drivers/partition/partition.c +++ b/drivers/partition/partition.c @@ -50,7 +50,7 @@ static int load_mbr_header(uintptr_t image_handle, mbr_entry_t *mbr_entry) { size_t bytes_read; int result; - mbr_entry_t *tmp; + mbr_entry_t tmp; assert(mbr_entry != NULL); /* MBR partition table is in LBA0. */ @@ -73,19 +73,19 @@ static int load_mbr_header(uintptr_t image_handle, mbr_entry_t *mbr_entry) return -ENOENT; } - tmp = (mbr_entry_t *)(&mbr_sector[MBR_PRIMARY_ENTRY_OFFSET]); + memcpy(&tmp, mbr_sector + MBR_PRIMARY_ENTRY_OFFSET, sizeof(tmp)); - if (tmp->first_lba != 1) { + if (tmp.first_lba != 1) { VERBOSE("MBR header may have an invalid first LBA\n"); return -EINVAL; } - if ((tmp->sector_nums == 0) || (tmp->sector_nums == UINT32_MAX)) { + if ((tmp.sector_nums == 0) || (tmp.sector_nums == UINT32_MAX)) { VERBOSE("MBR header entry has an invalid number of sectors\n"); return -EINVAL; } - memcpy(mbr_entry, tmp, sizeof(mbr_entry_t)); + memcpy(mbr_entry, &tmp, sizeof(mbr_entry_t)); return 0; }