Linux Modules
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Thiébaud Weksteen" <tweek@google.com>
Cc: linux-modules@vger.kernel.org
Subject: Re: [PATCH] module: validate string table section types
Date: Wed, 08 Jul 2026 01:33:01 +0000	[thread overview]
Message-ID: <20260708013301.C4D4A1F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260708012107.1621513-1-tweek@google.com>

Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:

Pre-existing issues:
- [High] The patch fixes an out-of-bounds read vulnerability for string tables by ensuring they are of type SHT_STRTAB, but fails to address the exact same vulnerability class for several other ELF sections (e.g., .modinfo, .gnu.linkonce.this_module, __version_ext_names, __ksymtab).
- [High] Iterating over sections in lookup functions triggers an out-of-bounds string read for SHT_NULL sections due to missing sh_name bounds checking.
- [High] Validation logic for section headers accesses sechdrs[0] out of bounds if e_shnum is 0 and e_shoff is near the end of the file.
--

--- Patch [1]: [PATCH] module: validate string table section types ---
commit e8e815fedf365febe70f5870d807616d37946281
Author: Thiébaud Weksteen <tweek@google.com>

module: validate string table section types

In elf_validity_cache_sechdrs, section sizes and offsets are validated,
unless the section type is SHT_NULL or SHT_NOBITS.

Later, elf_validity_cache_secstrings and elf_validity_cache_index_str
access the section name table (.shstrtab) and symbol string table
(.strtab) headers without first ensuring that their types are
SHT_STRTAB. If a section type is SHT_NULL or SHT_NOBITS, sh_offset has
not been validated and may reference out-of-bounds memory when
dereferenced in elf_validity_cache_secstrings or
elf_validity_cache_strtab.

Validate that both string section headers are of type SHT_STRTAB before
caching them.

> diff --git a/kernel/module/main.c b/kernel/module/main.c
> index 46dd8d25a6058..7cbc8f0e28c61 100644
> --- a/kernel/module/main.c
> +++ b/kernel/module/main.c
> @@ -2011,6 +2011,7 @@ static int elf_validity_cache_sechdrs(struct load_info *info)

[Severity: High]
This is a pre-existing issue, but does the validation logic in
elf_validity_cache_sechdrs() access sechdrs out of bounds if e_shnum is 0
and e_shoff is near the end of the file?

The overflow check evaluates to 0 > positive if e_shnum is 0 and e_shoff is
less than info->len, allowing the check to incorrectly pass:

elf_validity_cache_sechdrs() {
    ...
    if (info->hdr->e_shoff >= info->len
        || (info->hdr->e_shnum * sizeof(Elf_Shdr) >
            info->len - info->hdr->e_shoff)) {
    ...
}

The code then sets sechdrs and blindly accesses sechdrs[0], reading past the
end of the user-provided module buffer:

elf_validity_cache_sechdrs() {
    ...
    if (sechdrs[0].sh_type != SHT_NULL
        || sechdrs[0].sh_size != 0
        || sechdrs[0].sh_addr != 0) {
    ...
}

>   * Specifically checks:
>   *
>   * * Section name table index is inbounds of section headers
> + * * Section name table type is SHT_STRTAB
>   * * Section name table is not empty
>   * * Section name table is NUL terminated

[ ... ]

> @@ -2038,6 +2039,11 @@ static int elf_validity_cache_secstrings(struct load_info *info)
>  
>  	strhdr = &info->sechdrs[info->hdr->e_shstrndx];
>  
> +	if (strhdr->sh_type != SHT_STRTAB) {
> +		pr_err("Invalid ELF section name table type: %u\n", strhdr->sh_type);
> +		return -ENOEXEC;
> +	}
> +

[Severity: High]
This is a pre-existing issue, but does iterating over sections in lookup
functions trigger an out-of-bounds string read for SHT_NULL sections due to
missing sh_name bounds checking?

In elf_validity_cache_secstrings(), bounds validation of sh_name against the
string table size is explicitly skipped for SHT_NULL sections:

elf_validity_cache_secstrings() {
    ...
    if (shdr->sh_type == SHT_NULL)
        continue;
    ...
}

Later, section lookup functions like find_any_unique_sec() iterate over all
sections and blindly pass the unvalidated info->secstrings pointer to strcmp():

find_any_unique_sec() {
    ...
    if (strcmp(info->secstrings + info->sechdrs[i].sh_name,
               name) == 0) {
    ...
}

Could this cause an immediate out-of-bounds memory read when strcmp()
executes if an attacker sets a huge sh_name on a SHT_NULL section?

[ ... ]

> @@ -2218,6 +2224,12 @@ static int elf_validity_cache_index_str(struct load_info *info)
>  		return -ENOEXEC;
>  	}
>  
> +	if (info->sechdrs[str_idx].sh_type != SHT_STRTAB) {
> +		pr_err("Invalid ELF symbol string table type: %u\n",
> +		       info->sechdrs[str_idx].sh_type);
> +		return -ENOEXEC;
> +	}
> +

[Severity: High]
This is a pre-existing issue, but while this patch fixes an out-of-bounds
read vulnerability for string tables by ensuring they are of type SHT_STRTAB,
does the same vulnerability class exist for other ELF sections?

Since elf_validity_cache_sechdrs() skips bounds checking of sh_offset and
sh_size for SHT_NULL and SHT_NOBITS sections, lookup functions can match
sections by name while ignoring sh_type.

For example, elf_validity_cache_index_info() looks up .modinfo by name and
caches it without validating its sh_type:

elf_validity_cache_index_info() {
    ...
    info_idx = find_any_unique_sec(info, ".modinfo");
    ...
}

Similarly, in elf_validity_cache_index_mod(), the .gnu.linkonce.this_module
section rejects SHT_NOBITS but fails to reject SHT_NULL:

elf_validity_cache_index_mod() {
    ...
    if (shdr->sh_type == SHT_NOBITS) {
    ...
}

And in move_module(), the loop skips SHT_NOBITS but calls memcpy for
SHT_NULL:

move_module() {
    ...
    memcpy(dest, (void *)shdr->sh_addr, shdr->sh_size);
    ...
}

Could a malicious module supply these sections with type SHT_NULL and an
arbitrary, unvalidated sh_offset, leading to out-of-bounds reads or copies?

>  	info->index.str = str_idx;
>  	return 0;
>  }

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260708012107.1621513-1-tweek@google.com?part=1

  reply	other threads:[~2026-07-08  1:33 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-08  1:21 [PATCH] module: validate string table section types Thiébaud Weksteen
2026-07-08  1:33 ` sashiko-bot [this message]
2026-07-08 15:40 ` Petr Pavlu
2026-07-09  1:56   ` Thiébaud Weksteen
2026-07-09  9:23     ` Petr Pavlu
2026-07-10  8:23 ` Markus Elfring

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=20260708013301.C4D4A1F000E9@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=linux-modules@vger.kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    --cc=tweek@google.com \
    /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