When dump_init() reads the guest VMCOREINFO note and decides the note
header is invalid (oversized name/desc or note_size larger than the
buffer read from the guest), it frees s->guest_note and sets it to NULL
but leaves s->guest_note_size at its previous value.
dump_process() later dispatches on the requested format. For
DUMP_GUEST_MEMORY_FORMAT_WIN_DMP it calls create_win_dump(), which in
dump/win_dump-x86.c dereferences s->guest_note unconditionally:
WinDumpHeader *h = (void *)(s->guest_note + VMCOREINFO_ELF_NOTE_HDR_SIZE);
so a NULL s->guest_note results in a NULL-pointer dereference (crash /
host DoS) instead of the intended clean error.
guest_note is only ever non-NULL when guest_note_size was set together
with it, so make the two consistent: whenever the note is freed and
reset to NULL, also reset guest_note_size to 0, and harden
create_win_dump() to reject a missing note before dereferencing it.
Signed-off-by: Hongyan Xu <[email protected]>
---
dump/dump.c | 1 +
dump/win_dump-x86.c | 5 +++++
2 files changed, 6 insertions(+)
diff --git a/dump/dump.c b/dump/dump.c
index 52be7258a5..a2073cea5d 100644
--- a/dump/dump.c
+++ b/dump/dump.c
@@ -1906,6 +1906,7 @@ static void dump_init(DumpState *s, int fd, bool
has_format,
warn_report("Invalid guest note header");
g_free(s->guest_note);
s->guest_note = NULL;
+ s->guest_note_size = 0;
} else {
vmcoreinfo_update_phys_base(s);
s->note_size += s->guest_note_size;
diff --git a/dump/win_dump-x86.c b/dump/win_dump-x86.c
index 0dd0c503c5..97c5e3e0da 100644
--- a/dump/win_dump-x86.c
+++ b/dump/win_dump-x86.c
@@ -445,6 +445,11 @@ bool win_dump_available(Error **errp)
void create_win_dump(DumpState *s, Error **errp)
{
+ if (!s->guest_note) {
+ error_setg(errp, "win-dump: no vmcoreinfo note available");
+ return;
+ }
+
WinDumpHeader *h = (void *)(s->guest_note + VMCOREINFO_ELF_NOTE_HDR_SIZE);
X86CPU *first_x86_cpu = X86_CPU(first_cpu);
uint64_t saved_cr3 = first_x86_cpu->env.cr[3];
--
2.50.1.windows.1