]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
firmware: arm_scmi: Validate BASE_ERROR_EVENT payload size
authorSudeep Holla <sudeep.holla@kernel.org>
Sun, 17 May 2026 19:02:41 +0000 (20:02 +0100)
committerSudeep Holla <sudeep.holla@kernel.org>
Wed, 20 May 2026 09:00:10 +0000 (10:00 +0100)
BASE_ERROR_EVENT carries a variable number of message reports,
with the count encoded in error_status. The notification parser used
that count without checking whether the received payload contained all
reported entries.

Reject truncated payloads before copying the report array.

Link: https://patch.msgid.link/20260517-scmi_fixes-v1-2-d86daec4defd@kernel.org
Signed-off-by: Sudeep Holla <sudeep.holla@kernel.org>
drivers/firmware/arm_scmi/base.c

index 4df2620e3c5d0edb955d3b33a0b2114df74cd7a3..a9cea09355ff4b85e7c1ca3535da92f9f4ec2445 100644 (file)
@@ -325,6 +325,8 @@ static void *scmi_base_fill_custom_report(const struct scmi_protocol_handle *ph,
                                          void *report, u32 *src_id)
 {
        int i;
+       u32 error_status;
+       size_t expected_sz;
        const struct scmi_base_error_notify_payld *p = payld;
        struct scmi_base_error_report *r = report;
 
@@ -338,10 +340,19 @@ static void *scmi_base_fill_custom_report(const struct scmi_protocol_handle *ph,
        if (evt_id != SCMI_EVENT_BASE_ERROR_EVENT || sizeof(*p) < payld_sz)
                return NULL;
 
+       expected_sz = offsetof(typeof(*p), msg_reports);
+       if (payld_sz < expected_sz)
+               return NULL;
+
        r->timestamp = timestamp;
        r->agent_id = le32_to_cpu(p->agent_id);
-       r->fatal = IS_FATAL_ERROR(le32_to_cpu(p->error_status));
-       r->cmd_count = ERROR_CMD_COUNT(le32_to_cpu(p->error_status));
+       error_status = le32_to_cpu(p->error_status);
+       r->fatal = IS_FATAL_ERROR(error_status);
+       r->cmd_count = ERROR_CMD_COUNT(error_status);
+       expected_sz += r->cmd_count * sizeof(p->msg_reports[0]);
+       if (payld_sz < expected_sz)
+               return NULL;
+
        for (i = 0; i < r->cmd_count; i++)
                r->reports[i] = le64_to_cpu(p->msg_reports[i]);
        *src_id = 0;