Blame SOURCES/0001-lib-node.c-Limit-recursion-in-ri-records-CVE-2021-36.patch

3e92b7
From 771728218dac2fbf6997a7e53225e75a4c6b7255 Mon Sep 17 00:00:00 2001
3e92b7
From: "Richard W.M. Jones" <rjones@redhat.com>
3e92b7
Date: Thu, 8 Jul 2021 19:00:45 +0100
3e92b7
Subject: [PATCH] lib/node.c: Limit recursion in ri-records (CVE-2021-3622)
3e92b7
3e92b7
Windows Registry hive "ri"-records are arbitrarily nested B-tree-like
3e92b7
structures:
3e92b7
3e92b7
  +-------------+
3e92b7
  | ri          |
3e92b7
  |-------------|
3e92b7
  | nr_offsets  |
3e92b7
  |   offset[0] ------>  points to another lf/lh/li/ri block
3e92b7
  |   offset[1] ------>
3e92b7
  |   offset[2] ------>
3e92b7
  +-------------+
3e92b7
3e92b7
It is possible to construct a hive with a very deeply nested tree of
3e92b7
ri-records, causing the internal _get_children function to recurse to
3e92b7
any depth which can cause programs linked to hivex to crash with a
3e92b7
stack overflow.
3e92b7
3e92b7
Since it is not thought that deeply nested ri-records occur in real
3e92b7
hives, limit recursion depth.  If you hit this limit you will see the
3e92b7
following error and the operation will return an error instead of
3e92b7
crashing:
3e92b7
3e92b7
  \> ls
3e92b7
  hivex: _get_children: returning EINVAL because: ri-record nested to depth >= 32
3e92b7
  ls: Invalid argument
3e92b7
3e92b7
Thanks to Jeremy Galindo for finding and reporting this bug.
3e92b7
3e92b7
Reported-by: Jeremy Galindo, Sr Security Engineer, Datto.com
3e92b7
Signed-off-by: Richard W.M. Jones <rjones@redhat.com>
3e92b7
Fixes: CVE-2021-3622
3e92b7
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1975489
3e92b7
(cherry picked from commit 781a12c4a49dd81365c9c567c5aa5e19e894ba0e)
3e92b7
---
3e92b7
 lib/node.c | 18 ++++++++++++++----
3e92b7
 1 file changed, 14 insertions(+), 4 deletions(-)
3e92b7
3e92b7
diff --git a/lib/node.c b/lib/node.c
3e92b7
index 7b002a46..eb7fe93c 100644
3e92b7
--- a/lib/node.c
3e92b7
+++ b/lib/node.c
3e92b7
@@ -203,7 +203,7 @@ hivex_node_classname (hive_h *h, hive_node_h node)
3e92b7
 
3e92b7
 static int _get_children (hive_h *h, hive_node_h blkoff,
3e92b7
                           offset_list *children, offset_list *blocks,
3e92b7
-                          int flags);
3e92b7
+                          int flags, unsigned depth);
3e92b7
 static int check_child_is_nk_block (hive_h *h, hive_node_h child, int flags);
3e92b7
 
3e92b7
 /* Iterate over children (ie. subkeys of a node), returning child
3e92b7
@@ -335,7 +335,7 @@ _hivex_get_children (hive_h *h, hive_node_h node,
3e92b7
     goto error;
3e92b7
   }
3e92b7
 
3e92b7
-  if (_get_children (h, subkey_lf, &children, &blocks, flags) == -1)
3e92b7
+  if (_get_children (h, subkey_lf, &children, &blocks, flags, 0) == -1)
3e92b7
     goto error;
3e92b7
 
3e92b7
   /* Check the number of children we ended up reading matches
3e92b7
@@ -383,7 +383,7 @@ _hivex_get_children (hive_h *h, hive_node_h node,
3e92b7
 static int
3e92b7
 _get_children (hive_h *h, hive_node_h blkoff,
3e92b7
                offset_list *children, offset_list *blocks,
3e92b7
-               int flags)
3e92b7
+               int flags, unsigned depth)
3e92b7
 {
3e92b7
   /* Add this intermediate block. */
3e92b7
   if (_hivex_add_to_offset_list (blocks, blkoff) == -1)
3e92b7
@@ -486,7 +486,17 @@ _get_children (hive_h *h, hive_node_h blkoff,
3e92b7
         }
3e92b7
       }
3e92b7
 
3e92b7
-      if (_get_children (h, offset, children, blocks, flags) == -1)
3e92b7
+      /* Although in theory hive ri records might be nested to any
3e92b7
+       * depth, in practice this is unlikely.  Recursing here caused
3e92b7
+       * CVE-2021-3622.  Thus limit the depth we will recurse to
3e92b7
+       * something small.
3e92b7
+       */
3e92b7
+      if (depth >= 32) {
3e92b7
+        SET_ERRNO (EINVAL, "ri-record nested to depth >= %u", depth);
3e92b7
+        return -1;
3e92b7
+      }
3e92b7
+
3e92b7
+      if (_get_children (h, offset, children, blocks, flags, depth+1) == -1)
3e92b7
         return -1;
3e92b7
     }
3e92b7
   }
3e92b7
-- 
3e92b7
2.32.0
3e92b7