123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100 |
- 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
|