[PATCH] ihex: reject firmware images smaller than a single record
From: Priyanka Mani
Date: Fri Oct 09 2026 - 01:05:13 EST
ihex_validate_fw() computes the end of the record area as
end = (const void *)&fw->data[fw->size - sizeof(*end)];
Both fw->size and sizeof(*end) are size_t, so when the firmware image
is smaller than a single struct ihex_binrec (6 bytes) the subtraction
wraps around. 'end' then points far beyond the buffer, the
for (; rec <= end; rec = __ihex_next_binrec(rec))
loop condition is satisfied, and the body dereferences 'rec' while
walking records that do not exist.
This is trivially reachable from userspace via the sysfs firmware
fallback: loading an empty image (write "1" then "0" to .../loading
without writing any data) leaves fw->size == 0 and fw->data == NULL, so
the first ihex_binrec_size() reads rec->len at NULL + 4:
Oops: general protection fault, probably for non-canonical address ...
KASAN: null-ptr-deref in range [0x0000000000000000-0x0000000000000007]
RIP: 0010:ihex_binrec_size include/linux/ihex.h:26 [inline]
RIP: 0010:__ihex_next_binrec include/linux/ihex.h:35 [inline]
RIP: 0010:ihex_validate_fw include/linux/ihex.h:54 [inline]
RIP: 0010:request_ihex_firmware include/linux/ihex.h:74 [inline]
RIP: 0010:emi26_load_firmware drivers/usb/misc/emi26.c:86 [inline]
RIP: 0010:emi26_probe+0x283/0x1690 drivers/usb/misc/emi26.c:232
A valid ihex image must contain at least the mandatory zero-length
terminating record, so anything smaller than sizeof(struct ihex_binrec)
cannot be valid. Reject it up front before the wrapping subtraction.
Fixes: f1485f3deb89 ("ihex: request_ihex_firmware() function to load and validate firmware")
Reported-by: syzbot+baf3cbba7dd980984f0d@xxxxxxxxxxxxxxxxxxxxxxxxx
Closes: https://syzkaller.appspot.com/bug?extid=baf3cbba7dd980984f0d
Signed-off-by: Priyanka Mani <priyankamani2100@xxxxxxxxx>
---
include/linux/ihex.h | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/include/linux/ihex.h b/include/linux/ihex.h
index b824877e6d1b..61f1df4f7819 100644
--- a/include/linux/ihex.h
+++ b/include/linux/ihex.h
@@ -48,6 +48,16 @@ static inline int ihex_validate_fw(const struct firmware *fw)
{
const struct ihex_binrec *end, *rec;
+ /*
+ * The firmware must be large enough to hold at least the mandatory
+ * zero-length terminating record. Without this check a short (e.g.
+ * empty) image makes the fw->size - sizeof(*end) subtraction below
+ * wrap around, yielding a bogus 'end' pointer and an out-of-bounds
+ * walk over the records.
+ */
+ if (fw->size < sizeof(*end))
+ return -EINVAL;
+
rec = (const void *)fw->data;
end = (const void *)&fw->data[fw->size - sizeof(*end)];
--
2.43.0