From 405b2da3f3a6c3222b71141b4f41cdeb2b45191e Mon Sep 17 00:00:00 2001 From: Mikhail Zaslonko Date: Mon, 29 Jun 2026 19:46:21 +0200 Subject: [PATCH] zdump/dfi_vmcoreinfo: Validate vmcoreinfo value length before memcpy MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit vmcoreinfo_item() copies a key's value string from the vmcoreinfo heap blob into the caller's buffer using memcpy() without checking the source length. The length is derived from the distance between the '=' separator and the next '\n' (or '\0') in the blob, which is bounded only by the total vmcoreinfo size. A crafted dump with a vmcoreinfo value >= 1024 bytes would overflow the buffer. Additionally, the len parameter of vmcoreinfo_item() was declared UNUSED and never checked. Fix by computing val_len before the copy and returning -1 if val_len >= len. Change len type from int to size_t, which is natural for a buffer size, drops the need for a negativity guard, and makes the call site passing sizeof(str) type-consistent. Write directly into the caller's buf, instead of going through the intermediate str[]. Replace two strchr() calls with a single strchrnul(). Signed-off-by: Mikhail Zaslonko Reviewed-by: Alexander Egorenkov Signed-off-by: Jan Höppner --- zdump/dfi_vmcoreinfo.c | 19 ++++++++++--------- zdump/dfi_vmcoreinfo.h | 2 +- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/zdump/dfi_vmcoreinfo.c b/zdump/dfi_vmcoreinfo.c index deab3e29..4728301a 100644 --- a/zdump/dfi_vmcoreinfo.c +++ b/zdump/dfi_vmcoreinfo.c @@ -169,13 +169,14 @@ const char *dfi_vmcoreinfo_get(void) } /* - * Generic function: Return vmcoreinfo item (-1 on failure) + * Generic function: Return vmcoreinfo item (-1 on failure). */ -static int vmcoreinfo_item(char *buf, int UNUSED(len), const char *fmt, +static int vmcoreinfo_item(char *buf, size_t len, const char *fmt, const char *sym) { char str[1024], *sym_str, *sym_str_end; + size_t val_len; if (!l.vmcoreinfo) return -1; @@ -187,12 +188,12 @@ static int vmcoreinfo_item(char *buf, int UNUSED(len), const char *fmt, if (!sym_str) return -1; sym_str += strlen(str); - sym_str_end = strchr(sym_str, '\n'); - if (!sym_str_end) - sym_str_end = strchr(sym_str, '\0'); - memset(str, 0, sizeof(str)); - memcpy(str, sym_str, (unsigned long) (sym_str_end - sym_str)); - strcpy(buf, str); + sym_str_end = strchrnul(sym_str, '\n'); + val_len = (size_t)(sym_str_end - sym_str); + if (val_len >= len) + return -1; + memcpy(buf, sym_str, val_len); + buf[val_len] = '\0'; return 0; } @@ -216,7 +217,7 @@ static int vmcoreinfo_item_ulong(unsigned long *val, const char *fmt, /* * Return vmcoreinfo tag (-1 on failure) */ -int dfi_vmcoreinfo_tag(char *str, int len, const char *sym) +int dfi_vmcoreinfo_tag(char *str, size_t len, const char *sym) { return vmcoreinfo_item(str, len, NULL, sym); } diff --git a/zdump/dfi_vmcoreinfo.h b/zdump/dfi_vmcoreinfo.h index 0cb5a171..d6617a1b 100644 --- a/zdump/dfi_vmcoreinfo.h +++ b/zdump/dfi_vmcoreinfo.h @@ -10,7 +10,7 @@ void dfi_vmcoreinfo_init(void); const char *dfi_vmcoreinfo_get(void); -int dfi_vmcoreinfo_tag(char *str, int len, const char *sym); +int dfi_vmcoreinfo_tag(char *str, size_t len, const char *sym); int dfi_vmcoreinfo_symbol(unsigned long *val, const char *sym); int dfi_vmcoreinfo_offset(unsigned long *offs, const char *sym); int dfi_vmcoreinfo_size(unsigned long *size, const char *sym);