zdump/dfi_vmdump: Validate ADSR sec5_len before buffer read

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 <zaslonko@linux.ibm.com>
Reviewed-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
This commit is contained in:
Mikhail Zaslonko
2026-06-29 18:47:21 +02:00
committed by Jan Höppner
parent 7535682b1b
commit d3ac9f3365

View File

@@ -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 */