From: Mukesh Ojha Date: Tue, 31 Mar 2026 17:12:43 +0000 (+0530) Subject: remoteproc: qcom: Fix minidump out-of-bounds access on subsystems array X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=743cfae79d2458e241b06ed523c28a09f1449b75;p=thirdparty%2Fkernel%2Flinux.git remoteproc: qcom: Fix minidump out-of-bounds access on subsystems array 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 Acked-by: Konrad Dybcio Link: https://lore.kernel.org/r/20260331171243.1962067-1-mukesh.ojha@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- diff --git a/drivers/remoteproc/qcom_common.c b/drivers/remoteproc/qcom_common.c index 6c31140268acb..fd2b6824ad265 100644 --- a/drivers/remoteproc/qcom_common.c +++ b/drivers/remoteproc/qcom_common.c @@ -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];