[PATCH v4 10/12] efi/cper: Pass buffer length to memory location helpers

From: Pierre Gondois

Date: Fri Nov 13 2026 - 14:39:08 EST


Add a length parameter to:
- cper_mem_err_location()
- cper_mem_err2_location()
to prevent potential buffer overflows/truncated messages.

Signed-off-by: Pierre Gondois <pierre.gondois@xxxxxxx>
---
drivers/edac/ghes_edac.c | 4 ++--
drivers/firmware/efi/cper.c | 20 +++++++++-----------
include/linux/cper.h | 4 ++--
3 files changed, 13 insertions(+), 15 deletions(-)

diff --git a/drivers/edac/ghes_edac.c b/drivers/edac/ghes_edac.c
index 075328d1bb7d..f0ca61bddee6 100644
--- a/drivers/edac/ghes_edac.c
+++ b/drivers/edac/ghes_edac.c
@@ -357,7 +357,7 @@ static int ghes_edac_report_mem_error(struct notifier_block *nb,

len = sizeof(e->location);
p = e->location;
- p += cper_mem_err_location(&cmem, p);
+ p += cper_mem_err_location(&cmem, p, len);

if (mem_err->validation_bits & CPER_MEM_VALID_MODULE_HANDLE) {
struct dimm_info *dimm;
@@ -472,7 +472,7 @@ static int ghes_edac_report_mem_error2(struct notifier_block *nb,
/* Memory error location, mapped on e->location */
len = sizeof(e->location);
p = e->location;
- p += cper_mem_err2_location(mem_err, p);
+ p += cper_mem_err2_location(mem_err, p, len);

if (mem_err->validation_bits & CPER_MEM2_VALID_MODULE_HANDLE) {
struct dimm_info *dimm = NULL;
diff --git a/drivers/firmware/efi/cper.c b/drivers/firmware/efi/cper.c
index 0c38ff65ee0b..89ebd3cc6123 100644
--- a/drivers/firmware/efi/cper.c
+++ b/drivers/firmware/efi/cper.c
@@ -298,15 +298,14 @@ const char *cper_mem_err_status_str(u64 status)
}
EXPORT_SYMBOL_GPL(cper_mem_err_status_str);

-int cper_mem_err_location(struct cper_mem_err_compact *mem, char *msg)
+int cper_mem_err_location(struct cper_mem_err_compact *mem, char *msg, size_t len)
{
- u32 len, n;
+ u32 n;

- if (!msg)
+ if (!msg || !len)
return 0;

n = 0;
- len = CPER_REC_LEN;
if (mem->validation_bits & CPER_MEM_VALID_NODE)
n += scnprintf(msg + n, len - n, "node:%d ", mem->node);
if (mem->validation_bits & CPER_MEM_VALID_CARD)
@@ -419,7 +418,7 @@ const char *cper_mem_err_unpack(struct trace_seq *p,
const char *ret = trace_seq_buffer_ptr(p);
char rcd_decode_str[CPER_REC_LEN];

- if (cper_mem_err_location(cmem, rcd_decode_str))
+ if (cper_mem_err_location(cmem, rcd_decode_str, sizeof(rcd_decode_str)))
trace_seq_printf(p, "%s", rcd_decode_str);
if (cper_dimm_err_location(cmem, rcd_decode_str, sizeof(rcd_decode_str)))
trace_seq_printf(p, "%s", rcd_decode_str);
@@ -451,7 +450,7 @@ static void cper_print_mem(const char *pfx, const struct cper_sec_mem_err *mem,
printk("%s""physical_address_mask: 0x%016llx\n",
pfx, mem->physical_addr_mask);
cper_mem_err_pack(mem, &cmem);
- if (cper_mem_err_location(&cmem, rcd_decode_str))
+ if (cper_mem_err_location(&cmem, rcd_decode_str, sizeof(rcd_decode_str)))
printk("%s%s\n", pfx, rcd_decode_str);
if (mem->validation_bits & CPER_MEM_VALID_ERROR_TYPE) {
u8 etype = mem->error_type;
@@ -462,15 +461,14 @@ static void cper_print_mem(const char *pfx, const struct cper_sec_mem_err *mem,
printk("%s%s\n", pfx, rcd_decode_str);
}

-int cper_mem_err2_location(const struct cper_sec_mem_err2 *mem, char *msg)
+int cper_mem_err2_location(const struct cper_sec_mem_err2 *mem, char *msg, size_t len)
{
- u32 len, n;
+ u32 n;

- if (!msg)
+ if (!msg || !len)
return 0;

n = 0;
- len = CPER_REC_LEN;
if (mem->validation_bits & CPER_MEM2_VALID_NODE)
n += scnprintf(msg + n, len - n, "node:%d ", mem->node);
if (mem->validation_bits & CPER_MEM2_VALID_CARD)
@@ -551,7 +549,7 @@ static void cper_print_mem2(const char *pfx, const struct cper_sec_mem_err2 *mem
if (mem->validation_bits & CPER_MEM2_VALID_PA_MASK)
printk("%sphysical_address_mask: 0x%016llx\n", pfx,
mem->physical_addr_mask);
- if (cper_mem_err2_location(mem, rcd_decode_str))
+ if (cper_mem_err2_location(mem, rcd_decode_str, sizeof(rcd_decode_str)))
printk("%s%s\n", pfx, rcd_decode_str);
if (mem->validation_bits & CPER_MEM2_VALID_ERROR_TYPE)
printk("%serror_type: %u, %s\n", pfx, mem->error_type,
diff --git a/include/linux/cper.h b/include/linux/cper.h
index 4338c216b1dc..db69995a43bf 100644
--- a/include/linux/cper.h
+++ b/include/linux/cper.h
@@ -654,10 +654,10 @@ void cper_print_proc_arm(const char *pfx,
u32 length);
void cper_print_proc_ia(const char *pfx,
const struct cper_sec_proc_ia *proc);
-int cper_mem_err_location(struct cper_mem_err_compact *mem, char *msg);
+int cper_mem_err_location(struct cper_mem_err_compact *mem, char *msg, size_t len);
int cper_dimm_err_location(struct cper_mem_err_compact *mem, char *msg, size_t len);

-int cper_mem_err2_location(const struct cper_sec_mem_err2 *mem, char *msg);
+int cper_mem_err2_location(const struct cper_sec_mem_err2 *mem, char *msg, size_t len);
int cper_dimm_err2_location(const struct cper_sec_mem_err2 *mem, char *msg, size_t len);

struct acpi_hest_generic_status;
--
2.43.0