From: sashiko-bot@kernel.org
To: "Leizhen Zhang" <lzsx618@gmail.com>, nathan@kernel.org, nsc@kernel.org
Cc: linux-kbuild@vger.kernel.org, rostedt@goodmis.org, ljs@kernel.org
Subject: Re: [PATCH 2/5] elf-parse: check that the section header table is inside the file
Date: Tue, 20 Oct 2026 00:03:41 +0000 [thread overview]
Message-ID: <sashiko-outbox-178368@kernel.org> (raw)
In-Reply-To: <20261019000218.3977398-3-lzsx618@gmail.com>
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] elf-parse: missing SHN_UNDEF and SHN_XINDEX bounds checks in elf_parse()
--
commit 8e951169d34059326033b08713c8c35ae69b423f
Author: Leizhen Zhang <lzsx618@gmail.com>
elf-parse: check that the section header table is inside the file
This commit passes the mapped file size to elf_parse() to validate that the
ELF header fits in the mapping, the section header table lies within the
mapping bounds, and the section name string table index is in range.
> diff --git a/scripts/elf-parse.c b/scripts/elf-parse.c
> index 9e7d1a4f263fe..0e16a9cf67f45 100644
> --- a/scripts/elf-parse.c
> +++ b/scripts/elf-parse.c
[ ... ]
> @@ -168,6 +176,34 @@ static int elf_parse(const char *fname, void *addr, uint32_t types)
> ehdr->e32.e_ident[EI_CLASS], fname);
> return -1;
> }
> +
> + /*
> + * Everything past here walks the section headers with offsets and
> + * indices taken from the file, so the table the ELF header describes
> + * has to be inside the mapping first. e_shnum == 0 means the real
> + * count lives in section 0, which must then be present to be read.
> + */
> + shoff = ehdr_shoff(ehdr);
> + shentsize = ehdr_shentsize(ehdr);
> + shnum = ehdr_shnum(ehdr);
> + if (shnum == SHN_UNDEF)
> + shnum = 1;
> + if (shoff > size || shentsize == 0 ||
> + (size - shoff) / shentsize < shnum) {
> + fprintf(stderr, "ELF section headers out of range: %s\n",
> + fname);
> + return -1;
> + }
> +
> + /* SHN_XINDEX defers the index to section 0; elf_open_ro() checks it. */
> + shstrndx = ehdr_shstrndx(ehdr);
> + if (shstrndx != SHN_XINDEX && ehdr_shnum(ehdr) != SHN_UNDEF &&
> + shstrndx >= ehdr_shnum(ehdr)) {
> + fprintf(stderr, "ELF section name index out of range: %s\n",
> + fname);
> + return -1;
> + }
> +
> return 0;
> }
[Severity: Medium]
Can sorttable and tracepoint-update still read past the end of the mapping
when e_shnum is SHN_UNDEF or e_shstrndx is SHN_XINDEX?
The comment and commit message note that resolving the real section count for
SHN_UNDEF and the section name index for SHN_XINDEX stays with elf_open_ro()
(which is updated in the follow-up commit "elf-parse: check the section
indices that elf_open_ro() takes from the file").
However, sorttable and tracepoint-update do not call elf_open_ro(). Instead,
they call elf_map() and resolve section 0's sh_link and sh_size directly
without bounds checks:
scripts/sorttable.c:do_sort() and
scripts/tracepoint-update.c:process_tracepoints():
shstrndx = ehdr_shstrndx(ehdr);
if (shstrndx == SHN_XINDEX)
shstrndx = shdr_link(shdr_start);
string_sec = get_index(shdr_start, shentsize, shstrndx);
secstrings = (const char *)ehdr + shdr_offset(string_sec);
shnum = ehdr_shnum(ehdr);
if (shnum == SHN_UNDEF)
shnum = shdr_size(shdr_start);
If e_shnum == SHN_UNDEF and e_shstrndx is an out-of-range index (not equal to
SHN_XINDEX), elf_parse() skips the shstrndx check because ehdr_shnum(ehdr) ==
SHN_UNDEF, and both tools immediately index shdr_start out of bounds via
get_index(shdr_start, shentsize, shstrndx).
Similarly, if e_shnum == SHN_UNDEF and section 0's sh_size exceeds the number
of section headers that fit in the mapping, or if e_shstrndx == SHN_XINDEX
and section 0's sh_link >= shnum, elf_parse() succeeds and both tools read
past the end of the mapping.
Since elf_parse() already verifies that section 0 lies within the mapping when
shnum > 0, should elf_parse() resolve shdr_size() and shdr_link() from
section 0 and validate the real shnum and shstrndx right here so that all
callers of elf_map() are protected as well?
[ ... ]
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261019000218.3977398-1-lzsx618@gmail.com?part=2
next prev parent reply other threads:[~2026-10-20 0:03 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-19 0:02 [PATCH 0/5] elf-parse: validate what the host ELF tools read from the file Leizhen Zhang
2026-10-19 0:02 ` [PATCH 1/5] elf-parse: avoid an undefined shift when checking the ELF type Leizhen Zhang
2026-10-19 12:47 ` Steven Rostedt
2026-10-19 0:02 ` [PATCH 2/5] elf-parse: check that the section header table is inside the file Leizhen Zhang
2026-10-19 12:55 ` Steven Rostedt
2026-10-20 0:03 ` sashiko-bot [this message]
2026-10-19 0:02 ` [PATCH 3/5] elf-parse: check the section indices that elf_open_ro() takes from " Leizhen Zhang
2026-10-19 0:02 ` [PATCH 4/5] elf-parse: check the symbol table before walking it Leizhen Zhang
2026-10-19 0:02 ` [PATCH 5/5] elf-parse: bound symbol names by the string table Leizhen Zhang
2026-10-20 0:03 ` sashiko-bot
2026-10-19 12:57 ` [PATCH 0/5] elf-parse: validate what the host ELF tools read from the file Steven Rostedt
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=sashiko-outbox-178368@kernel.org \
--to=sashiko-bot@kernel.org \
--cc=linux-kbuild@vger.kernel.org \
--cc=ljs@kernel.org \
--cc=lzsx618@gmail.com \
--cc=nathan@kernel.org \
--cc=nsc@kernel.org \
--cc=rostedt@goodmis.org \
--cc=sashiko-reviews@lists.linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox