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

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