]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - queue-5.10/nilfs2-fix-failure-to-detect-dat-corruption-in-btree.patch
Fixes for 5.10
[thirdparty/kernel/stable-queue.git] / queue-5.10 / nilfs2-fix-failure-to-detect-dat-corruption-in-btree.patch
CommitLineData
b7ca0ba0
SL
1From 8ebfc9053ad1cff4e1fc4292ac4109168ec7b403 Mon Sep 17 00:00:00 2001
2From: Sasha Levin <sashal@kernel.org>
3Date: Wed, 13 Mar 2024 19:58:26 +0900
4Subject: nilfs2: fix failure to detect DAT corruption in btree and direct
5 mappings
6
7From: Ryusuke Konishi <konishi.ryusuke@gmail.com>
8
9[ Upstream commit f2f26b4a84a0ef41791bd2d70861c8eac748f4ba ]
10
11Patch series "nilfs2: fix kernel bug at submit_bh_wbc()".
12
13This resolves a kernel BUG reported by syzbot. Since there are two
14flaws involved, I've made each one a separate patch.
15
16The first patch alone resolves the syzbot-reported bug, but I think
17both fixes should be sent to stable, so I've tagged them as such.
18
19This patch (of 2):
20
21Syzbot has reported a kernel bug in submit_bh_wbc() when writing file data
22to a nilfs2 file system whose metadata is corrupted.
23
24There are two flaws involved in this issue.
25
26The first flaw is that when nilfs_get_block() locates a data block using
27btree or direct mapping, if the disk address translation routine
28nilfs_dat_translate() fails with internal code -ENOENT due to DAT metadata
29corruption, it can be passed back to nilfs_get_block(). This causes
30nilfs_get_block() to misidentify an existing block as non-existent,
31causing both data block lookup and insertion to fail inconsistently.
32
33The second flaw is that nilfs_get_block() returns a successful status in
34this inconsistent state. This causes the caller __block_write_begin_int()
35or others to request a read even though the buffer is not mapped,
36resulting in a BUG_ON check for the BH_Mapped flag in submit_bh_wbc()
37failing.
38
39This fixes the first issue by changing the return value to code -EINVAL
40when a conversion using DAT fails with code -ENOENT, avoiding the
41conflicting condition that leads to the kernel bug described above. Here,
42code -EINVAL indicates that metadata corruption was detected during the
43block lookup, which will be properly handled as a file system error and
44converted to -EIO when passing through the nilfs2 bmap layer.
45
46Link: https://lkml.kernel.org/r/20240313105827.5296-1-konishi.ryusuke@gmail.com
47Link: https://lkml.kernel.org/r/20240313105827.5296-2-konishi.ryusuke@gmail.com
48Fixes: c3a7abf06ce7 ("nilfs2: support contiguous lookup of blocks")
49Signed-off-by: Ryusuke Konishi <konishi.ryusuke@gmail.com>
50Reported-by: syzbot+cfed5b56649bddf80d6e@syzkaller.appspotmail.com
51Closes: https://syzkaller.appspot.com/bug?extid=cfed5b56649bddf80d6e
52Tested-by: Ryusuke Konishi <konishi.ryusuke@gmail.com>
53Cc: <stable@vger.kernel.org>
54Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
55Signed-off-by: Sasha Levin <sashal@kernel.org>
56---
57 fs/nilfs2/btree.c | 9 +++++++--
58 fs/nilfs2/direct.c | 9 +++++++--
59 2 files changed, 14 insertions(+), 4 deletions(-)
60
61diff --git a/fs/nilfs2/btree.c b/fs/nilfs2/btree.c
62index 65cd599cb2ab6..4905b7cd7bf33 100644
63--- a/fs/nilfs2/btree.c
64+++ b/fs/nilfs2/btree.c
65@@ -724,7 +724,7 @@ static int nilfs_btree_lookup_contig(const struct nilfs_bmap *btree,
66 dat = nilfs_bmap_get_dat(btree);
67 ret = nilfs_dat_translate(dat, ptr, &blocknr);
68 if (ret < 0)
69- goto out;
70+ goto dat_error;
71 ptr = blocknr;
72 }
73 cnt = 1;
74@@ -743,7 +743,7 @@ static int nilfs_btree_lookup_contig(const struct nilfs_bmap *btree,
75 if (dat) {
76 ret = nilfs_dat_translate(dat, ptr2, &blocknr);
77 if (ret < 0)
78- goto out;
79+ goto dat_error;
80 ptr2 = blocknr;
81 }
82 if (ptr2 != ptr + cnt || ++cnt == maxblocks)
83@@ -782,6 +782,11 @@ static int nilfs_btree_lookup_contig(const struct nilfs_bmap *btree,
84 out:
85 nilfs_btree_free_path(path);
86 return ret;
87+
88+ dat_error:
89+ if (ret == -ENOENT)
90+ ret = -EINVAL; /* Notify bmap layer of metadata corruption */
91+ goto out;
92 }
93
94 static void nilfs_btree_promote_key(struct nilfs_bmap *btree,
95diff --git a/fs/nilfs2/direct.c b/fs/nilfs2/direct.c
96index f353101955e3b..7faf8c285d6c9 100644
97--- a/fs/nilfs2/direct.c
98+++ b/fs/nilfs2/direct.c
99@@ -66,7 +66,7 @@ static int nilfs_direct_lookup_contig(const struct nilfs_bmap *direct,
100 dat = nilfs_bmap_get_dat(direct);
101 ret = nilfs_dat_translate(dat, ptr, &blocknr);
102 if (ret < 0)
103- return ret;
104+ goto dat_error;
105 ptr = blocknr;
106 }
107
108@@ -79,7 +79,7 @@ static int nilfs_direct_lookup_contig(const struct nilfs_bmap *direct,
109 if (dat) {
110 ret = nilfs_dat_translate(dat, ptr2, &blocknr);
111 if (ret < 0)
112- return ret;
113+ goto dat_error;
114 ptr2 = blocknr;
115 }
116 if (ptr2 != ptr + cnt)
117@@ -87,6 +87,11 @@ static int nilfs_direct_lookup_contig(const struct nilfs_bmap *direct,
118 }
119 *ptrp = ptr;
120 return cnt;
121+
122+ dat_error:
123+ if (ret == -ENOENT)
124+ ret = -EINVAL; /* Notify bmap layer of metadata corruption */
125+ return ret;
126 }
127
128 static __u64
129--
1302.43.0
131