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

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