zdump/dfi_vmcoreinfo: Validate vmcoreinfo value length before memcpy

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 <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 19:46:21 +02:00
committed by Jan Höppner
parent d3ac9f3365
commit 405b2da3f3
2 changed files with 11 additions and 10 deletions

View File

@@ -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) const char *sym)
{ {
char str[1024], *sym_str, *sym_str_end; char str[1024], *sym_str, *sym_str_end;
size_t val_len;
if (!l.vmcoreinfo) if (!l.vmcoreinfo)
return -1; return -1;
@@ -187,12 +188,12 @@ static int vmcoreinfo_item(char *buf, int UNUSED(len), const char *fmt,
if (!sym_str) if (!sym_str)
return -1; return -1;
sym_str += strlen(str); sym_str += strlen(str);
sym_str_end = strchr(sym_str, '\n'); sym_str_end = strchrnul(sym_str, '\n');
if (!sym_str_end) val_len = (size_t)(sym_str_end - sym_str);
sym_str_end = strchr(sym_str, '\0'); if (val_len >= len)
memset(str, 0, sizeof(str)); return -1;
memcpy(str, sym_str, (unsigned long) (sym_str_end - sym_str)); memcpy(buf, sym_str, val_len);
strcpy(buf, str); buf[val_len] = '\0';
return 0; return 0;
} }
@@ -216,7 +217,7 @@ static int vmcoreinfo_item_ulong(unsigned long *val, const char *fmt,
/* /*
* Return vmcoreinfo tag (-1 on failure) * 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); return vmcoreinfo_item(str, len, NULL, sym);
} }

View File

@@ -10,7 +10,7 @@
void dfi_vmcoreinfo_init(void); void dfi_vmcoreinfo_init(void);
const char *dfi_vmcoreinfo_get(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_symbol(unsigned long *val, const char *sym);
int dfi_vmcoreinfo_offset(unsigned long *offs, const char *sym); int dfi_vmcoreinfo_offset(unsigned long *offs, const char *sym);
int dfi_vmcoreinfo_size(unsigned long *size, const char *sym); int dfi_vmcoreinfo_size(unsigned long *size, const char *sym);