mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-22 16:06:04 -05:00
lib/buildid: take into account e_phoff when fetching program headers
Current code assumption is that program (segment) headers are following ELF header immediately. This is a common case, but is not guaranteed. So take into account e_phoff field of the ELF header when accessing program headers. Reviewed-by: Eduard Zingerman <eddyz87@gmail.com> Reported-by: Alexey Dobriyan <adobriyan@gmail.com> Signed-off-by: Andrii Nakryiko <andrii@kernel.org> Link: https://lore.kernel.org/r/20240829174232.3133883-4-andrii@kernel.org Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
parent
de3ec364c3
commit
d4deb82423
1 changed files with 16 additions and 19 deletions
|
@ -213,28 +213,26 @@ static int get_build_id_32(struct freader *r, unsigned char *build_id, __u32 *si
|
||||||
{
|
{
|
||||||
const Elf32_Ehdr *ehdr;
|
const Elf32_Ehdr *ehdr;
|
||||||
const Elf32_Phdr *phdr;
|
const Elf32_Phdr *phdr;
|
||||||
__u32 phnum, i;
|
__u32 phnum, phoff, i;
|
||||||
|
|
||||||
ehdr = freader_fetch(r, 0, sizeof(Elf32_Ehdr));
|
ehdr = freader_fetch(r, 0, sizeof(Elf32_Ehdr));
|
||||||
if (!ehdr)
|
if (!ehdr)
|
||||||
return r->err;
|
return r->err;
|
||||||
|
|
||||||
/*
|
|
||||||
* FIXME
|
|
||||||
* Neither ELF spec nor ELF loader require that program headers
|
|
||||||
* start immediately after ELF header.
|
|
||||||
*/
|
|
||||||
if (ehdr->e_phoff != sizeof(Elf32_Ehdr))
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
/* subsequent freader_fetch() calls invalidate pointers, so remember locally */
|
/* subsequent freader_fetch() calls invalidate pointers, so remember locally */
|
||||||
phnum = READ_ONCE(ehdr->e_phnum);
|
phnum = READ_ONCE(ehdr->e_phnum);
|
||||||
|
phoff = READ_ONCE(ehdr->e_phoff);
|
||||||
|
|
||||||
/* only supports phdr that fits in one page */
|
/* only supports phdr that fits in one page */
|
||||||
if (phnum > (PAGE_SIZE - sizeof(Elf32_Ehdr)) / sizeof(Elf32_Phdr))
|
if (phnum > (PAGE_SIZE - sizeof(Elf32_Ehdr)) / sizeof(Elf32_Phdr))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
/* check that phoff is not large enough to cause an overflow */
|
||||||
|
if (phoff + phnum * sizeof(Elf32_Phdr) < phoff)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
for (i = 0; i < phnum; ++i) {
|
for (i = 0; i < phnum; ++i) {
|
||||||
phdr = freader_fetch(r, i * sizeof(Elf32_Phdr), sizeof(Elf32_Phdr));
|
phdr = freader_fetch(r, phoff + i * sizeof(Elf32_Phdr), sizeof(Elf32_Phdr));
|
||||||
if (!phdr)
|
if (!phdr)
|
||||||
return r->err;
|
return r->err;
|
||||||
|
|
||||||
|
@ -252,27 +250,26 @@ static int get_build_id_64(struct freader *r, unsigned char *build_id, __u32 *si
|
||||||
const Elf64_Ehdr *ehdr;
|
const Elf64_Ehdr *ehdr;
|
||||||
const Elf64_Phdr *phdr;
|
const Elf64_Phdr *phdr;
|
||||||
__u32 phnum, i;
|
__u32 phnum, i;
|
||||||
|
__u64 phoff;
|
||||||
|
|
||||||
ehdr = freader_fetch(r, 0, sizeof(Elf64_Ehdr));
|
ehdr = freader_fetch(r, 0, sizeof(Elf64_Ehdr));
|
||||||
if (!ehdr)
|
if (!ehdr)
|
||||||
return r->err;
|
return r->err;
|
||||||
|
|
||||||
/*
|
|
||||||
* FIXME
|
|
||||||
* Neither ELF spec nor ELF loader require that program headers
|
|
||||||
* start immediately after ELF header.
|
|
||||||
*/
|
|
||||||
if (ehdr->e_phoff != sizeof(Elf64_Ehdr))
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
/* subsequent freader_fetch() calls invalidate pointers, so remember locally */
|
/* subsequent freader_fetch() calls invalidate pointers, so remember locally */
|
||||||
phnum = READ_ONCE(ehdr->e_phnum);
|
phnum = READ_ONCE(ehdr->e_phnum);
|
||||||
|
phoff = READ_ONCE(ehdr->e_phoff);
|
||||||
|
|
||||||
/* only supports phdr that fits in one page */
|
/* only supports phdr that fits in one page */
|
||||||
if (phnum > (PAGE_SIZE - sizeof(Elf64_Ehdr)) / sizeof(Elf64_Phdr))
|
if (phnum > (PAGE_SIZE - sizeof(Elf64_Ehdr)) / sizeof(Elf64_Phdr))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
/* check that phoff is not large enough to cause an overflow */
|
||||||
|
if (phoff + phnum * sizeof(Elf64_Phdr) < phoff)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
for (i = 0; i < phnum; ++i) {
|
for (i = 0; i < phnum; ++i) {
|
||||||
phdr = freader_fetch(r, i * sizeof(Elf64_Phdr), sizeof(Elf64_Phdr));
|
phdr = freader_fetch(r, phoff + i * sizeof(Elf64_Phdr), sizeof(Elf64_Phdr));
|
||||||
if (!phdr)
|
if (!phdr)
|
||||||
return r->err;
|
return r->err;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue