[PATCH RFC] ihex: Fix integer underflow and out-of-bounds read
"syzbot" <[email protected]> Mon, 3 Aug 2026 09:08:10 +0000 (UTC)
| Newsgroups | dev.linux.lists.syzbot |
|---|---|
| Message-ID | <[email protected]> |
When loading a 0-byte firmware, ihex_validate_fw() calculates the end
pointer by subtracting sizeof(*end) from fw->size. Since fw->size is 0,
this results in an integer underflow, making end a huge pointer far past
the end of the buffer. The validation loop then executes with a NULL rec
pointer, leading to a NULL pointer dereference when ihex_binrec_size()
attempts to read rec->len.
Oops: general protection fault, probably for non-canonical address
0xdffffc0000000000: 0000 [#1] SMP KASAN NOPTI
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
Additionally, if a firmware file consists only of the 6-byte EOF record,
ihex_validate_fw() successfully validates it. However, when iterating over
the records, ihex_next_binrec() blindly advances past the current record.
If the current record is the EOF record, __ihex_next_binrec() advances the
pointer past the end of the firmware buffer, and the subsequent read of
rec->len results in an out-of-bounds read.
Fix both issues by adding a size check in ihex_validate_fw() to ensure the
firmware is at least large enough to contain a single IHEX record, and by
updating ihex_next_binrec() to check the current record's length before
advancing so it returns NULL immediately when encountering the EOF record.
Fixes: bacfe09dd754 ("ihex.h: binary representation of ihex records")
Assisted-by: Gemini:gemini-3.5-flash Gemini:gemini-3.1-pro-preview syzbot
Reported-by: [email protected]
Closes: https://syzkaller.appspot.com/bug?extid=baf3cbba7dd980984f0d
Link: https://syzkaller.appspot.com/ai_job?id=a0c10e66-d30e-44f1-8ad1-c7f25ff69b04
To: <[email protected]>
To: "David Woodhouse" <[email protected]>
---
diff --git a/include/linux/ihex.h b/include/linux/ihex.h
index b824877e6..4ee4b5960 100644
--- a/include/linux/ihex.h
+++ b/include/linux/ihex.h
@@ -38,9 +38,13 @@ __ihex_next_binrec(const struct ihex_binrec *rec)
static inline const struct ihex_binrec *
ihex_next_binrec(const struct ihex_binrec *rec)
{
- rec = __ihex_next_binrec(rec);
+ const struct ihex_binrec *next;
- return be16_to_cpu(rec->len) ? rec : NULL;
+ if (!be16_to_cpu(rec->len))
+ return NULL;
+
+ next = __ihex_next_binrec(rec);
+ return be16_to_cpu(next->len) ? next : NULL;
}
/* Check that ihex_next_binrec() won't take us off the end of the image... */
@@ -48,6 +52,9 @@ static inline int ihex_validate_fw(const struct firmware *fw)
{
const struct ihex_binrec *end, *rec;
+ if (fw->size < sizeof(*end))
+ return -EINVAL;
+
rec = (const void *)fw->data;
end = (const void *)&fw->data[fw->size - sizeof(*end)];
base-commit: 075b74841bd0065a3bda3440873c747938e69b68
--
This is an AI-generated patch subject to moderation.
Reply with '#syz upstream' to Sign-off the patch as a human author
and send it to the upstream kernel mailing lists.
Reply with '#syz reject' to reject it ('#syz unreject' to undo).
See https://goo.gle/syzbot-ai-patches for information about AI-generated patches.
You can comment on the patch as usual, syzbot will try to address
the comments and send a new version of the patch if necessary.
syzbot engineers can be reached at [email protected].