diff options
author | Ryusuke Konishi <[email protected]> | 2024-09-04 17:13:09 +0900 |
---|---|---|
committer | Andrew Morton <[email protected]> | 2024-09-09 16:47:42 -0700 |
commit | f9c96351aa6718b42a9f42eaf7adce0356bdb5e8 (patch) | |
tree | b98eb5c348804981b003f4ef19c644d5b064ada8 | |
parent | 111b812d3662f3a1b831d19208f83aa711583fe6 (diff) |
nilfs2: fix potential oob read in nilfs_btree_check_delete()
The function nilfs_btree_check_delete(), which checks whether degeneration
to direct mapping occurs before deleting a b-tree entry, causes memory
access outside the block buffer when retrieving the maximum key if the
root node has no entries.
This does not usually happen because b-tree mappings with 0 child nodes
are never created by mkfs.nilfs2 or nilfs2 itself. However, it can happen
if the b-tree root node read from a device is configured that way, so fix
this potential issue by adding a check for that case.
Link: https://lkml.kernel.org/r/[email protected]
Fixes: 17c76b0104e4 ("nilfs2: B-tree based block mapping")
Signed-off-by: Ryusuke Konishi <[email protected]>
Cc: Lizhi Xu <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
-rw-r--r-- | fs/nilfs2/btree.c | 7 |
1 files changed, 5 insertions, 2 deletions
diff --git a/fs/nilfs2/btree.c b/fs/nilfs2/btree.c index dedd3c480842..ef5061bb56da 100644 --- a/fs/nilfs2/btree.c +++ b/fs/nilfs2/btree.c @@ -1659,13 +1659,16 @@ static int nilfs_btree_check_delete(struct nilfs_bmap *btree, __u64 key) int nchildren, ret; root = nilfs_btree_get_root(btree); + nchildren = nilfs_btree_node_get_nchildren(root); + if (unlikely(nchildren == 0)) + return 0; + switch (nilfs_btree_height(btree)) { case 2: bh = NULL; node = root; break; case 3: - nchildren = nilfs_btree_node_get_nchildren(root); if (nchildren > 1) return 0; ptr = nilfs_btree_node_get_ptr(root, nchildren - 1, @@ -1674,12 +1677,12 @@ static int nilfs_btree_check_delete(struct nilfs_bmap *btree, __u64 key) if (ret < 0) return ret; node = (struct nilfs_btree_node *)bh->b_data; + nchildren = nilfs_btree_node_get_nchildren(node); break; default: return 0; } - nchildren = nilfs_btree_node_get_nchildren(node); maxkey = nilfs_btree_node_get_key(node, nchildren - 1); nextmaxkey = (nchildren > 1) ? nilfs_btree_node_get_key(node, nchildren - 2) : 0; |