diff --git a/SOURCES/0001-Fix-Perl-directory-install-path.patch b/SOURCES/0001-Fix-Perl-directory-install-path.patch new file mode 100644 index 0000000..0ca73e8 --- /dev/null +++ b/SOURCES/0001-Fix-Perl-directory-install-path.patch @@ -0,0 +1,25 @@ +From 1c6bd6e0085204425d7c687f2566cb9b13231e6e Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Fri, 17 Feb 2017 15:58:04 +0000 +Subject: [PATCH 01/12] Fix Perl directory install path. + +--- + perl/Makefile.am | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/perl/Makefile.am b/perl/Makefile.am +index a0ae863..144a1bc 100644 +--- a/perl/Makefile.am ++++ b/perl/Makefile.am +@@ -43,7 +43,7 @@ $(TESTS): src_deps all + + TESTS_ENVIRONMENT = ../run + +-INSTALLDIRS = site ++INSTALLDIRS = vendor + + all: Makefile-pl src_deps + $(MAKE) -f Makefile-pl +-- +1.8.3.1 + diff --git a/SOURCES/0001-generator-Fix-a-spelling-mistake-in-the-documentatio.patch b/SOURCES/0001-generator-Fix-a-spelling-mistake-in-the-documentatio.patch deleted file mode 100644 index dc8ed8e..0000000 --- a/SOURCES/0001-generator-Fix-a-spelling-mistake-in-the-documentatio.patch +++ /dev/null @@ -1,50 +0,0 @@ -diff -ur hivex-1.3.10.old/generator/generator.ml hivex-1.3.10/generator/generator.ml ---- hivex-1.3.10.old/generator/generator.ml 2014-03-26 14:56:27.000000000 +0000 -+++ hivex-1.3.10/generator/generator.ml 2014-11-17 11:53:46.469958904 +0000 -@@ -242,7 +242,7 @@ - "\ - Return the length of the key (name) of a (key, value) pair as produced - by C. The length can legitimately be 0, so errno is --the necesary mechanism to check for errors. -+the necessary mechanism to check for errors. - - In the context of Windows Registries, a zero-length name means - that this value is the default key for this node in the tree. -diff -ur hivex-1.3.10.old/lib/hivex.pod hivex-1.3.10/lib/hivex.pod ---- hivex-1.3.10.old/lib/hivex.pod 2014-01-10 10:00:53.000000000 +0000 -+++ hivex-1.3.10/lib/hivex.pod 2014-11-17 11:53:49.288886768 +0000 -@@ -346,7 +346,7 @@ - - Return the length of the key (name) of a (key, value) pair as produced - by C. The length can legitimately be 0, so errno is --the necesary mechanism to check for errors. -+the necessary mechanism to check for errors. - - In the context of Windows Registries, a zero-length name means - that this value is the default key for this node in the tree. -diff -ur hivex-1.3.10.old/perl/lib/Win/Hivex.pm hivex-1.3.10/perl/lib/Win/Hivex.pm ---- hivex-1.3.10.old/perl/lib/Win/Hivex.pm 2014-01-10 10:00:53.000000000 +0000 -+++ hivex-1.3.10/perl/lib/Win/Hivex.pm 2014-11-17 11:53:49.337885514 +0000 -@@ -212,7 +212,7 @@ - - Return the length of the key (name) of a (key, value) pair as produced - by C. The length can legitimately be 0, so errno is --the necesary mechanism to check for errors. -+the necessary mechanism to check for errors. - - In the context of Windows Registries, a zero-length name means - that this value is the default key for this node in the tree. -diff -ur hivex-1.3.10.old/ruby/ext/hivex/_hivex.c hivex-1.3.10/ruby/ext/hivex/_hivex.c ---- hivex-1.3.10.old/ruby/ext/hivex/_hivex.c 2014-01-13 22:20:34.000000000 +0000 -+++ hivex-1.3.10/ruby/ext/hivex/_hivex.c 2014-11-17 11:53:50.808847877 +0000 -@@ -580,8 +580,8 @@ - * - * Return the length of the key (name) of a (key, value) - * pair as produced by "h.value_key". The length can -- * legitimately be 0, so errno is the necesary mechanism to -- * check for errors. -+ * legitimately be 0, so errno is the necessary mechanism -+ * to check for errors. - * - * In the context of Windows Registries, a zero-length name - * means that this value is the default key for this node diff --git a/SOURCES/0001-handle-Refuse-to-open-files-8192-bytes-in-size.patch b/SOURCES/0001-handle-Refuse-to-open-files-8192-bytes-in-size.patch deleted file mode 100644 index ac5dbf6..0000000 --- a/SOURCES/0001-handle-Refuse-to-open-files-8192-bytes-in-size.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 357f26fa64fd1d9ccac2331fe174a8ee9c607adb Mon Sep 17 00:00:00 2001 -From: "Richard W.M. Jones" -Date: Thu, 30 Oct 2014 13:50:39 +0000 -Subject: [PATCH 1/2] handle: Refuse to open files < 8192 bytes in size. - -These cannot be valid hives, since they don't contain a full header -page and at least a single page of data (in other words they couldn't -contain a root node). - -Thanks: Mahmoud Al-Qudsi ---- - lib/handle.c | 7 +++++++ - 1 file changed, 7 insertions(+) - -diff --git a/lib/handle.c b/lib/handle.c -index 62a8644..a3cbcf7 100644 ---- a/lib/handle.c -+++ b/lib/handle.c -@@ -104,6 +104,13 @@ hivex_open (const char *filename, int flags) - - h->size = statbuf.st_size; - -+ if (h->size < 0x2000) { -+ SET_ERRNO (EINVAL, -+ "%s: file is too small to be a Windows NT Registry hive file", -+ filename); -+ goto error; -+ } -+ - if (!h->writable) { - h->addr = mmap (NULL, h->size, PROT_READ, MAP_SHARED, h->fd, 0); - if (h->addr == MAP_FAILED) --- -2.1.0 - diff --git a/SOURCES/0001-lib-Don-t-leak-errno-from-_hivex_recode-function.patch b/SOURCES/0001-lib-Don-t-leak-errno-from-_hivex_recode-function.patch deleted file mode 100644 index 24ece49..0000000 --- a/SOURCES/0001-lib-Don-t-leak-errno-from-_hivex_recode-function.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 4b3c3cd2b3d8d34601979feeb1390fddd442ab04 Mon Sep 17 00:00:00 2001 -From: "Richard W.M. Jones" -Date: Thu, 20 Nov 2014 21:37:19 +0000 -Subject: [PATCH] lib: Don't leak errno from _hivex_recode function. - -If iconv returns E2BIG, that's an internal indication for us, and not -an error. Don't leak the errno up to the user, as happened here: - -https://www.redhat.com/archives/libguestfs/2014-November/msg00140.html - -Thanks Nicolas Ecarnot. ---- - lib/utf16.c | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/lib/utf16.c b/lib/utf16.c -index fe2c3bd..238f40a 100644 ---- a/lib/utf16.c -+++ b/lib/utf16.c -@@ -58,6 +58,10 @@ _hivex_recode (const char *input_encoding, const char *input, size_t input_len, - if (r == (size_t) -1) { - if (errno == E2BIG) { - int err = errno; -+ /* Reset errno here because we don't want to accidentally -+ * return E2BIG to a library caller. -+ */ -+ errno = 0; - size_t prev = outalloc; - /* Try again with a larger output buffer. */ - free (out); --- -2.1.0 - diff --git a/SOURCES/0001-value-Set-errno-0-on-non-error-path-in-hivex_value_d.patch b/SOURCES/0001-value-Set-errno-0-on-non-error-path-in-hivex_value_d.patch deleted file mode 100644 index 0344910..0000000 --- a/SOURCES/0001-value-Set-errno-0-on-non-error-path-in-hivex_value_d.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 38522d66673f341f8b12a82eb070fd1ffb8e55ec Mon Sep 17 00:00:00 2001 -From: "Richard W.M. Jones" -Date: Mon, 22 Sep 2014 15:08:44 +0100 -Subject: [PATCH 1/2] value: Set errno = 0 on non-error path in - hivex_value_data_cell_offset (RHBZ#1145056). - -hivex_value_data_cell_offset may return 0 to indicate that the data is -inline. This is not an error return, but it was possible for errno to -have a random (non-zero) value along this path. Explicitly set errno -= 0 on this path. - -Thanks: Wei Shi -(cherry picked from commit 9763f96a1374486c7d00ea5c04b8048fe69e63f3) ---- - lib/value.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/lib/value.c b/lib/value.c -index f222b41..aa80238 100644 ---- a/lib/value.c -+++ b/lib/value.c -@@ -276,6 +276,7 @@ hivex_value_data_cell_offset (hive_h *h, hive_value_h value, size_t *len) - /* There is no other location for the value data. */ - if (len) - *len = 0; -+ errno = 0; - return 0; - } else { - if (len) --- -2.0.4 - diff --git a/SOURCES/0002-handle-Check-that-pages-do-not-extend-beyond-the-end.patch b/SOURCES/0002-handle-Check-that-pages-do-not-extend-beyond-the-end.patch deleted file mode 100644 index 7977e16..0000000 --- a/SOURCES/0002-handle-Check-that-pages-do-not-extend-beyond-the-end.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 4bbdf555f88baeae0fa804a369a81a83908bd705 Mon Sep 17 00:00:00 2001 -From: "Richard W.M. Jones" -Date: Thu, 30 Oct 2014 14:02:25 +0000 -Subject: [PATCH 2/2] handle: Check that pages do not extend beyond the end of - the file. - -Thanks: Mahmoud Al-Qudsi ---- - lib/handle.c | 7 +++++++ - 1 file changed, 7 insertions(+) - -diff --git a/lib/handle.c b/lib/handle.c -index a3cbcf7..3a8f09b 100644 ---- a/lib/handle.c -+++ b/lib/handle.c -@@ -247,6 +247,13 @@ hivex_open (const char *filename, int flags) - goto error; - } - -+ if (off + page_size > h->size) { -+ SET_ERRNO (ENOTSUP, -+ "%s: page size %zu at 0x%zx extends beyond end of file, bad registry", -+ filename, page_size, off); -+ goto error; -+ } -+ - /* Read the blocks in this page. */ - size_t blkoff; - struct ntreg_hbin_block *block; --- -2.1.0 - diff --git a/SOURCES/0002-hivexml-Tidy-up-error-handling-and-printing.patch b/SOURCES/0002-hivexml-Tidy-up-error-handling-and-printing.patch deleted file mode 100644 index 0be6d03..0000000 --- a/SOURCES/0002-hivexml-Tidy-up-error-handling-and-printing.patch +++ /dev/null @@ -1,82 +0,0 @@ -From c7e6dd0f09ca43c616bb2740ec748206bee6b14f Mon Sep 17 00:00:00 2001 -From: "Richard W.M. Jones" -Date: Mon, 22 Sep 2014 15:10:36 +0100 -Subject: [PATCH 2/2] hivexml: Tidy up error handling and printing. - -(cherry picked from commit 914d9b9a91babf0227989bc7ea00cf5e41ed7da4) ---- - xml/hivexml.c | 28 +++++++++++++--------------- - 1 file changed, 13 insertions(+), 15 deletions(-) - -diff --git a/xml/hivexml.c b/xml/hivexml.c -index a4bc7eb..b496bb6 100644 ---- a/xml/hivexml.c -+++ b/xml/hivexml.c -@@ -116,7 +116,7 @@ main (int argc, char *argv[]) - - hive_h *h = hivex_open (argv[optind], open_flags); - if (h == NULL) { -- perror (argv[optind]); -+ fprintf (stderr, "hivex_open: %s: %m\n", argv[optind]); - exit (EXIT_FAILURE); - } - -@@ -148,12 +148,12 @@ main (int argc, char *argv[]) - } - - if (hivex_visit (h, &visitor, sizeof visitor, writer, visit_flags) == -1) { -- perror (argv[optind]); -+ fprintf (stderr, "hivex_visit: %s: %m\n", argv[optind]); - exit (EXIT_FAILURE); - } - - if (hivex_close (h) == -1) { -- perror (argv[optind]); -+ fprintf (stderr, "hivex_close: %s: %m\n", argv[optind]); - exit (EXIT_FAILURE); - } - -@@ -217,12 +217,9 @@ node_byte_runs (hive_h *h, void *writer_v, hive_node_h node) - { - xmlTextWriterPtr writer = (xmlTextWriterPtr) writer_v; - char buf[1+BYTE_RUN_BUF_LEN]; -- errno = 0; - size_t node_struct_length = hivex_node_struct_length (h, node); -- if (errno) { -- if (errno == EINVAL) { -- fprintf (stderr, "node_byte_runs: Invoked on what does not seem to be a node (%zu).\n", node); -- } -+ if (node_struct_length == 0) { -+ fprintf (stderr, "node_byte_runs: hivex_node_struct_length: %m\n"); - return -1; - } - /* A node has one byte run. */ -@@ -301,17 +298,18 @@ value_byte_runs (hive_h *h, void *writer_v, hive_value_h value) { - xmlTextWriterPtr writer = (xmlTextWriterPtr) writer_v; - char buf[1+BYTE_RUN_BUF_LEN]; - size_t value_data_cell_length; -- errno = 0; - size_t value_data_structure_length = hivex_value_struct_length (h, value); -- if (errno != 0) { -- if (errno == EINVAL) { -- fprintf (stderr, "value_byte_runs: Invoked on what does not seem to be a value (%zu).\n", value); -- } -+ if (value_data_structure_length == 0) { -+ fprintf (stderr, "value_byte_runs: hivex_value_struct_length: %m\n"); - return -1; - } -- hive_value_h value_data_cell_offset = hivex_value_data_cell_offset (h, value, &value_data_cell_length); -- if (errno != 0) -+ errno = 0; -+ hive_value_h value_data_cell_offset = -+ hivex_value_data_cell_offset (h, value, &value_data_cell_length); -+ if (value_data_cell_offset == 0 && errno != 0) { -+ fprintf (stderr, "value_byte_runs: hivex_value_data_cell_offset: %m\n"); - return -1; -+ } - - XML_CHECK (xmlTextWriterStartElement, (writer, BAD_CAST "byte_runs")); - memset (buf, 0, 1+BYTE_RUN_BUF_LEN); --- -2.0.4 - diff --git a/SOURCES/0002-value-Set-errno-0-on-non-error-path-in-hivex_value_d.patch b/SOURCES/0002-value-Set-errno-0-on-non-error-path-in-hivex_value_d.patch new file mode 100644 index 0000000..32dd1b4 --- /dev/null +++ b/SOURCES/0002-value-Set-errno-0-on-non-error-path-in-hivex_value_d.patch @@ -0,0 +1,32 @@ +From 6a4dac0da1f318a1114363b274fcee76e73fcccf Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Mon, 22 Sep 2014 15:08:44 +0100 +Subject: [PATCH 02/12] value: Set errno = 0 on non-error path in + hivex_value_data_cell_offset (RHBZ#1145056). + +hivex_value_data_cell_offset may return 0 to indicate that the data is +inline. This is not an error return, but it was possible for errno to +have a random (non-zero) value along this path. Explicitly set errno += 0 on this path. + +Thanks: Wei Shi +(cherry picked from commit 9763f96a1374486c7d00ea5c04b8048fe69e63f3) +--- + lib/value.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/lib/value.c b/lib/value.c +index f222b41..aa80238 100644 +--- a/lib/value.c ++++ b/lib/value.c +@@ -276,6 +276,7 @@ hivex_value_data_cell_offset (hive_h *h, hive_value_h value, size_t *len) + /* There is no other location for the value data. */ + if (len) + *len = 0; ++ errno = 0; + return 0; + } else { + if (len) +-- +1.8.3.1 + diff --git a/SOURCES/0003-hivexml-Tidy-up-error-handling-and-printing.patch b/SOURCES/0003-hivexml-Tidy-up-error-handling-and-printing.patch new file mode 100644 index 0000000..0942640 --- /dev/null +++ b/SOURCES/0003-hivexml-Tidy-up-error-handling-and-printing.patch @@ -0,0 +1,82 @@ +From 2cffe999c938a0bc67c3c6162ea4fc896af2dd22 Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Mon, 22 Sep 2014 15:10:36 +0100 +Subject: [PATCH 03/12] hivexml: Tidy up error handling and printing. + +(cherry picked from commit 914d9b9a91babf0227989bc7ea00cf5e41ed7da4) +--- + xml/hivexml.c | 28 +++++++++++++--------------- + 1 file changed, 13 insertions(+), 15 deletions(-) + +diff --git a/xml/hivexml.c b/xml/hivexml.c +index a4bc7eb..b496bb6 100644 +--- a/xml/hivexml.c ++++ b/xml/hivexml.c +@@ -116,7 +116,7 @@ main (int argc, char *argv[]) + + hive_h *h = hivex_open (argv[optind], open_flags); + if (h == NULL) { +- perror (argv[optind]); ++ fprintf (stderr, "hivex_open: %s: %m\n", argv[optind]); + exit (EXIT_FAILURE); + } + +@@ -148,12 +148,12 @@ main (int argc, char *argv[]) + } + + if (hivex_visit (h, &visitor, sizeof visitor, writer, visit_flags) == -1) { +- perror (argv[optind]); ++ fprintf (stderr, "hivex_visit: %s: %m\n", argv[optind]); + exit (EXIT_FAILURE); + } + + if (hivex_close (h) == -1) { +- perror (argv[optind]); ++ fprintf (stderr, "hivex_close: %s: %m\n", argv[optind]); + exit (EXIT_FAILURE); + } + +@@ -217,12 +217,9 @@ node_byte_runs (hive_h *h, void *writer_v, hive_node_h node) + { + xmlTextWriterPtr writer = (xmlTextWriterPtr) writer_v; + char buf[1+BYTE_RUN_BUF_LEN]; +- errno = 0; + size_t node_struct_length = hivex_node_struct_length (h, node); +- if (errno) { +- if (errno == EINVAL) { +- fprintf (stderr, "node_byte_runs: Invoked on what does not seem to be a node (%zu).\n", node); +- } ++ if (node_struct_length == 0) { ++ fprintf (stderr, "node_byte_runs: hivex_node_struct_length: %m\n"); + return -1; + } + /* A node has one byte run. */ +@@ -301,17 +298,18 @@ value_byte_runs (hive_h *h, void *writer_v, hive_value_h value) { + xmlTextWriterPtr writer = (xmlTextWriterPtr) writer_v; + char buf[1+BYTE_RUN_BUF_LEN]; + size_t value_data_cell_length; +- errno = 0; + size_t value_data_structure_length = hivex_value_struct_length (h, value); +- if (errno != 0) { +- if (errno == EINVAL) { +- fprintf (stderr, "value_byte_runs: Invoked on what does not seem to be a value (%zu).\n", value); +- } ++ if (value_data_structure_length == 0) { ++ fprintf (stderr, "value_byte_runs: hivex_value_struct_length: %m\n"); + return -1; + } +- hive_value_h value_data_cell_offset = hivex_value_data_cell_offset (h, value, &value_data_cell_length); +- if (errno != 0) ++ errno = 0; ++ hive_value_h value_data_cell_offset = ++ hivex_value_data_cell_offset (h, value, &value_data_cell_length); ++ if (value_data_cell_offset == 0 && errno != 0) { ++ fprintf (stderr, "value_byte_runs: hivex_value_data_cell_offset: %m\n"); + return -1; ++ } + + XML_CHECK (xmlTextWriterStartElement, (writer, BAD_CAST "byte_runs")); + memset (buf, 0, 1+BYTE_RUN_BUF_LEN); +-- +1.8.3.1 + diff --git a/SOURCES/0004-lib-Don-t-leak-errno-from-_hivex_recode-function.patch b/SOURCES/0004-lib-Don-t-leak-errno-from-_hivex_recode-function.patch new file mode 100644 index 0000000..21a442e --- /dev/null +++ b/SOURCES/0004-lib-Don-t-leak-errno-from-_hivex_recode-function.patch @@ -0,0 +1,35 @@ +From 1d90ea86a0ac6c5863597880b33a18755aff819c Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Thu, 20 Nov 2014 21:37:19 +0000 +Subject: [PATCH 04/12] lib: Don't leak errno from _hivex_recode function. + +If iconv returns E2BIG, that's an internal indication for us, and not +an error. Don't leak the errno up to the user, as happened here: + +https://www.redhat.com/archives/libguestfs/2014-November/msg00140.html + +Thanks Nicolas Ecarnot. + +(cherry picked from commit 4b3c3cd2b3d8d34601979feeb1390fddd442ab04) +--- + lib/utf16.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/lib/utf16.c b/lib/utf16.c +index f4299f2..3b54b01 100644 +--- a/lib/utf16.c ++++ b/lib/utf16.c +@@ -59,6 +59,10 @@ _hivex_recode (const char *input_encoding, const char *input, size_t input_len, + if (r == (size_t) -1) { + if (errno == E2BIG) { + int err = errno; ++ /* Reset errno here because we don't want to accidentally ++ * return E2BIG to a library caller. ++ */ ++ errno = 0; + size_t prev = outalloc; + /* Try again with a larger output buffer. */ + free (out); +-- +1.8.3.1 + diff --git a/SOURCES/0005-handle-Refuse-to-open-files-8192-bytes-in-size.patch b/SOURCES/0005-handle-Refuse-to-open-files-8192-bytes-in-size.patch new file mode 100644 index 0000000..b9e4483 --- /dev/null +++ b/SOURCES/0005-handle-Refuse-to-open-files-8192-bytes-in-size.patch @@ -0,0 +1,36 @@ +From ebcb61e3d88d99b929b4d8ccaad837a871c102d8 Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Thu, 30 Oct 2014 13:50:39 +0000 +Subject: [PATCH 05/12] handle: Refuse to open files < 8192 bytes in size. + +These cannot be valid hives, since they don't contain a full header +page and at least a single page of data (in other words they couldn't +contain a root node). + +Thanks: Mahmoud Al-Qudsi +(cherry picked from commit 357f26fa64fd1d9ccac2331fe174a8ee9c607adb) +--- + lib/handle.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/lib/handle.c b/lib/handle.c +index 62a8644..a3cbcf7 100644 +--- a/lib/handle.c ++++ b/lib/handle.c +@@ -104,6 +104,13 @@ hivex_open (const char *filename, int flags) + + h->size = statbuf.st_size; + ++ if (h->size < 0x2000) { ++ SET_ERRNO (EINVAL, ++ "%s: file is too small to be a Windows NT Registry hive file", ++ filename); ++ goto error; ++ } ++ + if (!h->writable) { + h->addr = mmap (NULL, h->size, PROT_READ, MAP_SHARED, h->fd, 0); + if (h->addr == MAP_FAILED) +-- +1.8.3.1 + diff --git a/SOURCES/0006-handle-Check-that-pages-do-not-extend-beyond-the-end.patch b/SOURCES/0006-handle-Check-that-pages-do-not-extend-beyond-the-end.patch new file mode 100644 index 0000000..8e4f674 --- /dev/null +++ b/SOURCES/0006-handle-Check-that-pages-do-not-extend-beyond-the-end.patch @@ -0,0 +1,33 @@ +From 5c718aab579d693ea3169ab4d29b5c3bc9105aa1 Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Thu, 30 Oct 2014 14:02:25 +0000 +Subject: [PATCH 06/12] handle: Check that pages do not extend beyond the end + of the file. + +Thanks: Mahmoud Al-Qudsi +(cherry picked from commit 4bbdf555f88baeae0fa804a369a81a83908bd705) +--- + lib/handle.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/lib/handle.c b/lib/handle.c +index a3cbcf7..3a8f09b 100644 +--- a/lib/handle.c ++++ b/lib/handle.c +@@ -247,6 +247,13 @@ hivex_open (const char *filename, int flags) + goto error; + } + ++ if (off + page_size > h->size) { ++ SET_ERRNO (ENOTSUP, ++ "%s: page size %zu at 0x%zx extends beyond end of file, bad registry", ++ filename, page_size, off); ++ goto error; ++ } ++ + /* Read the blocks in this page. */ + size_t blkoff; + struct ntreg_hbin_block *block; +-- +1.8.3.1 + diff --git a/SOURCES/0007-generator-Fix-a-spelling-mistake-in-the-documentatio.patch b/SOURCES/0007-generator-Fix-a-spelling-mistake-in-the-documentatio.patch new file mode 100644 index 0000000..161e615 --- /dev/null +++ b/SOURCES/0007-generator-Fix-a-spelling-mistake-in-the-documentatio.patch @@ -0,0 +1,27 @@ +From 026a1a2e01795defcfe5b638347671e09fcec2b6 Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Tue, 20 May 2014 10:48:40 +0100 +Subject: [PATCH 07/12] generator: Fix a spelling mistake in the documentation + (RHBZ#1099286). + +(cherry picked from commit cea8dbf029029a725768caa14ddc876f56bfd878) +--- + generator/generator.ml | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/generator/generator.ml b/generator/generator.ml +index 02aaf12..64c7681 100755 +--- a/generator/generator.ml ++++ b/generator/generator.ml +@@ -242,7 +242,7 @@ default key."; + "\ + Return the length of the key (name) of a (key, value) pair as produced + by C. The length can legitimately be 0, so errno is +-the necesary mechanism to check for errors. ++the necessary mechanism to check for errors. + + In the context of Windows Registries, a zero-length name means + that this value is the default key for this node in the tree. +-- +1.8.3.1 + diff --git a/SOURCES/0008-add-HIVEX_OPEN_UNSAFE-flag.patch b/SOURCES/0008-add-HIVEX_OPEN_UNSAFE-flag.patch new file mode 100644 index 0000000..93c4e95 --- /dev/null +++ b/SOURCES/0008-add-HIVEX_OPEN_UNSAFE-flag.patch @@ -0,0 +1,70 @@ +From 691f5532ab4138093cdd8c661aba7519b0b1e2ad Mon Sep 17 00:00:00 2001 +From: Dawid Zamirski +Date: Thu, 16 Feb 2017 18:17:22 -0500 +Subject: [PATCH 08/12] add HIVEX_OPEN_UNSAFE flag. + +This flag will be used to control behavior of libhivex API functions so +that they tolerate corruption in hives by either using heuristic +recovery from unexpected situations or simply ignore bad registry +keys/values whenever possible. + +(cherry picked from commit 507f9328c67c701c32894249437551395bd8072c) +--- + generator/generator.ml | 8 ++++++++ + lib/handle.c | 1 + + lib/hivex-internal.h | 1 + + 3 files changed, 10 insertions(+) + +diff --git a/generator/generator.ml b/generator/generator.ml +index 64c7681..249a317 100755 +--- a/generator/generator.ml ++++ b/generator/generator.ml +@@ -113,6 +113,7 @@ let open_flags = [ + 1, "VERBOSE", "Verbose messages"; + 2, "DEBUG", "Debug messages"; + 4, "WRITE", "Enable writes to the hive"; ++ 8, "UNSAFE", "Enable heuristics to allow read/write of corrupted hives"; + ] + + (* The API calls. *) +@@ -145,6 +146,13 @@ Open the hive for writing. If omitted, the hive is read-only. + + See L. + ++=item HIVEX_OPEN_UNSAFE ++ ++Open the hive in unsafe mode that enables heuristics to handle corrupted hives. ++ ++This may allow to read or write registry keys/values that appear intact in an ++otherwise corrupted hive. Use at your own risk. ++ + =back"; + + "close", (RErrDispose, [AHive]), +diff --git a/lib/handle.c b/lib/handle.c +index 3a8f09b..dff2780 100644 +--- a/lib/handle.c ++++ b/lib/handle.c +@@ -83,6 +83,7 @@ hivex_open (const char *filename, int flags) + DEBUG (2, "created handle %p", h); + + h->writable = !!(flags & HIVEX_OPEN_WRITE); ++ h->unsafe = !!(flags & HIVEX_OPEN_UNSAFE); + h->filename = strdup (filename); + if (h->filename == NULL) + goto error; +diff --git a/lib/hivex-internal.h b/lib/hivex-internal.h +index bfd24c8..bbca215 100644 +--- a/lib/hivex-internal.h ++++ b/lib/hivex-internal.h +@@ -30,6 +30,7 @@ struct hive_h { + size_t size; + int msglvl; /* 1 = verbose, 2 or 3 = debug */ + int writable; ++ int unsafe; + + /* Registry file, memory mapped if read-only, or malloc'd if writing. */ + union { +-- +1.8.3.1 + diff --git a/SOURCES/0009-lib-change-how-hbin-sections-are-read.patch b/SOURCES/0009-lib-change-how-hbin-sections-are-read.patch new file mode 100644 index 0000000..e20e700 --- /dev/null +++ b/SOURCES/0009-lib-change-how-hbin-sections-are-read.patch @@ -0,0 +1,94 @@ +From f80b9b31f99ccdc06887c23dab46a37fc4f4ce74 Mon Sep 17 00:00:00 2001 +From: Dawid Zamirski +Date: Thu, 16 Feb 2017 18:17:23 -0500 +Subject: [PATCH 09/12] lib: change how hbin sections are read. + +Only when HIVEX_OPEN_UNSAFE flag is set: + +* hivex_open: when looping over hbin sections (aka pages), handle a + case where following hbin section may not begin at exactly at the end + of previous one. If this happens, scan the page section until next + one is found and validate it by checking declared offset with actual + one - if they match, all is good and we can safely move on. + +Rationale: there are registry hives there is some garbage data between +hbin section but the hive is still perfectly usable as long as the +offsets stated in hbin headers are correct. + +(cherry picked from commit 8d092a746dbd9e61ec85cf17449c201bc0719721) +--- + lib/handle.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++----- + 1 file changed, 46 insertions(+), 5 deletions(-) + +diff --git a/lib/handle.c b/lib/handle.c +index dff2780..8c64b6d 100644 +--- a/lib/handle.c ++++ b/lib/handle.c +@@ -227,11 +227,42 @@ hivex_open (const char *filename, int flags) + page->magic[1] != 'b' || + page->magic[2] != 'i' || + page->magic[3] != 'n') { +- SET_ERRNO (ENOTSUP, +- "%s: trailing garbage at end of file " +- "(at 0x%zx, after %zu pages)", +- filename, off, pages); +- goto error; ++ ++ if (!h->unsafe) { ++ SET_ERRNO (ENOTSUP, ++ "%s: trailing garbage at end of file " ++ "(at 0x%zx, after %zu pages)", ++ filename, off, pages); ++ goto error; ++ } ++ ++ DEBUG (2, ++ "page not found at expected offset 0x%zx, " ++ "seeking until one is found or EOF is reached", ++ off); ++ ++ int found = 0; ++ while (off < h->size) { ++ off += 0x1000; ++ ++ if (off >= h->endpages) ++ break; ++ ++ page = (struct ntreg_hbin_page *) ((char *) h->addr + off); ++ if (page->magic[0] == 'h' && ++ page->magic[1] == 'b' && ++ page->magic[2] == 'i' && ++ page->magic[3] == 'n') { ++ DEBUG (2, "found next page by seeking at 0x%zx", off); ++ found = 1; ++ break; ++ } ++ } ++ ++ if (!found) { ++ DEBUG (2, "page not found and end of pages section reached"); ++ break; ++ } + } + + size_t page_size = le32toh (page->page_size); +@@ -255,6 +286,16 @@ hivex_open (const char *filename, int flags) + goto error; + } + ++ size_t page_offset = le32toh(page->offset_first) + 0x1000; ++ ++ if (page_offset != off) { ++ SET_ERRNO (ENOTSUP, ++ "%s: declared page offset (0x%zx) does not match computed " ++ "offset (0x%zx), bad registry", ++ filename, page_offset, off); ++ goto error; ++ } ++ + /* Read the blocks in this page. */ + size_t blkoff; + struct ntreg_hbin_block *block; +-- +1.8.3.1 + diff --git a/SOURCES/0010-lib-allow-to-walk-registry-with-corrupted-blocks.patch b/SOURCES/0010-lib-allow-to-walk-registry-with-corrupted-blocks.patch new file mode 100644 index 0000000..c135032 --- /dev/null +++ b/SOURCES/0010-lib-allow-to-walk-registry-with-corrupted-blocks.patch @@ -0,0 +1,137 @@ +From 8e187357f466c31a9e75ac4924b32bbf4823e73f Mon Sep 17 00:00:00 2001 +From: Dawid Zamirski +Date: Thu, 16 Feb 2017 18:17:24 -0500 +Subject: [PATCH 10/12] lib: allow to walk registry with corrupted blocks + +Only when HIVEX_OPEN_UNSAFE flag is set. + +There are some corrupted registry files that have invalid hbin cells +but are still readable. This patch makes the following changes: + +* hivex_open - do not abort with complete failure if we run across a + block with invalid size (unless it's the root block). Instead just + log the event, and move on. This will allow open hives that have + apparent invalid blocks but the ones of potential interest might be + perfectly accessible. +* _hivex_get_children - similiarly, if the's invalid subkey, just skip + it instead of failing so one can continue to browse other valid + subkeys. + +The above is similar to the behavior to Windows regedit where one can +load such corrupted hives with e.g. "reg load HKU\Corrupted" and +browse/change it despite some keys might be missing. + +(cherry picked from commit 5345ec8f1df304dc93a6b1e4cbb40e7c1cf6f88d) +--- + lib/handle.c | 16 ++++++++++++---- + lib/node.c | 46 +++++++++++++++++++++++++++++++++++----------- + 2 files changed, 47 insertions(+), 15 deletions(-) + +diff --git a/lib/handle.c b/lib/handle.c +index 8c64b6d..0d2b24b 100644 +--- a/lib/handle.c ++++ b/lib/handle.c +@@ -313,10 +313,18 @@ hivex_open (const char *filename, int flags) + int used; + seg_len = block_len (h, blkoff, &used); + if (seg_len <= 4 || (seg_len & 3) != 0) { +- SET_ERRNO (ENOTSUP, +- "%s: block size %" PRIu32 " at 0x%zx, bad registry", +- filename, le32toh (block->seg_len), blkoff); +- goto error; ++ if (is_root || !h->unsafe) { ++ SET_ERRNO (ENOTSUP, ++ "%s, the block at 0x%zx has invalid size %" PRIi32 ++ ", bad registry", ++ filename, blkoff, le32toh (block->seg_len)); ++ goto error; ++ } else { ++ DEBUG (2, ++ "%s: block at 0x%zx has invalid size %" PRIi32 ", skipping", ++ filename, blkoff, le32toh (block->seg_len)); ++ break; ++ } + } + + if (h->msglvl >= 2) { +diff --git a/lib/node.c b/lib/node.c +index 22d1861..a90c964 100644 +--- a/lib/node.c ++++ b/lib/node.c +@@ -343,11 +343,18 @@ _hivex_get_children (hive_h *h, hive_node_h node, + */ + size_t nr_children = _hivex_get_offset_list_length (&children); + if (nr_subkeys_in_nk != nr_children) { +- SET_ERRNO (ENOTSUP, +- "nr_subkeys_in_nk = %zu " +- "is not equal to number of children read %zu", +- nr_subkeys_in_nk, nr_children); +- goto error; ++ if (!h->unsafe) { ++ SET_ERRNO (ENOTSUP, ++ "nr_subkeys_in_nk = %zu " ++ "is not equal to number of childred read %zu", ++ nr_subkeys_in_nk, nr_children); ++ goto error; ++ } else { ++ DEBUG (2, ++ "nr_subkeys_in_nk = %zu " ++ "is not equal to number of children read %zu", ++ nr_subkeys_in_nk, nr_children); ++ } + } + + out: +@@ -407,8 +414,14 @@ _get_children (hive_h *h, hive_node_h blkoff, + for (i = 0; i < nr_subkeys_in_lf; ++i) { + hive_node_h subkey = le32toh (lf->keys[i].offset); + subkey += 0x1000; +- if (check_child_is_nk_block (h, subkey, flags) == -1) +- return -1; ++ if (check_child_is_nk_block (h, subkey, flags) == -1) { ++ if (h->unsafe) { ++ DEBUG (2, "subkey at 0x%zx is not an NK block, skipping", subkey); ++ continue; ++ } else { ++ return -1; ++ } ++ } + if (_hivex_add_to_offset_list (children, subkey) == -1) + return -1; + } +@@ -435,8 +448,14 @@ _get_children (hive_h *h, hive_node_h blkoff, + 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 (check_child_is_nk_block (h, subkey, flags) == -1) { ++ if (h->unsafe) { ++ DEBUG (2, "subkey at 0x%zx is not an NK block, skipping", subkey); ++ continue; ++ } else { ++ return -1; ++ } ++ } + if (_hivex_add_to_offset_list (children, subkey) == -1) + return -1; + } +@@ -458,8 +477,13 @@ _get_children (hive_h *h, hive_node_h blkoff, + hive_node_h offset = le32toh (ri->offset[i]); + offset += 0x1000; + if (!IS_VALID_BLOCK (h, offset)) { +- SET_ERRNO (EFAULT, "ri-offset is not a valid block (0x%zx)", offset); +- return -1; ++ if (h->unsafe) { ++ DEBUG (2, "ri-offset is not a valid block (0x%zx), skipping", offset); ++ continue; ++ } else { ++ SET_ERRNO (EFAULT, "ri-offset is not a valid block (0x%zx)", offset); ++ return -1; ++ } + } + + if (_get_children (h, offset, children, blocks, flags) == -1) +-- +1.8.3.1 + diff --git a/SOURCES/0011-hivexsh-add-u-flag-for-HIVEX_OPEN_UNSAFE.patch b/SOURCES/0011-hivexsh-add-u-flag-for-HIVEX_OPEN_UNSAFE.patch new file mode 100644 index 0000000..37fde1d --- /dev/null +++ b/SOURCES/0011-hivexsh-add-u-flag-for-HIVEX_OPEN_UNSAFE.patch @@ -0,0 +1,95 @@ +From d4f5c255832391ba6132959d1ded57ce9286e7d6 Mon Sep 17 00:00:00 2001 +From: Dawid Zamirski +Date: Thu, 16 Feb 2017 18:17:25 -0500 +Subject: [PATCH 11/12] hivexsh: add -u flag for HIVEX_OPEN_UNSAFE. + +and pass it to hivex_open. Additionally make hivex_value_value failures +non-critical in this mode when iterating through node children/values. + +(cherry picked from commit 62c53cda651f34f18a2b55e91012c0448acb70f1) +--- + sh/hivexsh.c | 26 ++++++++++++++++++++------ + 1 file changed, 20 insertions(+), 6 deletions(-) + +diff --git a/sh/hivexsh.c b/sh/hivexsh.c +index f578ccc..39ab9d0 100644 +--- a/sh/hivexsh.c ++++ b/sh/hivexsh.c +@@ -67,6 +67,7 @@ + + static int quit = 0; + static int is_tty; ++static int unsafe = 0; + static hive_h *h = NULL; + static char *prompt_string = NULL; /* Normal prompt string. */ + static char *loaded = NULL; /* Basename of loaded file, if any. */ +@@ -97,7 +98,7 @@ static int cmd_setval (char *args); + static void + usage (void) + { +- fprintf (stderr, "hivexsh [-dfw] [hivefile]\n"); ++ fprintf (stderr, "hivexsh [-dfwu] [hivefile]\n"); + exit (EXIT_FAILURE); + } + +@@ -115,7 +116,7 @@ main (int argc, char *argv[]) + + set_prompt_string (); + +- while ((c = getopt (argc, argv, "df:w")) != EOF) { ++ while ((c = getopt (argc, argv, "df:wu")) != EOF) { + switch (c) { + case 'd': + open_flags |= HIVEX_OPEN_DEBUG; +@@ -126,6 +127,10 @@ main (int argc, char *argv[]) + case 'w': + open_flags |= HIVEX_OPEN_WRITE; + break; ++ case 'u': ++ open_flags |= HIVEX_OPEN_UNSAFE; ++ unsafe = 1; ++ break; + default: + usage (); + } +@@ -771,6 +776,7 @@ cmd_lsval (char *key) + + hive_type t; + size_t len; ++ + if (hivex_value_type (h, values[i], &t, &len) == -1) + goto error; + +@@ -779,8 +785,12 @@ cmd_lsval (char *key) + case hive_t_expand_string: + case hive_t_link: { + char *str = hivex_value_string (h, values[i]); +- if (!str) +- goto error; ++ if (!str) { ++ if (unsafe) ++ continue; ++ else ++ goto error; ++ } + + if (t != hive_t_string) + printf ("str(%d):", t); +@@ -813,8 +823,12 @@ cmd_lsval (char *key) + default: { + unsigned char *data = + (unsigned char *) hivex_value_value (h, values[i], &t, &len); +- if (!data) +- goto error; ++ if (!data) { ++ if (unsafe) ++ continue; ++ else ++ goto error; ++ } + + printf ("hex(%d):", t); + size_t j; +-- +1.8.3.1 + diff --git a/SOURCES/0012-hivexregedit-allow-to-pass-HIVEX_OPEN_UNSAFE.patch b/SOURCES/0012-hivexregedit-allow-to-pass-HIVEX_OPEN_UNSAFE.patch new file mode 100644 index 0000000..53a5aff --- /dev/null +++ b/SOURCES/0012-hivexregedit-allow-to-pass-HIVEX_OPEN_UNSAFE.patch @@ -0,0 +1,168 @@ +From 362d5cd9b6527e4f9d3a3729afbe7cd90486c39d Mon Sep 17 00:00:00 2001 +From: Dawid Zamirski +Date: Thu, 16 Feb 2017 18:17:26 -0500 +Subject: [PATCH 12/12] hivexregedit: allow to pass HIVEX_OPEN_UNSAFE + +via new --unsafe flag. Also make --export catpure, log and skip over +errors when reading subkeys/values so that export in unsafe mode does +not abort at first sign of error. + +(cherry picked from commit 2610b1e089fa84d294f9925342929e3d7408c35b) +--- + perl/lib/Win/Hivex/Regedit.pm | 59 ++++++++++++++++++++++++++++++++++++++----- + regedit/hivexregedit | 20 ++++++++++++--- + 2 files changed, 70 insertions(+), 9 deletions(-) + +diff --git a/perl/lib/Win/Hivex/Regedit.pm b/perl/lib/Win/Hivex/Regedit.pm +index 8914f9e..355699e 100644 +--- a/perl/lib/Win/Hivex/Regedit.pm ++++ b/perl/lib/Win/Hivex/Regedit.pm +@@ -67,7 +67,7 @@ package Win::Hivex::Regedit; + use strict; + use warnings; + +-use Carp qw(croak confess); ++use Carp qw(croak carp confess); + use Encode qw(encode decode); + + require Exporter; +@@ -528,19 +528,51 @@ sub reg_export_node + print $fh "]\n"; + + my $unsafe_printable_strings = $params{unsafe_printable_strings}; ++ my $unsafe = $params{unsafe}; ++ ++ my @values; ++ my @safe_values; + + # Get the values. +- my @values = $h->node_values ($node); ++ if ($unsafe) { ++ my $have_vals = 0; ++ eval { ++ @values = $h->node_values ($node); ++ $have_vals = 1; ++ }; ++ ++ if (!$have_vals) { ++ carp "Failed to read node values at $path"; ++ } ++ } else { ++ @values = $h->node_values ($node); ++ } + + foreach (@values) { + use bytes; + + my $key = $h->value_key ($_); +- my ($type, $data) = $h->value_value ($_); +- $_ = { key => $key, type => $type, data => $data } ++ my ($type, $data); ++ ++ if ($unsafe) { ++ my $val_ok = 0; ++ eval { ++ ($type, $data) = $h->value_value ($_); ++ $val_ok = 1; ++ }; ++ ++ if (!$val_ok) { ++ carp "skipping unreadable value of key: $key in $path"; ++ next; ++ } ++ } else { ++ ($type, $data) = $h->value_value ($_); ++ } ++ ++ push @safe_values, { key => $key, type => $type, data => $data }; + } + +- @values = sort { $a->{key} cmp $b->{key} } @values; ++ @values = sort { $a->{key} cmp $b->{key} } @safe_values; + + # Print the values. + foreach (@values) { +@@ -573,7 +605,22 @@ sub reg_export_node + } + print $fh "\n"; + +- my @children = $h->node_children ($node); ++ my @children; ++ ++ if ($unsafe) { ++ my $have_children = 0; ++ eval { ++ @children = $h->node_children ($node); ++ $have_children = 1; ++ }; ++ ++ if (!$have_children) { ++ carp "Could not get children of $path"; ++ } ++ } else { ++ @children = $h->node_children ($node); ++ } ++ + @children = sort { $h->node_name ($a) cmp $h->node_name ($b) } @children; + reg_export_node ($h, $_, $fh, @_) foreach @children; + } +diff --git a/regedit/hivexregedit b/regedit/hivexregedit +index 0e534de..aa0ee6e 100755 +--- a/regedit/hivexregedit ++++ b/regedit/hivexregedit +@@ -252,6 +252,17 @@ into another program or stored in another hive. + + =cut + ++my $unsafe; ++ ++=item B<--unsafe> ++ ++Use heuristics to tolerate certain levels of corruption within hives. ++ ++This is unsafe but may allow to export/merge valid keys/values in an ++othewise corrupted hive. ++ ++=cut ++ + GetOptions ("help|?" => \$help, + "debug" => \$debug, + "merge|import" => \$merge, +@@ -259,6 +270,7 @@ GetOptions ("help|?" => \$help, + "prefix=s" => \$prefix, + "encoding=s" => \$encoding, + "unsafe-printable-strings" => \$unsafe_printable_strings, ++ "unsafe" => \$unsafe, + ) or pod2usage (2); + pod2usage (1) if $help; + +@@ -281,7 +293,8 @@ if ($merge) { # --merge (reg_import) + + my $hivefile = shift @ARGV; + +- my $h = Win::Hivex->open ($hivefile, write => 1, debug => $debug); ++ my $h = Win::Hivex->open ($hivefile, write => 1, debug => $debug, ++ unsafe => $unsafe); + + # Read from stdin unless other files have been specified. + unshift (@ARGV, '-') unless @ARGV; +@@ -312,13 +325,14 @@ if ($merge) { # --merge (reg_import) + my $hivefile = shift @ARGV; + my $key = shift @ARGV; + +- my $h = Win::Hivex->open ($hivefile, debug => $debug); ++ my $h = Win::Hivex->open ($hivefile, debug => $debug, unsafe => $unsafe); + + print "Windows Registry Editor Version 5.00\n\n"; + + reg_export ($h, $key, \*STDOUT, + prefix => $prefix, +- unsafe_printable_strings => $unsafe_printable_strings); ++ unsafe_printable_strings => $unsafe_printable_strings, ++ unsafe => $unsafe); + } + + =head1 SEE ALSO +-- +1.8.3.1 + diff --git a/SOURCES/generated.patch b/SOURCES/generated.patch new file mode 100644 index 0000000..b6ad060 --- /dev/null +++ b/SOURCES/generated.patch @@ -0,0 +1,272 @@ +Only in hivex-1.3.10/generator: .pod2text.data.version.2 +Only in hivex-1.3.10/generator: stamp-generator +diff -ur hivex-1.3.10.old/lib/hivex.h hivex-1.3.10/lib/hivex.h +--- hivex-1.3.10.old/lib/hivex.h 2014-01-10 10:00:53.000000000 +0000 ++++ hivex-1.3.10/lib/hivex.h 2017-02-17 16:17:58.114476857 +0000 +@@ -3,7 +3,7 @@ + * generator/generator.ml + * ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST. + * +- * Copyright (C) 2009-2014 Red Hat Inc. ++ * Copyright (C) 2009-2017 Red Hat Inc. + * Derived from code by Petter Nordahl-Hagen under a compatible license: + * Copyright (c) 1997-2007 Petter Nordahl-Hagen. + * Derived from code by Markus Stephany under a compatible license: +@@ -111,6 +111,8 @@ + #define HIVEX_OPEN_DEBUG 2 + /* Enable writes to the hive */ + #define HIVEX_OPEN_WRITE 4 ++ /* Enable heuristics to allow read/write of corrupted hives */ ++#define HIVEX_OPEN_UNSAFE 8 + + /* Array of (key, value) pairs passed to hivex_node_set_values. */ + struct hive_set_value { +diff -ur hivex-1.3.10.old/lib/hivex.pod hivex-1.3.10/lib/hivex.pod +--- hivex-1.3.10.old/lib/hivex.pod 2014-01-10 10:00:53.000000000 +0000 ++++ hivex-1.3.10/lib/hivex.pod 2017-02-17 16:17:58.137476198 +0000 +@@ -5,7 +5,7 @@ + generator/generator.ml + ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST. + +- Copyright (C) 2009-2014 Red Hat Inc. ++ Copyright (C) 2009-2017 Red Hat Inc. + Derived from code by Petter Nordahl-Hagen under a compatible license: + Copyright (c) 1997-2007 Petter Nordahl-Hagen. + Derived from code by Markus Stephany under a compatible license: +@@ -200,6 +200,13 @@ + + See L. + ++=item HIVEX_OPEN_UNSAFE ++ ++Open the hive in unsafe mode that enables heuristics to handle corrupted hives. ++ ++This may allow to read or write registry keys/values that appear intact in an ++otherwise corrupted hive. Use at your own risk. ++ + =back + + Returns a new hive handle. +@@ -346,7 +353,7 @@ + + Return the length of the key (name) of a (key, value) pair as produced + by C. The length can legitimately be 0, so errno is +-the necesary mechanism to check for errors. ++the necessary mechanism to check for errors. + + In the context of Windows Registries, a zero-length name means + that this value is the default key for this node in the tree. +diff -ur hivex-1.3.10.old/lib/hivex.syms hivex-1.3.10/lib/hivex.syms +--- hivex-1.3.10.old/lib/hivex.syms 2014-01-10 10:00:53.000000000 +0000 ++++ hivex-1.3.10/lib/hivex.syms 2017-02-17 16:17:58.140476112 +0000 +@@ -3,7 +3,7 @@ + # generator/generator.ml + # ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST. + # +-# Copyright (C) 2009-2014 Red Hat Inc. ++# Copyright (C) 2009-2017 Red Hat Inc. + # Derived from code by Petter Nordahl-Hagen under a compatible license: + # Copyright (c) 1997-2007 Petter Nordahl-Hagen. + # Derived from code by Markus Stephany under a compatible license: +diff -ur hivex-1.3.10.old/ocaml/hivex_c.c hivex-1.3.10/ocaml/hivex_c.c +--- hivex-1.3.10.old/ocaml/hivex_c.c 2014-01-10 10:00:53.000000000 +0000 ++++ hivex-1.3.10/ocaml/hivex_c.c 2017-02-17 16:17:58.161475510 +0000 +@@ -3,7 +3,7 @@ + * generator/generator.ml + * ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST. + * +- * Copyright (C) 2009-2014 Red Hat Inc. ++ * Copyright (C) 2009-2017 Red Hat Inc. + * Derived from code by Petter Nordahl-Hagen under a compatible license: + * Copyright (c) 1997-2007 Petter Nordahl-Hagen. + * Derived from code by Markus Stephany under a compatible license: +diff -ur hivex-1.3.10.old/ocaml/hivex.ml hivex-1.3.10/ocaml/hivex.ml +--- hivex-1.3.10.old/ocaml/hivex.ml 2014-01-10 10:00:53.000000000 +0000 ++++ hivex-1.3.10/ocaml/hivex.ml 2017-02-17 16:17:58.151475796 +0000 +@@ -3,7 +3,7 @@ + * generator/generator.ml + * ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST. + * +- * Copyright (C) 2009-2014 Red Hat Inc. ++ * Copyright (C) 2009-2017 Red Hat Inc. + * Derived from code by Petter Nordahl-Hagen under a compatible license: + * Copyright (c) 1997-2007 Petter Nordahl-Hagen. + * Derived from code by Markus Stephany under a compatible license: +@@ -56,6 +56,7 @@ + | OPEN_VERBOSE (** Verbose messages *) + | OPEN_DEBUG (** Debug messages *) + | OPEN_WRITE (** Enable writes to the hive *) ++ | OPEN_UNSAFE (** Enable heuristics to allow read/write of corrupted hives *) + + type set_value = { + key : string; +diff -ur hivex-1.3.10.old/ocaml/hivex.mli hivex-1.3.10/ocaml/hivex.mli +--- hivex-1.3.10.old/ocaml/hivex.mli 2014-01-10 10:00:53.000000000 +0000 ++++ hivex-1.3.10/ocaml/hivex.mli 2017-02-17 16:17:58.147475911 +0000 +@@ -3,7 +3,7 @@ + * generator/generator.ml + * ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST. + * +- * Copyright (C) 2009-2014 Red Hat Inc. ++ * Copyright (C) 2009-2017 Red Hat Inc. + * Derived from code by Petter Nordahl-Hagen under a compatible license: + * Copyright (c) 1997-2007 Petter Nordahl-Hagen. + * Derived from code by Markus Stephany under a compatible license: +@@ -63,6 +63,7 @@ + | OPEN_VERBOSE (** Verbose messages *) + | OPEN_DEBUG (** Debug messages *) + | OPEN_WRITE (** Enable writes to the hive *) ++ | OPEN_UNSAFE (** Enable heuristics to allow read/write of corrupted hives *) + (** Open flags for {!open_file} call. *) + + type set_value = { +diff -ur hivex-1.3.10.old/perl/Hivex.xs hivex-1.3.10/perl/Hivex.xs +--- hivex-1.3.10.old/perl/Hivex.xs 2014-01-13 22:20:34.000000000 +0000 ++++ hivex-1.3.10/perl/Hivex.xs 2017-02-17 16:17:58.172475194 +0000 +@@ -3,7 +3,7 @@ + * generator/generator.ml + * ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST. + * +- * Copyright (C) 2009-2014 Red Hat Inc. ++ * Copyright (C) 2009-2017 Red Hat Inc. + * Derived from code by Petter Nordahl-Hagen under a compatible license: + * Copyright (c) 1997-2007 Petter Nordahl-Hagen. + * Derived from code by Markus Stephany under a compatible license: +diff -ur hivex-1.3.10.old/perl/lib/Win/Hivex.pm hivex-1.3.10/perl/lib/Win/Hivex.pm +--- hivex-1.3.10.old/perl/lib/Win/Hivex.pm 2014-01-10 10:00:53.000000000 +0000 ++++ hivex-1.3.10/perl/lib/Win/Hivex.pm 2017-02-17 16:17:58.166475366 +0000 +@@ -3,7 +3,7 @@ + # generator/generator.ml + # ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST. + # +-# Copyright (C) 2009-2014 Red Hat Inc. ++# Copyright (C) 2009-2017 Red Hat Inc. + # Derived from code by Petter Nordahl-Hagen under a compatible license: + # Copyright (c) 1997-2007 Petter Nordahl-Hagen. + # Derived from code by Markus Stephany under a compatible license: +@@ -66,7 +66,8 @@ + $h = Win::Hivex->open ($filename, + [verbose => 1,] + [debug => 1,] +- [write => 1,]) ++ [write => 1,] ++ [unsafe => 1,]) + + Open a Windows Registry binary hive file. + +@@ -94,6 +95,8 @@ + $flags += 2 if $flags{debug}; + # Enable writes to the hive + $flags += 4 if $flags{write}; ++ # Enable heuristics to allow read/write of corrupted hives ++ $flags += 8 if $flags{unsafe}; + + my $self = Win::Hivex::_open ($filename, $flags); + bless $self, $class; +@@ -212,7 +215,7 @@ + + Return the length of the key (name) of a (key, value) pair as produced + by C. The length can legitimately be 0, so errno is +-the necesary mechanism to check for errors. ++the necessary mechanism to check for errors. + + In the context of Windows Registries, a zero-length name means + that this value is the default key for this node in the tree. +@@ -388,7 +391,7 @@ + + =head1 COPYRIGHT + +-Copyright (C) 2009-2014 Red Hat Inc. ++Copyright (C) 2009-2017 Red Hat Inc. + + =head1 LICENSE + +diff -ur hivex-1.3.10.old/python/hivex.py hivex-1.3.10/python/hivex.py +--- hivex-1.3.10.old/python/hivex.py 2014-01-10 10:00:53.000000000 +0000 ++++ hivex-1.3.10/python/hivex.py 2017-02-17 16:17:58.177475051 +0000 +@@ -3,7 +3,7 @@ + # generator/generator.ml + # ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST. + # +-# Copyright (C) 2009-2014 Red Hat Inc. ++# Copyright (C) 2009-2017 Red Hat Inc. + # Derived from code by Petter Nordahl-Hagen under a compatible license: + # Copyright (c) 1997-2007 Petter Nordahl-Hagen. + # Derived from code by Markus Stephany under a compatible license: +@@ -39,7 +39,7 @@ + class Hivex(object): + """Instances of this class are hivex API handles.""" + +- def __init__ (self, filename, verbose = False, debug = False, write = False): ++ def __init__ (self, filename, verbose = False, debug = False, write = False, unsafe = False): + """Create a new hivex handle.""" + flags = 0 + # Verbose messages +@@ -48,6 +48,8 @@ + if debug: flags += 2 + # Enable writes to the hive + if write: flags += 4 ++ # Enable heuristics to allow read/write of corrupted hives ++ if unsafe: flags += 8 + self._o = libhivexmod.open (filename, flags) + + def __del__ (self): +diff -ur hivex-1.3.10.old/python/hivex-py.c hivex-1.3.10/python/hivex-py.c +--- hivex-1.3.10.old/python/hivex-py.c 2014-04-23 15:47:20.000000000 +0100 ++++ hivex-1.3.10/python/hivex-py.c 2017-02-17 16:17:58.186474793 +0000 +@@ -3,7 +3,7 @@ + * generator/generator.ml + * ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST. + * +- * Copyright (C) 2009-2014 Red Hat Inc. ++ * Copyright (C) 2009-2017 Red Hat Inc. + * Derived from code by Petter Nordahl-Hagen under a compatible license: + * Copyright (c) 1997-2007 Petter Nordahl-Hagen. + * Derived from code by Markus Stephany under a compatible license: +diff -ur hivex-1.3.10.old/ruby/ext/hivex/_hivex.c hivex-1.3.10/ruby/ext/hivex/_hivex.c +--- hivex-1.3.10.old/ruby/ext/hivex/_hivex.c 2014-01-13 22:20:34.000000000 +0000 ++++ hivex-1.3.10/ruby/ext/hivex/_hivex.c 2017-02-17 16:17:59.440438835 +0000 +@@ -3,7 +3,7 @@ + * generator/generator.ml + * ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST. + * +- * Copyright (C) 2009-2014 Red Hat Inc. ++ * Copyright (C) 2009-2017 Red Hat Inc. + * Derived from code by Petter Nordahl-Hagen under a compatible license: + * Copyright (c) 1997-2007 Petter Nordahl-Hagen. + * Derived from code by Markus Stephany under a compatible license: +@@ -121,6 +121,14 @@ + * read-only. + * + * See "WRITING TO HIVE FILES" in hivex(3). ++ * ++ * HIVEX_OPEN_UNSAFE ++ * Open the hive in unsafe mode that enables heuristics ++ * to handle corrupted hives. ++ * ++ * This may allow to read or write registry keys/values ++ * that appear intact in an otherwise corrupted hive. ++ * Use at your own risk. + * + * + * (For the C API documentation for this function, see +@@ -137,6 +145,8 @@ + flags += 2; + if (RTEST (rb_hash_lookup (flagsv, ID2SYM (rb_intern ("write"))))) + flags += 4; ++ if (RTEST (rb_hash_lookup (flagsv, ID2SYM (rb_intern ("unsafe"))))) ++ flags += 8; + + hive_h *r; + +@@ -580,8 +590,8 @@ + * + * Return the length of the key (name) of a (key, value) + * pair as produced by "h.value_key". The length can +- * legitimately be 0, so errno is the necesary mechanism to +- * check for errors. ++ * legitimately be 0, so errno is the necessary mechanism ++ * to check for errors. + * + * In the context of Windows Registries, a zero-length name + * means that this value is the default key for this node diff --git a/SOURCES/hivex-1.3.8-dirs.patch b/SOURCES/hivex-1.3.8-dirs.patch deleted file mode 100644 index 3f0f652..0000000 --- a/SOURCES/hivex-1.3.8-dirs.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff -ur hivex-1.3.8.old/perl/Makefile.am hivex-1.3.8/perl/Makefile.am ---- hivex-1.3.8.old/perl/Makefile.am 2013-07-25 15:09:00.000000000 +0100 -+++ hivex-1.3.8/perl/Makefile.am 2013-07-25 23:14:10.952149773 +0100 -@@ -43,7 +43,7 @@ - - TESTS_ENVIRONMENT = ../run - --INSTALLDIRS = site -+INSTALLDIRS = vendor - - all: Makefile-pl src_deps - $(MAKE) -f Makefile-pl diff --git a/SPECS/hivex.spec b/SPECS/hivex.spec index 81e7343..24b555f 100644 --- a/SPECS/hivex.spec +++ b/SPECS/hivex.spec @@ -7,7 +7,7 @@ Name: hivex Version: 1.3.10 -Release: 5.7%{?dist} +Release: 5.8%{?dist} Summary: Read and write Windows Registry binary hive files License: LGPLv2 @@ -15,22 +15,42 @@ URL: http://libguestfs.org/ Source0: http://libguestfs.org/download/hivex/%{name}-%{version}.tar.gz +# The RHEL 7 patches are stored in the upstream git repository, +# in the branch called 'rhel-7.4', ie: +# https://github.com/libguestfs/hivex/tree/rhel-7.4 + # Fix Perl directory install path. -Patch0: %{name}-1.3.8-dirs.patch -BuildRequires: autoconf, automake, libtool, gettext-devel +Patch0001: 0001-Fix-Perl-directory-install-path.patch -# Upstream patches to fix RHBZ#1145056 -Patch1: 0001-value-Set-errno-0-on-non-error-path-in-hivex_value_d.patch -Patch2: 0002-hivexml-Tidy-up-error-handling-and-printing.patch -Patch3: 0001-lib-Don-t-leak-errno-from-_hivex_recode-function.patch +# Upstream patches to fix RHBZ#1145056. +Patch0002: 0002-value-Set-errno-0-on-non-error-path-in-hivex_value_d.patch +Patch0003: 0003-hivexml-Tidy-up-error-handling-and-printing.patch +Patch0004: 0004-lib-Don-t-leak-errno-from-_hivex_recode-function.patch -# Upstream patches to fix RHBZ#1158992 -Patch4: 0001-handle-Refuse-to-open-files-8192-bytes-in-size.patch -Patch5: 0002-handle-Check-that-pages-do-not-extend-beyond-the-end.patch +# Upstream patches to fix RHBZ#1158992. +Patch0005: 0005-handle-Refuse-to-open-files-8192-bytes-in-size.patch +Patch0006: 0006-handle-Check-that-pages-do-not-extend-beyond-the-end.patch # Fix typo in documentation (RHBZ#1099286). -# Patch contains upstream fix + generated code. -Patch6: 0001-generator-Fix-a-spelling-mistake-in-the-documentatio.patch +Patch0007: 0007-generator-Fix-a-spelling-mistake-in-the-documentatio.patch + +# Tolerate corruption in some hives (RHBZ#1423436). +Patch0008: 0008-add-HIVEX_OPEN_UNSAFE-flag.patch +Patch0009: 0009-lib-change-how-hbin-sections-are-read.patch +Patch0010: 0010-lib-allow-to-walk-registry-with-corrupted-blocks.patch +Patch0011: 0011-hivexsh-add-u-flag-for-HIVEX_OPEN_UNSAFE.patch +Patch0012: 0012-hivexregedit-allow-to-pass-HIVEX_OPEN_UNSAFE.patch + +# Patch generated code (because we can't assume we have OCaml on all +# arches). To construct this you need to do 'make prep', run the +# generator by hand, and diff before and after. +Patch9999: generated.patch + +# Use git to apply patches. +BuildRequires: git + +# Since some patches touch autotools file, we need to rerun autoreconf. +BuildRequires: autoconf, automake, libtool, gettext-devel BuildRequires: perl BuildRequires: perl-Test-Simple @@ -159,15 +179,22 @@ ruby-%{name} contains Ruby bindings for %{name}. %prep %setup -q -%patch0 -p1 -b .dirs -autoreconf -i +# Use git to apply patches. +# http://rwmj.wordpress.com/2011/08/09/nice-rpm-git-patch-management-trick/ +git init +git config user.email "libguestfs@redhat.com" +git config user.name "libguestfs" +git add . +git commit -a -q -m "%{version} baseline" +for f in %{patches}; do + if [[ ! "$f" =~ generated.patch ]]; then + git am "$f" + else + patch -p1 < "$f" + fi +done -%patch1 -p1 -%patch2 -p1 -%patch3 -p1 -%patch4 -p1 -%patch5 -p1 -%patch6 -p1 +autoreconf -i %build %configure --disable-static @@ -269,6 +296,11 @@ rm $RPM_BUILD_ROOT%{python_sitearch}/libhivexmod.la %changelog +* Fri Feb 17 2017 Richard W.M. Jones - 1.3.10-5.8 +- Tolerate corruption in some hives + resolves: rhbz#1423436 +- Switch to using git to manage patches. + * Mon Nov 17 2014 Richard W.M. Jones - 1.3.10-5.7 - Fix: "Argument list too long" when using virt-v2v on Windows guest with French copy of Citrix installed