From d3ac9f336546d190c4e3f830ec8a7fb6549d4955 Mon Sep 17 00:00:00 2001 From: Mikhail Zaslonko Date: Mon, 29 Jun 2026 18:47:21 +0200 Subject: [PATCH] zdump/dfi_vmdump: Validate ADSR sec5_len before buffer read MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The 16-bit sec5_len field from the ADSR record was used directly as the byte count for zg_read() and ebc_2_asc() into a pair of 1024-byte stack buffers. A crafted VMDUMP file with sec5_len > 1024 would overflow both buffers and write past the stack frame. The overflow is only reachable when zgetdump is invoked with the -V (verbose) flag, but that is a common diagnostic usage. Section 5 contains a human-readable dump symptom string used only for display purposes. Truncate sec5_len to sizeof(buf) - 1 so that oversized values are silently clamped rather than causing an abort, and the symptom string is still printed up to the buffer limit. Signed-off-by: Mikhail Zaslonko Reviewed-by: Alexander Egorenkov Signed-off-by: Jan Höppner --- zdump/dfi_vmdump.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/zdump/dfi_vmdump.c b/zdump/dfi_vmdump.c index 7161cdd6..088a66de 100644 --- a/zdump/dfi_vmdump.c +++ b/zdump/dfi_vmdump.c @@ -30,6 +30,8 @@ #include "lib/util_log.h" #include "lib/util_libc.h" +#define SYMPTOM_STR_MAX_LEN 1024 + static struct { struct vmd_adsr adsr; /* Dump file symptom record */ struct vmd_fmbk fmbk; /* Dump file map record */ @@ -180,17 +182,21 @@ static void vmdump64big_init(void) zg_read(g.fh, &l.adsr, sizeof(l.adsr), ZG_CHECK); if (g.opts.verbose) { - u8 buf_asc[1024], buf[1024]; + u8 buf_asc[SYMPTOM_STR_MAX_LEN], buf[SYMPTOM_STR_MAX_LEN]; + const u16 sec5_len = MIN(l.adsr.sec5_len, SYMPTOM_STR_MAX_LEN - 1); zg_seek(g.fh, l.adsr.sec5_offset, ZG_CHECK); - zg_read(g.fh, buf, l.adsr.sec5_len, ZG_CHECK); - ebc_2_asc(buf, buf_asc, l.adsr.sec5_len); - for (i = 0; i < l.adsr.sec5_len; i++) { + zg_read(g.fh, buf, sec5_len, ZG_CHECK); + ebc_2_asc(buf, buf_asc, sec5_len); + for (i = 0; i < sec5_len; i++) { if (buf_asc[i] == 0 || iscntrl(buf_asc[i])) buf_asc[i] = ' '; } - buf_asc[l.adsr.sec5_len] = 0; - util_log_print(UTIL_LOG_DEBUG, "Symptom string: %s\n", buf_asc); + buf_asc[sec5_len] = 0; + if (sec5_len < l.adsr.sec5_len) + STDERR("Warning: Symptom string too long, adsr.sec5_len = %#x\n", l.adsr.sec5_len); + util_log_print(UTIL_LOG_DEBUG, "Symptom string%s: %s\n", + sec5_len < l.adsr.sec5_len ? "(TRUNCATED)" : "", buf_asc); } /* Record 2: fmbk */