[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20240313105827.5296-2-konishi.ryusuke@gmail.com>
Date: Wed, 13 Mar 2024 19:58:26 +0900
From: Ryusuke Konishi <konishi.ryusuke@...il.com>
To: Andrew Morton <akpm@...ux-foundation.org>
Cc: syzbot <syzbot+cfed5b56649bddf80d6e@...kaller.appspotmail.com>,
syzkaller-bugs@...glegroups.com,
linux-nilfs@...r.kernel.org,
linux-kernel@...r.kernel.org
Subject: [PATCH 1/2] nilfs2: fix failure to detect DAT corruption in btree and direct mappings
Syzbot has reported a kernel bug in submit_bh_wbc() when writing file
data to a nilfs2 file system whose metadata is corrupted.
There are two flaws involved in this issue.
The first flaw is that when nilfs_get_block() locates a data block
using btree or direct mapping, if the disk address translation routine
nilfs_dat_translate() fails with internal code -ENOENT due to DAT
metadata corruption, it can be passed back to nilfs_get_block(). This
causes nilfs_get_block() to misidentify an existing block as
non-existent, causing both data block lookup and insertion to fail
inconsistently.
The second flaw is that nilfs_get_block() returns a successful status
in this inconsistent state. This causes the caller
__block_write_begin_int() or others to request a read even though the
buffer is not mapped, resulting in a BUG_ON check for the BH_Mapped
flag in submit_bh_wbc() failing.
This fixes the first issue by changing the return value to code
-EINVAL when a conversion using DAT fails with code -ENOENT, avoiding
the conflicting condition that leads to the kernel bug described
above. Here, code -EINVAL indicates that metadata corruption was
detected during the block lookup, which will be properly handled as a
file system error and converted to -EIO when passing through the
nilfs2 bmap layer.
Signed-off-by: Ryusuke Konishi <konishi.ryusuke@...il.com>
Reported-by: syzbot+cfed5b56649bddf80d6e@...kaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=cfed5b56649bddf80d6e
Fixes: c3a7abf06ce7 ("nilfs2: support contiguous lookup of blocks")
Tested-by: Ryusuke Konishi <konishi.ryusuke@...il.com>
Cc: stable@...r.kernel.org
---
fs/nilfs2/btree.c | 9 +++++++--
fs/nilfs2/direct.c | 9 +++++++--
2 files changed, 14 insertions(+), 4 deletions(-)
diff --git a/fs/nilfs2/btree.c b/fs/nilfs2/btree.c
index 13592e82eaf6..65659fa0372e 100644
--- a/fs/nilfs2/btree.c
+++ b/fs/nilfs2/btree.c
@@ -724,7 +724,7 @@ static int nilfs_btree_lookup_contig(const struct nilfs_bmap *btree,
dat = nilfs_bmap_get_dat(btree);
ret = nilfs_dat_translate(dat, ptr, &blocknr);
if (ret < 0)
- goto out;
+ goto dat_error;
ptr = blocknr;
}
cnt = 1;
@@ -743,7 +743,7 @@ static int nilfs_btree_lookup_contig(const struct nilfs_bmap *btree,
if (dat) {
ret = nilfs_dat_translate(dat, ptr2, &blocknr);
if (ret < 0)
- goto out;
+ goto dat_error;
ptr2 = blocknr;
}
if (ptr2 != ptr + cnt || ++cnt == maxblocks)
@@ -781,6 +781,11 @@ static int nilfs_btree_lookup_contig(const struct nilfs_bmap *btree,
out:
nilfs_btree_free_path(path);
return ret;
+
+ dat_error:
+ if (ret == -ENOENT)
+ ret = -EINVAL; /* Notify bmap layer of metadata corruption */
+ goto out;
}
static void nilfs_btree_promote_key(struct nilfs_bmap *btree,
diff --git a/fs/nilfs2/direct.c b/fs/nilfs2/direct.c
index 4c85914f2abc..893ab36824cc 100644
--- a/fs/nilfs2/direct.c
+++ b/fs/nilfs2/direct.c
@@ -66,7 +66,7 @@ static int nilfs_direct_lookup_contig(const struct nilfs_bmap *direct,
dat = nilfs_bmap_get_dat(direct);
ret = nilfs_dat_translate(dat, ptr, &blocknr);
if (ret < 0)
- return ret;
+ goto dat_error;
ptr = blocknr;
}
@@ -79,7 +79,7 @@ static int nilfs_direct_lookup_contig(const struct nilfs_bmap *direct,
if (dat) {
ret = nilfs_dat_translate(dat, ptr2, &blocknr);
if (ret < 0)
- return ret;
+ goto dat_error;
ptr2 = blocknr;
}
if (ptr2 != ptr + cnt)
@@ -87,6 +87,11 @@ static int nilfs_direct_lookup_contig(const struct nilfs_bmap *direct,
}
*ptrp = ptr;
return cnt;
+
+ dat_error:
+ if (ret == -ENOENT)
+ ret = -EINVAL; /* Notify bmap layer of metadata corruption */
+ return ret;
}
static __u64
--
2.34.1
Powered by blists - more mailing lists