[PATCH v4 2/3] RAS: Fix out-of-bounds read when tracing arm_event
From: Abbott Liu
Date: Wed Sep 09 2026 - 07:52:03 EST
The vsei_len < 0 error path did not verify the pei_len and ctx_len.
When vsei_len is negative, section_length is too small to hold the
full record, yet pei_len and ctx_len were derived from
err_info_num/context_info_num and may describe regions beyond the
(long)err .. err + section_length buffer. To prevent trace_arm_event
from reading past the allocated record, sanitize the parameters:
recalculate ctx_len and pei_len based on section_length, limit them,
and set the corresponding pointers to NULL and lengths to 0 when
there is no remaining space.
pei_len and ctx_len become s32 so that the recalculated lengths can
be checked for negative values.
Fixes: 05954511b73e ("RAS: Report all ARM processor CPER information to userspace")
Signed-off-by: Abbott Liu <liuwenliang@xxxxxxxxxx>
---
drivers/ras/ras.c | 22 ++++++++++++++++++----
1 file changed, 18 insertions(+), 4 deletions(-)
diff --git a/drivers/ras/ras.c b/drivers/ras/ras.c
index 2540538a16a8..085fe2d980e5 100644
--- a/drivers/ras/ras.c
+++ b/drivers/ras/ras.c
@@ -58,10 +58,10 @@ void log_arm_hw_error(struct cper_sec_proc_arm *err, const u8 sev)
struct cper_arm_err_info *err_info;
struct cper_arm_ctx_info *ctx_info;
u8 *ven_err_data;
- u32 ctx_len = 0;
+ s32 ctx_len = 0;
int n, sz, cpu;
s32 vsei_len;
- u32 pei_len;
+ s32 pei_len;
u8 *pei_err, *ctx_err;
pei_len = sizeof(struct cper_arm_err_info) * err->err_info_num;
@@ -87,14 +87,28 @@ void log_arm_hw_error(struct cper_sec_proc_arm *err, const u8 sev)
pr_warn(FW_BUG "section length is too small\n");
pr_warn(FW_BUG "firmware-generated error record is incorrect\n");
vsei_len = 0;
+ ven_err_data = NULL;
+
+ ctx_len = err->section_length - (sizeof(struct cper_sec_proc_arm) + pei_len);
+ if (ctx_len < 0) {
+ ctx_len = 0;
+ ctx_err = NULL;
+
+ pei_len = err->section_length - sizeof(struct cper_sec_proc_arm);
+ if (pei_len < 0) {
+ pei_len = 0;
+ pei_err = NULL;
+ }
+ }
+ } else {
+ ven_err_data = (u8 *)ctx_info;
}
- ven_err_data = (u8 *)ctx_info;
cpu = GET_LOGICAL_INDEX(err->mpidr);
if (cpu < 0)
cpu = -1;
- trace_arm_event(err, pei_err, pei_len, ctx_err, ctx_len,
+ trace_arm_event(err, pei_err, (u32)pei_len, ctx_err, (u32)ctx_len,
ven_err_data, (u32)vsei_len, sev, cpu);
}
--
2.43.0