nalika / rpms / grub2

Forked from rpms/grub2 2 years ago
Clone

Blame SOURCES/0447-fs-nilfs2-Don-t-search-children-if-provided-number-i.patch

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