| From 37c0eb05cdcc64c28d31c4ebd300f14d5239d05e Mon Sep 17 00:00:00 2001 |
| From: Daniel Axtens <dja@axtens.net> |
| Date: Mon, 18 Jan 2021 16:49:44 +1100 |
| Subject: [PATCH] fs/nilfs2: Don't search children if provided number is too |
| large |
| |
| NILFS2 reads the number of children a node has from the node. Unfortunately, |
| that's not trustworthy. Check if it's beyond what the filesystem permits and |
| reject it if so. |
| |
| This blocks some OOB reads. I'm not sure how controllable the read is and what |
| could be done with invalidly read data later on. |
| |
| Signed-off-by: Daniel Axtens <dja@axtens.net> |
| Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com> |
| Signed-off-by: Stefan SΓΈrensen <stefan.sorensen@spectralink.com> |
| --- |
| grub-core/fs/nilfs2.c | 38 +++++++++++++++++++++++--------------- |
| 1 file changed, 23 insertions(+), 15 deletions(-) |
| |
| diff --git a/grub-core/fs/nilfs2.c b/grub-core/fs/nilfs2.c |
| index fee2242..43ac1ad 100644 |
| --- a/grub-core/fs/nilfs2.c |
| +++ b/grub-core/fs/nilfs2.c |
| @@ -416,14 +416,34 @@ grub_nilfs2_btree_node_get_key (struct grub_nilfs2_btree_node *node, |
| } |
| |
| static inline int |
| -grub_nilfs2_btree_node_lookup (struct grub_nilfs2_btree_node *node, |
| +grub_nilfs2_btree_node_nchildren_max (struct grub_nilfs2_data *data, |
| + struct grub_nilfs2_btree_node *node) |
| +{ |
| + int node_children_max = ((NILFS2_BLOCK_SIZE (data) - |
| + sizeof (struct grub_nilfs2_btree_node) - |
| + NILFS_BTREE_NODE_EXTRA_PAD_SIZE) / |
| + (sizeof (grub_uint64_t) + sizeof (grub_uint64_t))); |
| + |
| + return (node->bn_flags & NILFS_BTREE_NODE_ROOT) ? 3 : node_children_max; |
| +} |
| + |
| +static inline int |
| +grub_nilfs2_btree_node_lookup (struct grub_nilfs2_data *data, |
| + struct grub_nilfs2_btree_node *node, |
| grub_uint64_t key, int *indexp) |
| { |
| grub_uint64_t nkey; |
| int index, low, high, s; |
| |
| low = 0; |
| + |
| high = grub_le_to_cpu16 (node->bn_nchildren) - 1; |
| + if (high >= grub_nilfs2_btree_node_nchildren_max (data, node)) |
| + { |
| + grub_error (GRUB_ERR_BAD_FS, "too many children"); |
| + return 0; |
| + } |
| + |
| index = 0; |
| s = 0; |
| while (low <= high) |
| @@ -459,18 +479,6 @@ grub_nilfs2_btree_node_lookup (struct grub_nilfs2_btree_node *node, |
| return s == 0; |
| } |
| |
| -static inline int |
| -grub_nilfs2_btree_node_nchildren_max (struct grub_nilfs2_data *data, |
| - struct grub_nilfs2_btree_node *node) |
| -{ |
| - int node_children_max = ((NILFS2_BLOCK_SIZE (data) - |
| - sizeof (struct grub_nilfs2_btree_node) - |
| - NILFS_BTREE_NODE_EXTRA_PAD_SIZE) / |
| - (sizeof (grub_uint64_t) + sizeof (grub_uint64_t))); |
| - |
| - return (node->bn_flags & NILFS_BTREE_NODE_ROOT) ? 3 : node_children_max; |
| -} |
| - |
| static inline grub_uint64_t * |
| grub_nilfs2_btree_node_dptrs (struct grub_nilfs2_data *data, |
| struct grub_nilfs2_btree_node *node) |
| @@ -517,7 +525,7 @@ grub_nilfs2_btree_lookup (struct grub_nilfs2_data *data, |
| node = grub_nilfs2_btree_get_root (inode); |
| level = grub_nilfs2_btree_get_level (node); |
| |
| - found = grub_nilfs2_btree_node_lookup (node, key, &index); |
| + found = grub_nilfs2_btree_node_lookup (data, node, key, &index); |
| ptr = grub_nilfs2_btree_node_get_ptr (data, node, index); |
| if (need_translate) |
| ptr = grub_nilfs2_dat_translate (data, ptr); |
| @@ -538,7 +546,7 @@ grub_nilfs2_btree_lookup (struct grub_nilfs2_data *data, |
| } |
| |
| if (!found) |
| - found = grub_nilfs2_btree_node_lookup (node, key, &index); |
| + found = grub_nilfs2_btree_node_lookup (data, node, key, &index); |
| else |
| index = 0; |
| |
| -- |
| 2.14.2 |
| |