[PATCH 3/3] nilfs2: fix potential oob read in nilfs_btree_check_delete()

From: Ryusuke Konishi
Date: Wed Sep 04 2024 - 04:21:23 EST


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.

Signed-off-by: Ryusuke Konishi <konishi.ryusuke@xxxxxxxxx>
Fixes: 17c76b0104e4 ("nilfs2: B-tree based block mapping")
---
fs/nilfs2/btree.c | 7 +++++--
1 file 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;
--
2.43.0