From 08a28078886ac5783e5ec796a7c7bb32d3fa0de1 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Tue, 14 Oct 2025 06:45:05 +0000 Subject: [PATCH 1/3] soc: qcom: mdt_loader: Ensure we don't read past the ELF header stable inclusion from stable-v6.6.103 commit 981c845f29838e468a9bfa87f784307193a31297 category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/ICXMCU CVE: CVE-2025-39787 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=981c845f29838e468a9bfa87f784307193a31297 -------------------------------- commit 9f9967fed9d066ed3dae9372b45ffa4f6fccfeef upstream. When the MDT loader is used in remoteproc, the ELF header is sanitized beforehand, but that's not necessary the case for other clients. Validate the size of the firmware buffer to ensure that we don't read past the end as we iterate over the header. e_phentsize and e_shentsize are validated as well, to ensure that the assumptions about step size in the traversal are valid. Fixes: 2aad40d911ee ("remoteproc: Move qcom_mdt_loader into drivers/soc/qcom") Cc: stable@vger.kernel.org Reported-by: Doug Anderson Signed-off-by: Bjorn Andersson Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20250610-mdt-loader-validation-and-fixes-v2-1-f7073e9ab899@oss.qualcomm.com Signed-off-by: Bjorn Andersson Signed-off-by: Greg Kroah-Hartman Signed-off-by: Chen Jinghuang --- drivers/soc/qcom/mdt_loader.c | 43 +++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/drivers/soc/qcom/mdt_loader.c b/drivers/soc/qcom/mdt_loader.c index 6f177e46fa0f..2834f0771d3f 100644 --- a/drivers/soc/qcom/mdt_loader.c +++ b/drivers/soc/qcom/mdt_loader.c @@ -17,6 +17,37 @@ #include #include +static bool mdt_header_valid(const struct firmware *fw) +{ + const struct elf32_hdr *ehdr; + size_t phend; + size_t shend; + + if (fw->size < sizeof(*ehdr)) + return false; + + ehdr = (struct elf32_hdr *)fw->data; + + if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG)) + return false; + + if (ehdr->e_phentsize != sizeof(struct elf32_phdr)) + return -EINVAL; + + phend = size_add(size_mul(sizeof(struct elf32_phdr), ehdr->e_phnum), ehdr->e_phoff); + if (phend > fw->size) + return false; + + if (ehdr->e_shentsize != sizeof(struct elf32_shdr)) + return -EINVAL; + + shend = size_add(size_mul(sizeof(struct elf32_shdr), ehdr->e_shnum), ehdr->e_shoff); + if (shend > fw->size) + return false; + + return true; +} + static bool mdt_phdr_valid(const struct elf32_phdr *phdr) { if (phdr->p_type != PT_LOAD) @@ -84,6 +115,9 @@ ssize_t qcom_mdt_get_size(const struct firmware *fw) phys_addr_t max_addr = 0; int i; + if (!mdt_header_valid(fw)) + return -EINVAL; + ehdr = (struct elf32_hdr *)fw->data; phdrs = (struct elf32_phdr *)(ehdr + 1); @@ -136,6 +170,9 @@ void *qcom_mdt_read_metadata(const struct firmware *fw, size_t *data_len, ssize_t ret; void *data; + if (!mdt_header_valid(fw)) + return ERR_PTR(-EINVAL); + ehdr = (struct elf32_hdr *)fw->data; phdrs = (struct elf32_phdr *)(ehdr + 1); @@ -216,6 +253,9 @@ int qcom_mdt_pas_init(struct device *dev, const struct firmware *fw, int ret; int i; + if (!mdt_header_valid(fw)) + return -EINVAL; + ehdr = (struct elf32_hdr *)fw->data; phdrs = (struct elf32_phdr *)(ehdr + 1); @@ -312,6 +352,9 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw, if (!fw || !mem_region || !mem_phys || !mem_size) return -EINVAL; + if (!mdt_header_valid(fw)) + return -EINVAL; + is_split = qcom_mdt_bins_are_split(fw, fw_name); ehdr = (struct elf32_hdr *)fw->data; phdrs = (struct elf32_phdr *)(ehdr + 1); -- Gitee From 83ba9a9b357897cb2a3894a3df8879bd692dc4d5 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 14 Oct 2025 06:45:06 +0000 Subject: [PATCH 2/3] soc: qcom: mdt_loader: Fix error return values in mdt_header_valid() stable inclusion from stable-v6.6.103 commit 72ff3acf00443119779bb44773c796b26ba37f8c category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/ICXMCU CVE: CVE-2025-39787 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=72ff3acf00443119779bb44773c796b26ba37f8c -------------------------------- commit 9f35ab0e53ccbea57bb9cbad8065e0406d516195 upstream. This function is supposed to return true for valid headers and false for invalid. In a couple places it returns -EINVAL instead which means the invalid headers are counted as true. Change it to return false. Fixes: 9f9967fed9d0 ("soc: qcom: mdt_loader: Ensure we don't read past the ELF header") Signed-off-by: Dan Carpenter Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/db57c01c-bdcc-4a0f-95db-b0f2784ea91f@sabinyo.mountain Signed-off-by: Bjorn Andersson Signed-off-by: Greg Kroah-Hartman Signed-off-by: Chen Jinghuang --- drivers/soc/qcom/mdt_loader.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/soc/qcom/mdt_loader.c b/drivers/soc/qcom/mdt_loader.c index 2834f0771d3f..f49f21cf3b4b 100644 --- a/drivers/soc/qcom/mdt_loader.c +++ b/drivers/soc/qcom/mdt_loader.c @@ -32,14 +32,14 @@ static bool mdt_header_valid(const struct firmware *fw) return false; if (ehdr->e_phentsize != sizeof(struct elf32_phdr)) - return -EINVAL; + return false; phend = size_add(size_mul(sizeof(struct elf32_phdr), ehdr->e_phnum), ehdr->e_phoff); if (phend > fw->size) return false; if (ehdr->e_shentsize != sizeof(struct elf32_shdr)) - return -EINVAL; + return false; shend = size_add(size_mul(sizeof(struct elf32_shdr), ehdr->e_shnum), ehdr->e_shoff); if (shend > fw->size) -- Gitee From 8eac9013a4a72465ef5f17501f39a577cc4dbfde Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Tue, 14 Oct 2025 06:45:07 +0000 Subject: [PATCH 3/3] soc: qcom: mdt_loader: Deal with zero e_shentsize stable inclusion from stable-v6.6.103 commit bc983b83435490910ab96cc892ca81ee57e4ed8b category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/ICXMCU CVE: CVE-2025-39787 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=bc983b83435490910ab96cc892ca81ee57e4ed8b -------------------------------- commit 25daf9af0ac1bf12490b723b5efaf8dcc85980bc upstream. Firmware that doesn't provide section headers leave both e_shentsize and e_shnum 0, which obvious isn't compatible with the newly introduced stricter checks. Make the section-related checks conditional on either of these values being non-zero. Fixes: 9f9967fed9d0 ("soc: qcom: mdt_loader: Ensure we don't read past the ELF header") Reported-by: Val Packett Closes: https://lore.kernel.org/all/ece307c3-7d65-440f-babd-88cf9705b908@packett.cool/ Reported-by: Neil Armstrong Closes: https://lore.kernel.org/all/aec9cd03-6fc2-4dc8-b937-8b7cf7bf4128@linaro.org/ Signed-off-by: Bjorn Andersson Fixes: 9f35ab0e53cc ("soc: qcom: mdt_loader: Fix error return values in mdt_header_valid()") Tested-by: Neil Armstrong # on SM8650-QRD Reviewed-by: Dmitry Baryshkov Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20250730-mdt-loader-shentsize-zero-v1-1-04f43186229c@oss.qualcomm.com Signed-off-by: Bjorn Andersson Signed-off-by: Greg Kroah-Hartman Signed-off-by: Chen Jinghuang --- drivers/soc/qcom/mdt_loader.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/soc/qcom/mdt_loader.c b/drivers/soc/qcom/mdt_loader.c index f49f21cf3b4b..6994cc41e6f3 100644 --- a/drivers/soc/qcom/mdt_loader.c +++ b/drivers/soc/qcom/mdt_loader.c @@ -38,12 +38,14 @@ static bool mdt_header_valid(const struct firmware *fw) if (phend > fw->size) return false; - if (ehdr->e_shentsize != sizeof(struct elf32_shdr)) - return false; + if (ehdr->e_shentsize || ehdr->e_shnum) { + if (ehdr->e_shentsize != sizeof(struct elf32_shdr)) + return false; - shend = size_add(size_mul(sizeof(struct elf32_shdr), ehdr->e_shnum), ehdr->e_shoff); - if (shend > fw->size) - return false; + shend = size_add(size_mul(sizeof(struct elf32_shdr), ehdr->e_shnum), ehdr->e_shoff); + if (shend > fw->size) + return false; + } return true; } -- Gitee