|
|
7483d8 |
From 61f4928dcc31b91aaf3bcbcf2898f8f09586a213 Mon Sep 17 00:00:00 2001
|
|
|
7483d8 |
From: "Richard W.M. Jones" <rjones@redhat.com>
|
|
|
7483d8 |
Date: Thu, 15 Apr 2021 15:50:13 +0100
|
|
|
7483d8 |
Subject: [PATCH] lib/handle.c: Bounds check for block exceeding page length
|
|
|
7483d8 |
(CVE-2021-3504)
|
|
|
7483d8 |
|
|
|
7483d8 |
Hives are encoded as fixed-sized pages containing smaller variable-
|
|
|
7483d8 |
length blocks:
|
|
|
7483d8 |
|
|
|
7483d8 |
+-------------------+-------------------+-------------------+--
|
|
|
7483d8 |
| header |[ blk ][blk][ blk ]|[blk][blk][blk] |
|
|
|
7483d8 |
+-------------------+-------------------+-------------------+--
|
|
|
7483d8 |
|
|
|
7483d8 |
Blocks should not straddle a page boundary. However because blocks
|
|
|
7483d8 |
contain a 32 bit length field it is possible to construct an invalid
|
|
|
7483d8 |
hive where the last block in a page overlaps either the next page or
|
|
|
7483d8 |
the end of the file:
|
|
|
7483d8 |
|
|
|
7483d8 |
+-------------------+-------------------+
|
|
|
7483d8 |
| header |[ blk ][blk][ blk ..... ]
|
|
|
7483d8 |
+-------------------+-------------------+
|
|
|
7483d8 |
|
|
|
7483d8 |
Hivex lacked a bounds check and would process the registry. Because
|
|
|
7483d8 |
the rest of the code assumes this situation can never happen it was
|
|
|
7483d8 |
possible to have a block containing some field (eg. a registry key
|
|
|
7483d8 |
name) which would extend beyond the end of the file. Hivex mmaps or
|
|
|
7483d8 |
mallocs the file, causing hivex to read memory beyond the end of the
|
|
|
7483d8 |
mapped region, resulting in reading other memory structures or a
|
|
|
7483d8 |
crash. (Writing beyond the end of the mapped region seems to be
|
|
|
7483d8 |
impossible because we always allocate a new page before writing.)
|
|
|
7483d8 |
|
|
|
7483d8 |
This commit adds a check which rejects the malformed registry on
|
|
|
7483d8 |
hivex_open.
|
|
|
7483d8 |
|
|
|
7483d8 |
Credit: Jeremy Galindo, Sr Security Engineer, Datto.com
|
|
|
7483d8 |
Signed-off-by: Richard W.M. Jones <rjones@redhat.com>
|
|
|
7483d8 |
Fixes: CVE-2021-3504
|
|
|
7483d8 |
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1949687
|
|
|
7483d8 |
---
|
|
|
7483d8 |
lib/handle.c | 12 ++++++++++--
|
|
|
7483d8 |
1 file changed, 10 insertions(+), 2 deletions(-)
|
|
|
7483d8 |
|
|
|
7483d8 |
diff --git a/lib/handle.c b/lib/handle.c
|
|
|
7483d8 |
index 88b1563f..2e4231a5 100644
|
|
|
7483d8 |
--- a/lib/handle.c
|
|
|
7483d8 |
+++ b/lib/handle.c
|
|
|
7483d8 |
@@ -353,8 +353,8 @@ hivex_open (const char *filename, int flags)
|
|
|
7483d8 |
#pragma GCC diagnostic pop
|
|
|
7483d8 |
if (is_root || !h->unsafe) {
|
|
|
7483d8 |
SET_ERRNO (ENOTSUP,
|
|
|
7483d8 |
- "%s, the block at 0x%zx has invalid size %" PRIu32
|
|
|
7483d8 |
- ", bad registry",
|
|
|
7483d8 |
+ "%s, the block at 0x%zx size %" PRIu32
|
|
|
7483d8 |
+ " <= 4 or not a multiple of 4, bad registry",
|
|
|
7483d8 |
filename, blkoff, le32toh (block->seg_len));
|
|
|
7483d8 |
goto error;
|
|
|
7483d8 |
} else {
|
|
|
7483d8 |
@@ -365,6 +365,14 @@ hivex_open (const char *filename, int flags)
|
|
|
7483d8 |
}
|
|
|
7483d8 |
}
|
|
|
7483d8 |
|
|
|
7483d8 |
+ if (blkoff + seg_len > off + page_size) {
|
|
|
7483d8 |
+ SET_ERRNO (ENOTSUP,
|
|
|
7483d8 |
+ "%s, the block at 0x%zx size %" PRIu32
|
|
|
7483d8 |
+ " extends beyond the current page, bad registry",
|
|
|
7483d8 |
+ filename, blkoff, le32toh (block->seg_len));
|
|
|
7483d8 |
+ goto error;
|
|
|
7483d8 |
+ }
|
|
|
7483d8 |
+
|
|
|
7483d8 |
if (h->msglvl >= 2) {
|
|
|
7483d8 |
unsigned char *id = (unsigned char *) block->id;
|
|
|
7483d8 |
int id0 = id[0], id1 = id[1];
|
|
|
7483d8 |
--
|
|
|
7483d8 |
2.29.2
|
|
|
7483d8 |
|