summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/remoteproc/remoteproc_elf_loader.c23
1 files changed, 21 insertions, 2 deletions
diff --git a/drivers/remoteproc/remoteproc_elf_loader.c b/drivers/remoteproc/remoteproc_elf_loader.c
index 94177e416047..da3cddbe7d4c 100644
--- a/drivers/remoteproc/remoteproc_elf_loader.c
+++ b/drivers/remoteproc/remoteproc_elf_loader.c
@@ -46,8 +46,9 @@ int rproc_elf_sanity_check(struct rproc *rproc, const struct firmware *fw)
struct elf32_hdr *ehdr;
u32 elf_shdr_get_size;
u64 phoff, shoff;
+ size_t shend;
char class;
- u16 phnum;
+ u16 phnum, shnum, shstrndx;
if (!fw) {
dev_err(dev, "failed to load %s\n", name);
@@ -90,9 +91,27 @@ int rproc_elf_sanity_check(struct rproc *rproc, const struct firmware *fw)
phoff = elf_hdr_get_e_phoff(class, fw->data);
shoff = elf_hdr_get_e_shoff(class, fw->data);
phnum = elf_hdr_get_e_phnum(class, fw->data);
+ shnum = elf_hdr_get_e_shnum(class, fw->data);
+ shstrndx = elf_hdr_get_e_shstrndx(class, fw->data);
elf_shdr_get_size = elf_size_of_shdr(class);
- if (fw->size < shoff + elf_shdr_get_size) {
+ /* keeps shoff in size_t range for the two bounds below */
+ if (shoff > fw->size) {
+ dev_err(dev, "Section header table is out of bounds\n");
+ return -EINVAL;
+ }
+
+ if (shnum) {
+ shend = size_add(size_mul(elf_shdr_get_size, shnum), shoff);
+ if (shend > fw->size) {
+ dev_err(dev, "Section headers are out of bounds\n");
+ return -EINVAL;
+ }
+ }
+
+ /* find_table() reads the header at shstrndx even with no sections */
+ shend = size_add(size_mul(elf_shdr_get_size, (size_t)shstrndx + 1), shoff);
+ if (shend > fw->size) {
dev_err(dev, "Image is too small\n");
return -EINVAL;
}