]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
remoteproc: qcom: Fix minidump out-of-bounds access on subsystems array
authorMukesh Ojha <mukesh.ojha@oss.qualcomm.com>
Tue, 31 Mar 2026 17:12:43 +0000 (22:42 +0530)
committerBjorn Andersson <andersson@kernel.org>
Mon, 6 Apr 2026 14:44:12 +0000 (09:44 -0500)
MAX_NUM_OF_SS was hardcoded to 10 in the minidump_global_toc struct,
which is a direct overlay on an SMEM item allocated by the firmware.
Newer Qualcomm SoC firmware allocates space for more subsystems, while
older firmware only allocates space for 10. Bumping the constant would
cause Linux to read/write beyond the SMEM item boundary on older
platforms.

Fix this by converting subsystems[] to a flexible array member and
deriving the actual number of subsystems at runtime from the size
returned by qcom_smem_get(). Add a bounds check on minidump_id against
the derived count before indexing into the array.

Signed-off-by: Mukesh Ojha <mukesh.ojha@oss.qualcomm.com>
Acked-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Link: https://lore.kernel.org/r/20260331171243.1962067-1-mukesh.ojha@oss.qualcomm.com
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
drivers/remoteproc/qcom_common.c

index 6c31140268acb1ad0a997d7740bbbc27b05830a4..fd2b6824ad265ec967741c8c1977e9d4f3bd424d 100644 (file)
@@ -28,7 +28,6 @@
 #define to_ssr_subdev(d) container_of(d, struct qcom_rproc_ssr, subdev)
 #define to_pdm_subdev(d) container_of(d, struct qcom_rproc_pdm, subdev)
 
-#define MAX_NUM_OF_SS           10
 #define MAX_REGION_NAME_LENGTH  16
 #define SBL_MINIDUMP_SMEM_ID   602
 #define MINIDUMP_REGION_VALID          ('V' << 24 | 'A' << 16 | 'L' << 8 | 'I' << 0)
@@ -80,7 +79,7 @@ struct minidump_global_toc {
        __le32                          status;
        __le32                          md_revision;
        __le32                          enabled;
-       struct minidump_subsystem       subsystems[MAX_NUM_OF_SS];
+       struct minidump_subsystem       subsystems[];
 };
 
 struct qcom_ssr_subsystem {
@@ -151,9 +150,11 @@ void qcom_minidump(struct rproc *rproc, unsigned int minidump_id,
        int ret;
        struct minidump_subsystem *subsystem;
        struct minidump_global_toc *toc;
+       unsigned int num_ss;
+       size_t toc_size;
 
        /* Get Global minidump ToC*/
-       toc = qcom_smem_get(QCOM_SMEM_HOST_ANY, SBL_MINIDUMP_SMEM_ID, NULL);
+       toc = qcom_smem_get(QCOM_SMEM_HOST_ANY, SBL_MINIDUMP_SMEM_ID, &toc_size);
 
        /* check if global table pointer exists and init is set */
        if (IS_ERR(toc) || !toc->status) {
@@ -161,6 +162,16 @@ void qcom_minidump(struct rproc *rproc, unsigned int minidump_id,
                return;
        }
 
+       /* Derive the number of subsystems from the actual SMEM item size */
+       num_ss = (toc_size - offsetof(struct minidump_global_toc, subsystems)) /
+                sizeof(struct minidump_subsystem);
+
+       if (minidump_id >= num_ss) {
+               dev_err(&rproc->dev, "Minidump id %d is out of range: %d\n",
+                       minidump_id, num_ss);
+               return;
+       }
+
        /* Get subsystem table of contents using the minidump id */
        subsystem = &toc->subsystems[minidump_id];