1From 37c0eb05cdcc64c28d31c4ebd300f14d5239d05e Mon Sep 17 00:00:00 2001
2From: Daniel Axtens <dja@axtens.net>
3Date: Mon, 18 Jan 2021 16:49:44 +1100
4Subject: [PATCH] fs/nilfs2: Don't search children if provided number is too
5 large
6
7NILFS2 reads the number of children a node has from the node. Unfortunately,
8that's not trustworthy. Check if it's beyond what the filesystem permits and
9reject it if so.
10
11This blocks some OOB reads. I'm not sure how controllable the read is and what
12could be done with invalidly read data later on.
13
14Signed-off-by: Daniel Axtens <dja@axtens.net>
15Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
16Signed-off-by: Stefan Sørensen <stefan.sorensen@spectralink.com>
17---
18 grub-core/fs/nilfs2.c | 38 +++++++++++++++++++++++---------------
19 1 file changed, 23 insertions(+), 15 deletions(-)
20
21diff --git a/grub-core/fs/nilfs2.c b/grub-core/fs/nilfs2.c
22index fee2242..43ac1ad 100644
23--- a/grub-core/fs/nilfs2.c
24+++ b/grub-core/fs/nilfs2.c
25@@ -416,14 +416,34 @@ grub_nilfs2_btree_node_get_key (struct grub_nilfs2_btree_node *node,
26 }
27
28 static inline int
29-grub_nilfs2_btree_node_lookup (struct grub_nilfs2_btree_node *node,
30+grub_nilfs2_btree_node_nchildren_max (struct grub_nilfs2_data *data,
31+				      struct grub_nilfs2_btree_node *node)
32+{
33+  int node_children_max = ((NILFS2_BLOCK_SIZE (data) -
34+			    sizeof (struct grub_nilfs2_btree_node) -
35+			    NILFS_BTREE_NODE_EXTRA_PAD_SIZE) /
36+			   (sizeof (grub_uint64_t) + sizeof (grub_uint64_t)));
37+
38+  return (node->bn_flags & NILFS_BTREE_NODE_ROOT) ? 3 : node_children_max;
39+}
40+
41+static inline int
42+grub_nilfs2_btree_node_lookup (struct grub_nilfs2_data *data,
43+			       struct grub_nilfs2_btree_node *node,
44 			       grub_uint64_t key, int *indexp)
45 {
46   grub_uint64_t nkey;
47   int index, low, high, s;
48
49   low = 0;
50+
51   high = grub_le_to_cpu16 (node->bn_nchildren) - 1;
52+  if (high >= grub_nilfs2_btree_node_nchildren_max (data, node))
53+    {
54+      grub_error (GRUB_ERR_BAD_FS, "too many children");
55+      return 0;
56+    }
57+
58   index = 0;
59   s = 0;
60   while (low <= high)
61@@ -459,18 +479,6 @@ grub_nilfs2_btree_node_lookup (struct grub_nilfs2_btree_node *node,
62   return s == 0;
63 }
64
65-static inline int
66-grub_nilfs2_btree_node_nchildren_max (struct grub_nilfs2_data *data,
67-				      struct grub_nilfs2_btree_node *node)
68-{
69-  int node_children_max = ((NILFS2_BLOCK_SIZE (data) -
70-			    sizeof (struct grub_nilfs2_btree_node) -
71-			    NILFS_BTREE_NODE_EXTRA_PAD_SIZE) /
72-			   (sizeof (grub_uint64_t) + sizeof (grub_uint64_t)));
73-
74-  return (node->bn_flags & NILFS_BTREE_NODE_ROOT) ? 3 : node_children_max;
75-}
76-
77 static inline grub_uint64_t *
78 grub_nilfs2_btree_node_dptrs (struct grub_nilfs2_data *data,
79 			      struct grub_nilfs2_btree_node *node)
80@@ -517,7 +525,7 @@ grub_nilfs2_btree_lookup (struct grub_nilfs2_data *data,
81   node = grub_nilfs2_btree_get_root (inode);
82   level = grub_nilfs2_btree_get_level (node);
83
84-  found = grub_nilfs2_btree_node_lookup (node, key, &index);
85+  found = grub_nilfs2_btree_node_lookup (data, node, key, &index);
86   ptr = grub_nilfs2_btree_node_get_ptr (data, node, index);
87   if (need_translate)
88     ptr = grub_nilfs2_dat_translate (data, ptr);
89@@ -538,7 +546,7 @@ grub_nilfs2_btree_lookup (struct grub_nilfs2_data *data,
90 	}
91
92       if (!found)
93-	found = grub_nilfs2_btree_node_lookup (node, key, &index);
94+	found = grub_nilfs2_btree_node_lookup (data, node, key, &index);
95       else
96 	index = 0;
97
98--
992.14.2
100
101