[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[Libguestfs] [PATCH hivex 17/19] lib: get_children: Handle li-records as intermediate nodes (RHBZ#717583).



From: "Richard W.M. Jones" <rjones redhat com>

This is a full fix for
https://bugzilla.redhat.com/show_bug.cgi?id=717583
---
 lib/node.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 87 insertions(+), 1 deletion(-)

diff --git a/lib/node.c b/lib/node.c
index 9127251..4824df2 100644
--- a/lib/node.c
+++ b/lib/node.c
@@ -202,6 +202,64 @@ static int check_child_is_nk_block (hive_h *h, hive_node_h child, int flags);
  *
  * The list of intermediate nodes (a mix of lf/lh/ri/li blocks) is
  * returned in 'blocks_ret'.
+ *
+ * ----------------------------------------
+ *
+ * The format of the intermediate blocks is not documented, but
+ * appears to be this:
+ *
+ * +-------------+  This is the parent registry key.
+ * | nk          |
+ * |-------------|
+ * | subkey_lf  ---->  Points to either lf/lh, li or ri
+ * |             |     (all 3 cases have to be dealt with
+ * |             |     separately, see below)
+ * +-------------+
+ *
+ * The subkey_lf field can point to one of three things, which are
+ * all subtly different:
+ *
+ * (1) lf/lh record.  (It's not clear what the precise difference
+ * is but we treat them as the same thing)
+ *
+ * +-------------+
+ * | lf/lh       |
+ * |-------------|
+ * | nr_keys     |
+ * |   keys[0].offset ------>  points to nk blocks (the children)
+ * |   keys[1].offset ------>
+ * |   keys[2].offset ------>
+ * +-------------+
+ *
+ * (2) li record.
+ *
+ * Although the format of an li-record is the same as the format of an
+ * ri-record, the difference is that the offsets point directly to the
+ * nk blocks (children).
+ *
+ * +-------------+
+ * | li          |
+ * |-------------|
+ * | nr_offsets  |
+ * |   offset[0] ------>  points to nk blocks (the children)
+ * |   offset[1] ------>
+ * |   offset[2] ------>
+ * +-------------+
+ *
+ * (3) ri record.
+ *
+ * The format of the block is the same as the li-record, BUT ri-record
+ * offsets *never* point directly to nk blocks.  They only point to
+ * other lf/lh/li/ri-records, thus forming a tree of arbitrary depth.
+ *
+ * +-------------+
+ * | ri          |
+ * |-------------|
+ * | nr_offsets  |
+ * |   offset[0] ------>  points to another lf/lh/li/ri block
+ * |   offset[1] ------>
+ * |   offset[2] ------>
+ * +-------------+
  */
 int
 _hivex_get_children (hive_h *h, hive_node_h node,
@@ -328,6 +386,34 @@ _get_children (hive_h *h, hive_node_h blkoff,
         return -1;
     }
   }
+  /* Points to li-record? */
+  else if (block->id[0] == 'l' && block->id[1] == 'i') {
+    /* li-records are formatted the same as ri-records, but they
+     * contain direct links to child records (same as lf/lh), so
+     * we treat them the same way as lf/lh.
+     */
+    struct ntreg_ri_record *ri = (struct ntreg_ri_record *) block;
+
+    /* Check number of subkeys in the nk-record matches number of subkeys
+     * in the li-record.
+     */
+    size_t nr_offsets = le16toh (ri->nr_offsets);
+
+    if (8 + nr_offsets * 4 > len) {
+      SET_ERRNO (EFAULT, "too many offsets (%zu, %zu)", nr_offsets, len);
+      return -1;
+    }
+
+    size_t i;
+    for (i = 0; i < nr_offsets; ++i) {
+      hive_node_h subkey = le32toh (ri->offset[i]);
+      subkey += 0x1000;
+      if (check_child_is_nk_block (h, subkey, flags) == -1)
+        return -1;
+      if (_hivex_add_to_offset_list (children, subkey) == -1)
+        return -1;
+    }
+  }
   /* Points to ri-record? */
   else if (block->id[0] == 'r' && block->id[1] == 'i') {
     struct ntreg_ri_record *ri = (struct ntreg_ri_record *) block;
@@ -355,7 +441,7 @@ _get_children (hive_h *h, hive_node_h blkoff,
   }
   else {
     SET_ERRNO (ENOTSUP,
-               "subkey block is not lf/lh/ri (0x%zx, %d, %d)",
+               "subkey block is not lf/lh/li/ri (0x%zx, %d, %d)",
                blkoff, block->id[0], block->id[1]);
     return -1;
   }
-- 
1.8.3.1


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]