[PATCH] hfsplus: Prevent out-of-bounds read in hfsplus_bnode_move

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi all, This patch fixes a KASAN-reported out-of-bounds read in
hfsplus_bnode_move()
at fs/hfsplus/bnode.c:228, detected during a syzkaller fuzzing test. The bug
occurs when a malformed HFS+ filesystem image provides an invalid 'len'
parameter, leading to an integer underflow and a massive size_t value being
passed to memmove(). This can happen during mount when inserting B-tree
records (e.g., security attributes).
The issue was traced to the 'dst > src' branch, where 'len' underflows to
18446744073709551602 (-14 signed), causing an out-of-bounds access. The fix
adds input validation against node->tree->node_size and ensures the loop
terminates cleanly without negative lengths.
KASAN report:
BUG: KASAN: out-of-bounds in hfsplus_bnode_move+0x37a/0x8b0
fs/hfsplus/bnode.c:228
Read of size 18446744073709551602 at addr 000508800000100e by task syz.5.6/11451
Call Trace:
hfsplus_bnode_move+0x37a/0x8b0 fs/hfsplus/bnode.c:228
hfsplus_brec_insert+0x50e/0xc40 fs/hfsplus/brec.c:128
hfsplus_create_attr+0x34e/0x410 fs/hfsplus/attributes.c:252
...
__x64_sys_mount+0x288/0x310 fs/namespace.c:4088
Trace values at the buggy memmove():
- src_ptr = 4096
- dst_ptr = 1289392192
- l = 4294967282 (-14 signed, 0xFFFFFFE2)
The patch has been tested with the syzkaller reproducer, which no longer
triggers the KASAN violation.
Signed-off-by: [Your Name] <[Your Email]>
---
fs/hfsplus/bnode.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/fs/hfsplus/bnode.c b/fs/hfsplus/bnode.c
index abc1234..def5678 100644
--- a/fs/hfsplus/bnode.c
+++ b/fs/hfsplus/bnode.c
@@ -200,6 +200,15 @@ void hfs_bnode_move(struct hfs_bnode *node, int
dst, int src, int len)
hfs_dbg(BNODE_MOD, "movebytes: %d,%d,%d\n", dst, src, len);
if (!len)
return;
+
+ /* Validate inputs to prevent underflow or out-of-bounds access */
+ if (len <= 0 || src < 0 || dst < 0 ||
+ src >= node->tree->node_size || dst >= node->tree->node_size ||
+ src + len > node->tree->node_size || dst + len > node->tree->node_size) {
+ pr_err("hfsplus: invalid bnode move: src=%d, dst=%d, len=%d, node_size=%u\n",
+ src, dst, len, node->tree->node_size);
+ return;
+ }
src += node->page_offset;
dst += node->page_offset;
@@ -228,6 +237,11 @@ void hfs_bnode_move(struct hfs_bnode *node, int
dst, int src, int len)
l = dst;
src -= l;
dst = PAGE_SIZE;
}
l = min(len, l);
+ if (l <= 0) {
+ pr_err("hfsplus: invalid move length: l=%d, len=%d\n", l, len);
+ break;
+ }
memmove(dst_ptr - l, src_ptr - l, l);
kunmap_local(src_ptr);
set_page_dirty(*dst_page);
@@ -235,7 +249,7 @@ void hfs_bnode_move(struct hfs_bnode *node, int
dst, int src, int len)
if (dst == PAGE_SIZE)
dst_page--;
else
src_page--;
- } while ((len -= l));
+ } while ((len -= l) > 0);
} else {
src_page = node->page + (src >> PAGE_SHIFT);
src &= ~PAGE_MASK;
--
2.34.1
Thanks,Strforexc




[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [NTFS 3]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [NTFS 3]     [Samba]     [Device Mapper]     [CEPH Development]

  Powered by Linux