]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
hfs/hfsplus: fix u32 overflow in check_and_correct_requested_length
authorTristan Madani <tristan@talencesecurity.com>
Tue, 5 May 2026 11:12:58 +0000 (11:12 +0000)
committerViacheslav Dubeyko <slava@dubeyko.com>
Thu, 7 May 2026 22:07:20 +0000 (15:07 -0700)
check_and_correct_requested_length() compares (off + len) against
node_size using u32 arithmetic.  When the caller passes a large len
value (e.g. from an underflowed subtraction in hfs_brec_remove()),
off + len can wrap past 2^32 and produce a small result, causing the
bounds check to pass when it should fail.

For example, with off=14 and len=0xFFFFFFF2 (underflowed from
data_off - keyoffset - size in hfs_brec_remove), off + len wraps to 6,
which is less than a typical node_size of 512, so the check passes and
the subsequent memmove reads ~4GB past the node buffer.

Fix this by widening the addition to u64 before comparing against
node_size.  This prevents the u32 wrap while keeping the logic
straightforward.

Reported-by: syzbot+6df204b70bf3261691c5@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=6df204b70bf3261691c5
Tested-by: syzbot+6df204b70bf3261691c5@syzkaller.appspotmail.com
Reported-by: syzbot+e76bf3d19b85350571ac@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=e76bf3d19b85350571ac
Tested-by: syzbot+e76bf3d19b85350571ac@syzkaller.appspotmail.com
Fixes: a431930c9bac ("hfs: fix slab-out-of-bounds in hfs_bnode_read()")
Cc: stable@vger.kernel.org
Signed-off-by: Tristan Madani <tristan@talencesecurity.com>
Reviewed-by: Viacheslav Dubeyko <slava@dubeyko.com>
Signed-off-by: Viacheslav Dubeyko <slava@dubeyko.com>
Link: https://lore.kernel.org/r/20260505111300.3592757-2-tristmd@gmail.com
Signed-off-by: Viacheslav Dubeyko <slava@dubeyko.com>
fs/hfs/bnode.c
fs/hfsplus/hfsplus_fs.h

index b0165de7640dbbeaef2bfe351bfdeacaa30fda52..3a8a3878d7b089b8707c4234b5e93b1498ba3d99 100644 (file)
@@ -41,7 +41,7 @@ u32 check_and_correct_requested_length(struct hfs_bnode *node, u32 off, u32 len)
 
        node_size = node->tree->node_size;
 
-       if ((off + len) > node_size) {
+       if ((u64)off + len > node_size) {
                u32 new_len = node_size - off;
 
                pr_err("requested length has been corrected: "
index 3545b8dbf11c58a21f9541a728ee968535164d91..0e4268de9e60e0e1d166dba26c702739bbd72573 100644 (file)
@@ -600,7 +600,7 @@ u32 check_and_correct_requested_length(struct hfs_bnode *node, u32 off, u32 len)
 
        node_size = node->tree->node_size;
 
-       if ((off + len) > node_size) {
+       if ((u64)off + len > node_size) {
                u32 new_len = node_size - off;
 
                pr_err("requested length has been corrected: "