diff options
| -rw-r--r-- | drivers/remoteproc/remoteproc_elf_loader.c | 23 |
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; } |
