[PATCH] fix : slab-out-of-bounds Read in bch2_sb_members_v2_to_text
From: Abhinav Ananthu
Date: Mon Jun 09 2025 - 03:57:10 EST
BUG: KASAN: slab-out-of-bounds in members_v2_get fs/bcachefs/sb-members.c:68 [inline]
BUG: KASAN: slab-out-of-bounds in bch2_sb_members_v2_to_text+0x1ae/0x310 fs/bcachefs/sb-members.c:347
bcachefs: fix slab-out-of-bounds read in bch2_sb_members_v2_to_text
syzbot reported a slab-out-of-bounds read in bch2_sb_members_v2_to_text().
This function parses superblock member entries from a serialized array,
but did not properly validate the bounds of each entry before accessing it.
When the function iterated over v->entries[], it assumed each
bch_sb_field_members_v2_entry was fully contained within the buffer.
However, if the structure was truncated or malformed, this could lead to
reads beyond the end of the allocated slab, triggering memory safety bugs
under KASAN and potentially leading to undefined behavior.
This patch adds a bounds check to ensure the offset does not exceed the
total size of the entries buffer before accessing each entry. This
prevents out-of-bounds access and resolves the bug.
Reported-by: syzbot+5138f00559ffb3cb3610@xxxxxxxxxxxxxxxxxxxxxxxxx
Closes: https://syzkaller.appspot.com/bug?extid=<5138f00559ffb3cb3610>
Fixes: 1c8dfd7ba50dbbb72113caf4fa7868512cdad2f4("KASAN: slab-out-of-bounds Read in bch2_sb_members_v2_to_text")
Signed-off-by: Abhinav Ananthu <abhinav.ogl@xxxxxxxxx>
---
fs/bcachefs/sb-members.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/fs/bcachefs/sb-members.c b/fs/bcachefs/sb-members.c
index 77809ee23c45..9f137cf7d33e 100644
--- a/fs/bcachefs/sb-members.c
+++ b/fs/bcachefs/sb-members.c
@@ -64,6 +64,12 @@ struct bch_member *bch2_members_v2_get_mut(struct bch_sb *sb, int i)
static struct bch_member members_v2_get(struct bch_sb_field_members_v2 *mi, int i)
{
struct bch_member ret, *p = __bch2_members_v2_get_mut(mi, i);
+ size_t array_size = le32_to_cpu(mi->field.u64s)*8-16;
+ size_t member_bytes = le16_to_cpu(mi->member_bytes);
+ if (i < 0 || (member_bytes && i >= array_size / member_bytes)) {
+ memset(&ret, 0, sizeof(ret));
+ return ret;
+ }
memset(&ret, 0, sizeof(ret));
memcpy(&ret, p, min_t(size_t, le16_to_cpu(mi->member_bytes), sizeof(ret)));
return ret;
--
2.34.1