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