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

[Libguestfs] [hivex][PATCH 3/8] hivex: Add offset-&-length function for long value data



This patch adds value_data_cell_offset to the hivex ABI, to report the
hive space used for long (>4 bytes) value data.

Signed-off-by: Alex Nelson <ajnelson cs ucsc edu>
---
 generator/generator.ml |   12 +++++++++
 lib/hivex.c            |   60 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 72 insertions(+), 0 deletions(-)

diff --git a/generator/generator.ml b/generator/generator.ml
index 7ece245..6204ecd 100755
--- a/generator/generator.ml
+++ b/generator/generator.ml
@@ -273,6 +273,18 @@ Return the length of the node data structure.";
     "\
 Return the length of the value data structure.";
 
+  "value_data_cell_offset", (RLenValue, [AHive; AValue "val"]),
+    "return the offset and length of a value data cell",
+    "\
+Return the offset and length of the value's data cell, not value cell.
+E.g. if the value data were \"foobar\" then the cell length would be 10,
+and the offset would be to a value data cell, which houses the data
+prefixed with 4 bytes describing the size.  If the data length is not
+greater than 4, then 0 is returned as offset and length, as the data
+are inline in the value.
+
+Returns 0 and sets errno on error.";
+
   "value_value", (RLenTypeVal, [AHive; AValue "val"]),
     "return data length, data type and data of a value",
     "\
diff --git a/lib/hivex.c b/lib/hivex.c
index bf1a860..df313bf 100644
--- a/lib/hivex.c
+++ b/lib/hivex.c
@@ -1257,6 +1257,66 @@ hivex_value_type (hive_h *h, hive_value_h value, hive_type *t, size_t *len)
   return 0;
 }
 
+hive_value_h
+hivex_value_data_cell_offset (hive_h *h, hive_value_h value, size_t *len)
+{
+  if (!IS_VALID_BLOCK (h, value) || !BLOCK_ID_EQ (h, value, "vk")) {
+    errno = EINVAL;
+    return 0;
+  }
+
+  if (h->msglvl >= 2)
+    fprintf (stderr, "hivex_value_data_cell_offset: value=0x%zx\n", value);
+  struct ntreg_vk_record *vk = (struct ntreg_vk_record *) (h->addr + value);
+
+  size_t data_len;
+  int is_inline;
+
+  data_len = le32toh (vk->data_len);
+  is_inline = !!(data_len & 0x80000000);
+  data_len &= 0x7fffffff;
+
+  if (h->msglvl >= 2)
+    fprintf (stderr, "hivex_value_data_cell_offset: is_inline=%d\n", is_inline);
+
+  if (h->msglvl >= 2)
+    fprintf (stderr, "hivex_value_data_cell_offset: data_len=%zx\n", data_len);
+
+  if (is_inline && data_len > 4) {
+    errno = ENOTSUP;
+    return 0;
+  }
+
+  if (is_inline) {
+    /* There is no other location for the value data. */
+    if (len)
+      *len = 0;
+    return 0;
+  } else {
+    if (len)
+      *len = data_len + 4;  /* Include 4 header length bytes */
+  }
+
+  if (h->msglvl >= 2)
+    fprintf (stderr, "hivex_value_data_cell_offset: Proceeding with indirect data.\n");
+
+  size_t data_offset = le32toh (vk->data_offset);
+  data_offset += 0x1000;  /* Add 0x1000 because everything's off by 4KiB */
+  if (!IS_VALID_BLOCK (h, data_offset)) {
+    if (h->msglvl >= 2)
+      fprintf (stderr, "hivex_value_data_cell_offset: returning EFAULT because data "
+               "offset is not a valid block (0x%zx)\n",
+               data_offset);
+    errno = EFAULT;
+    return 0;
+  }
+
+  if (h->msglvl >= 2)
+    fprintf (stderr, "hivex_value_data_cell_offset: data_offset=%zx\n", data_offset);
+
+  return data_offset;
+}
+
 char *
 hivex_value_value (hive_h *h, hive_value_h value,
                    hive_type *t_rtn, size_t *len_rtn)
-- 
1.7.4.4




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