* [PATCH v2 0/3] soc: qcom: mdt_loader: Validation and cleanup fixes
@ 2025-06-11 2:58 Bjorn Andersson
2025-06-11 2:58 ` [PATCH v2 1/3] soc: qcom: mdt_loader: Ensure we don't read past the ELF header Bjorn Andersson
` (3 more replies)
0 siblings, 4 replies; 6+ messages in thread
From: Bjorn Andersson @ 2025-06-11 2:58 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio
Cc: linux-arm-msm, linux-kernel, linux-remoteproc, Mukesh Ojha,
Doug Anderson, Bjorn Andersson, stable, Dmitry Baryshkov
Signed-off-by: Bjorn Andersson <bjorn.andersson@oss.qualcomm.com>
---
Changes in v2:
- Validate e_phentsize and and e_shentsize as well
---
Bjorn Andersson (3):
soc: qcom: mdt_loader: Ensure we don't read past the ELF header
soc: qcom: mdt_loader: Rename mdt_phdr_valid()
soc: qcom: mdt_loader: Actually use the e_phoff
drivers/soc/qcom/mdt_loader.c | 63 ++++++++++++++++++++++++++++++++++++-------
1 file changed, 53 insertions(+), 10 deletions(-)
---
base-commit: 19272b37aa4f83ca52bdf9c16d5d81bdd1354494
change-id: 20250604-mdt-loader-validation-and-fixes-5c3267f5b19f
Best regards,
--
Bjorn Andersson <bjorn.andersson@oss.qualcomm.com>
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v2 1/3] soc: qcom: mdt_loader: Ensure we don't read past the ELF header
2025-06-11 2:58 [PATCH v2 0/3] soc: qcom: mdt_loader: Validation and cleanup fixes Bjorn Andersson
@ 2025-06-11 2:58 ` Bjorn Andersson
2025-06-16 14:06 ` Dmitry Baryshkov
2025-06-11 2:58 ` [PATCH v2 2/3] soc: qcom: mdt_loader: Rename mdt_phdr_valid() Bjorn Andersson
` (2 subsequent siblings)
3 siblings, 1 reply; 6+ messages in thread
From: Bjorn Andersson @ 2025-06-11 2:58 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio
Cc: linux-arm-msm, linux-kernel, linux-remoteproc, Mukesh Ojha,
Doug Anderson, Bjorn Andersson, stable
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 <dianders@chromium.org>
Signed-off-by: Bjorn Andersson <bjorn.andersson@oss.qualcomm.com>
---
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 b2c0fb55d4ae678ee333f0d6b8b586de319f53b1..b2c9731b6f2afacf4acafe555dd36ca0657444a6 100644
--- a/drivers/soc/qcom/mdt_loader.c
+++ b/drivers/soc/qcom/mdt_loader.c
@@ -18,6 +18,37 @@
#include <linux/slab.h>
#include <linux/soc/qcom/mdt_loader.h>
+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)
@@ -82,6 +113,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);
@@ -134,6 +168,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);
@@ -214,6 +251,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);
@@ -310,6 +350,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);
--
2.49.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH v2 2/3] soc: qcom: mdt_loader: Rename mdt_phdr_valid()
2025-06-11 2:58 [PATCH v2 0/3] soc: qcom: mdt_loader: Validation and cleanup fixes Bjorn Andersson
2025-06-11 2:58 ` [PATCH v2 1/3] soc: qcom: mdt_loader: Ensure we don't read past the ELF header Bjorn Andersson
@ 2025-06-11 2:58 ` Bjorn Andersson
2025-06-11 2:58 ` [PATCH v2 3/3] soc: qcom: mdt_loader: Actually use the e_phoff Bjorn Andersson
2025-06-17 21:31 ` [PATCH v2 0/3] soc: qcom: mdt_loader: Validation and cleanup fixes Bjorn Andersson
3 siblings, 0 replies; 6+ messages in thread
From: Bjorn Andersson @ 2025-06-11 2:58 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio
Cc: linux-arm-msm, linux-kernel, linux-remoteproc, Mukesh Ojha,
Doug Anderson, Bjorn Andersson, Dmitry Baryshkov
The function checks if a program header refers to a PT_LOAD segment,
that isn't a hash segment (which should be PT_LOAD in the first place),
andwith non-zero size. That's not the definition of "valid", but rather
if it's "loadable".
Rename the function to reflect what it does.
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
Signed-off-by: Bjorn Andersson <bjorn.andersson@oss.qualcomm.com>
---
drivers/soc/qcom/mdt_loader.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/drivers/soc/qcom/mdt_loader.c b/drivers/soc/qcom/mdt_loader.c
index b2c9731b6f2afacf4acafe555dd36ca0657444a6..52f0c8bb7c5ee9f043009a274f147128f0778151 100644
--- a/drivers/soc/qcom/mdt_loader.c
+++ b/drivers/soc/qcom/mdt_loader.c
@@ -49,7 +49,7 @@ static bool mdt_header_valid(const struct firmware *fw)
return true;
}
-static bool mdt_phdr_valid(const struct elf32_phdr *phdr)
+static bool mdt_phdr_loadable(const struct elf32_phdr *phdr)
{
if (phdr->p_type != PT_LOAD)
return false;
@@ -122,7 +122,7 @@ ssize_t qcom_mdt_get_size(const struct firmware *fw)
for (i = 0; i < ehdr->e_phnum; i++) {
phdr = &phdrs[i];
- if (!mdt_phdr_valid(phdr))
+ if (!mdt_phdr_loadable(phdr))
continue;
if (phdr->p_paddr < min_addr)
@@ -260,7 +260,7 @@ int qcom_mdt_pas_init(struct device *dev, const struct firmware *fw,
for (i = 0; i < ehdr->e_phnum; i++) {
phdr = &phdrs[i];
- if (!mdt_phdr_valid(phdr))
+ if (!mdt_phdr_loadable(phdr))
continue;
if (phdr->p_flags & QCOM_MDT_RELOCATABLE)
@@ -360,7 +360,7 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw,
for (i = 0; i < ehdr->e_phnum; i++) {
phdr = &phdrs[i];
- if (!mdt_phdr_valid(phdr))
+ if (!mdt_phdr_loadable(phdr))
continue;
if (phdr->p_flags & QCOM_MDT_RELOCATABLE)
@@ -387,7 +387,7 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw,
for (i = 0; i < ehdr->e_phnum; i++) {
phdr = &phdrs[i];
- if (!mdt_phdr_valid(phdr))
+ if (!mdt_phdr_loadable(phdr))
continue;
offset = phdr->p_paddr - mem_reloc;
--
2.49.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH v2 3/3] soc: qcom: mdt_loader: Actually use the e_phoff
2025-06-11 2:58 [PATCH v2 0/3] soc: qcom: mdt_loader: Validation and cleanup fixes Bjorn Andersson
2025-06-11 2:58 ` [PATCH v2 1/3] soc: qcom: mdt_loader: Ensure we don't read past the ELF header Bjorn Andersson
2025-06-11 2:58 ` [PATCH v2 2/3] soc: qcom: mdt_loader: Rename mdt_phdr_valid() Bjorn Andersson
@ 2025-06-11 2:58 ` Bjorn Andersson
2025-06-17 21:31 ` [PATCH v2 0/3] soc: qcom: mdt_loader: Validation and cleanup fixes Bjorn Andersson
3 siblings, 0 replies; 6+ messages in thread
From: Bjorn Andersson @ 2025-06-11 2:58 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio
Cc: linux-arm-msm, linux-kernel, linux-remoteproc, Mukesh Ojha,
Doug Anderson, Bjorn Andersson, Dmitry Baryshkov
Rather than relying/assuming that the tools generating the firmware
places the program headers immediately following the ELF header, use
e_phoff as intended to find the program headers.
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
Signed-off-by: Bjorn Andersson <bjorn.andersson@oss.qualcomm.com>
---
drivers/soc/qcom/mdt_loader.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/drivers/soc/qcom/mdt_loader.c b/drivers/soc/qcom/mdt_loader.c
index 52f0c8bb7c5ee9f043009a274f147128f0778151..1b4ebae458f3e0e37ce40afeaea2e0fa3568c8dd 100644
--- a/drivers/soc/qcom/mdt_loader.c
+++ b/drivers/soc/qcom/mdt_loader.c
@@ -117,7 +117,7 @@ ssize_t qcom_mdt_get_size(const struct firmware *fw)
return -EINVAL;
ehdr = (struct elf32_hdr *)fw->data;
- phdrs = (struct elf32_phdr *)(ehdr + 1);
+ phdrs = (struct elf32_phdr *)(fw->data + ehdr->e_phoff);
for (i = 0; i < ehdr->e_phnum; i++) {
phdr = &phdrs[i];
@@ -172,7 +172,7 @@ void *qcom_mdt_read_metadata(const struct firmware *fw, size_t *data_len,
return ERR_PTR(-EINVAL);
ehdr = (struct elf32_hdr *)fw->data;
- phdrs = (struct elf32_phdr *)(ehdr + 1);
+ phdrs = (struct elf32_phdr *)(fw->data + ehdr->e_phoff);
if (ehdr->e_phnum < 2)
return ERR_PTR(-EINVAL);
@@ -255,7 +255,7 @@ int qcom_mdt_pas_init(struct device *dev, const struct firmware *fw,
return -EINVAL;
ehdr = (struct elf32_hdr *)fw->data;
- phdrs = (struct elf32_phdr *)(ehdr + 1);
+ phdrs = (struct elf32_phdr *)(fw->data + ehdr->e_phoff);
for (i = 0; i < ehdr->e_phnum; i++) {
phdr = &phdrs[i];
@@ -310,7 +310,7 @@ static bool qcom_mdt_bins_are_split(const struct firmware *fw, const char *fw_na
int i;
ehdr = (struct elf32_hdr *)fw->data;
- phdrs = (struct elf32_phdr *)(ehdr + 1);
+ phdrs = (struct elf32_phdr *)(fw->data + ehdr->e_phoff);
for (i = 0; i < ehdr->e_phnum; i++) {
/*
@@ -355,7 +355,7 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw,
is_split = qcom_mdt_bins_are_split(fw, fw_name);
ehdr = (struct elf32_hdr *)fw->data;
- phdrs = (struct elf32_phdr *)(ehdr + 1);
+ phdrs = (struct elf32_phdr *)(fw->data + ehdr->e_phoff);
for (i = 0; i < ehdr->e_phnum; i++) {
phdr = &phdrs[i];
--
2.49.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH v2 1/3] soc: qcom: mdt_loader: Ensure we don't read past the ELF header
2025-06-11 2:58 ` [PATCH v2 1/3] soc: qcom: mdt_loader: Ensure we don't read past the ELF header Bjorn Andersson
@ 2025-06-16 14:06 ` Dmitry Baryshkov
0 siblings, 0 replies; 6+ messages in thread
From: Dmitry Baryshkov @ 2025-06-16 14:06 UTC (permalink / raw)
To: Bjorn Andersson
Cc: Bjorn Andersson, Konrad Dybcio, linux-arm-msm, linux-kernel,
linux-remoteproc, Mukesh Ojha, Doug Anderson, stable
On Tue, Jun 10, 2025 at 09:58:28PM -0500, Bjorn Andersson wrote:
> 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 <dianders@chromium.org>
> Signed-off-by: Bjorn Andersson <bjorn.andersson@oss.qualcomm.com>
> ---
> drivers/soc/qcom/mdt_loader.c | 43 +++++++++++++++++++++++++++++++++++++++++++
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
Nit: in theory we don't need to validate section headers since we don't
use them in the loader. However it's better be safe than sorry.
> 1 file changed, 43 insertions(+)
>
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v2 0/3] soc: qcom: mdt_loader: Validation and cleanup fixes
2025-06-11 2:58 [PATCH v2 0/3] soc: qcom: mdt_loader: Validation and cleanup fixes Bjorn Andersson
` (2 preceding siblings ...)
2025-06-11 2:58 ` [PATCH v2 3/3] soc: qcom: mdt_loader: Actually use the e_phoff Bjorn Andersson
@ 2025-06-17 21:31 ` Bjorn Andersson
3 siblings, 0 replies; 6+ messages in thread
From: Bjorn Andersson @ 2025-06-17 21:31 UTC (permalink / raw)
To: Konrad Dybcio, Bjorn Andersson
Cc: linux-arm-msm, linux-kernel, linux-remoteproc, Mukesh Ojha,
Doug Anderson, stable, Dmitry Baryshkov
On Tue, 10 Jun 2025 21:58:27 -0500, Bjorn Andersson wrote:
>
Applied, thanks!
[1/3] soc: qcom: mdt_loader: Ensure we don't read past the ELF header
commit: 9f9967fed9d066ed3dae9372b45ffa4f6fccfeef
[2/3] soc: qcom: mdt_loader: Rename mdt_phdr_valid()
commit: cd840362b0a7b3da59740c1380b18ce0ccf8c264
[3/3] soc: qcom: mdt_loader: Actually use the e_phoff
commit: 47e339cac89143709e84a3b71ba8bd9b2fdd2368
Best regards,
--
Bjorn Andersson <andersson@kernel.org>
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2025-06-17 21:31 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-06-11 2:58 [PATCH v2 0/3] soc: qcom: mdt_loader: Validation and cleanup fixes Bjorn Andersson
2025-06-11 2:58 ` [PATCH v2 1/3] soc: qcom: mdt_loader: Ensure we don't read past the ELF header Bjorn Andersson
2025-06-16 14:06 ` Dmitry Baryshkov
2025-06-11 2:58 ` [PATCH v2 2/3] soc: qcom: mdt_loader: Rename mdt_phdr_valid() Bjorn Andersson
2025-06-11 2:58 ` [PATCH v2 3/3] soc: qcom: mdt_loader: Actually use the e_phoff Bjorn Andersson
2025-06-17 21:31 ` [PATCH v2 0/3] soc: qcom: mdt_loader: Validation and cleanup fixes Bjorn Andersson
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).