summaryrefslogtreecommitdiffstats
path: root/kernel/module/main.c
diff options
context:
space:
mode:
authorMatthew Maurer <mmaurer@google.com>2024-10-16 01:16:36 +0200
committerLuis Chamberlain <mcgrof@kernel.org>2024-10-19 23:35:06 +0200
commit90f8f312db720dbabec7c6258ef580b50129cc21 (patch)
tree5c73850d4ecdcc78ff9135a7f46f91a2ce3cc81a /kernel/module/main.c
parentmodule: Take const arg in validate_section_offset (diff)
downloadlinux-90f8f312db720dbabec7c6258ef580b50129cc21.tar.xz
linux-90f8f312db720dbabec7c6258ef580b50129cc21.zip
module: Factor out elf_validity_ehdr
Factor out verification of the ELF header and document what is checked. Signed-off-by: Matthew Maurer <mmaurer@google.com> Reviewed-by: Sami Tolvanen <samitolvanen@google.com> Signed-off-by: Luis Chamberlain <mcgrof@kernel.org>
Diffstat (limited to '')
-rw-r--r--kernel/module/main.c70
1 files changed, 47 insertions, 23 deletions
diff --git a/kernel/module/main.c b/kernel/module/main.c
index 1a2dd52147ba..59c977acfb44 100644
--- a/kernel/module/main.c
+++ b/kernel/module/main.c
@@ -1664,6 +1664,50 @@ static int validate_section_offset(const struct load_info *info, Elf_Shdr *shdr)
return 0;
}
+/**
+ * elf_validity_ehdr() - Checks an ELF header for module validity
+ * @info: Load info containing the ELF header to check
+ *
+ * Checks whether an ELF header could belong to a valid module. Checks:
+ *
+ * * ELF header is within the data the user provided
+ * * ELF magic is present
+ * * It is relocatable (not final linked, not core file, etc.)
+ * * The header's machine type matches what the architecture expects.
+ * * Optional arch-specific hook for other properties
+ * - module_elf_check_arch() is currently only used by PPC to check
+ * ELF ABI version, but may be used by others in the future.
+ *
+ * Return: %0 if valid, %-ENOEXEC on failure.
+ */
+static int elf_validity_ehdr(const struct load_info *info)
+{
+ if (info->len < sizeof(*(info->hdr))) {
+ pr_err("Invalid ELF header len %lu\n", info->len);
+ return -ENOEXEC;
+ }
+ if (memcmp(info->hdr->e_ident, ELFMAG, SELFMAG) != 0) {
+ pr_err("Invalid ELF header magic: != %s\n", ELFMAG);
+ return -ENOEXEC;
+ }
+ if (info->hdr->e_type != ET_REL) {
+ pr_err("Invalid ELF header type: %u != %u\n",
+ info->hdr->e_type, ET_REL);
+ return -ENOEXEC;
+ }
+ if (!elf_check_arch(info->hdr)) {
+ pr_err("Invalid architecture in ELF header: %u\n",
+ info->hdr->e_machine);
+ return -ENOEXEC;
+ }
+ if (!module_elf_check_arch(info->hdr)) {
+ pr_err("Invalid module architecture in ELF header: %u\n",
+ info->hdr->e_machine);
+ return -ENOEXEC;
+ }
+ return 0;
+}
+
/*
* Check userspace passed ELF module against our expectations, and cache
* useful variables for further processing as we go.
@@ -1693,30 +1737,10 @@ static int elf_validity_cache_copy(struct load_info *info, int flags)
unsigned int num_info_secs = 0, info_idx;
unsigned int num_sym_secs = 0, sym_idx;
- if (info->len < sizeof(*(info->hdr))) {
- pr_err("Invalid ELF header len %lu\n", info->len);
- goto no_exec;
- }
+ err = elf_validity_ehdr(info);
+ if (err < 0)
+ return err;
- if (memcmp(info->hdr->e_ident, ELFMAG, SELFMAG) != 0) {
- pr_err("Invalid ELF header magic: != %s\n", ELFMAG);
- goto no_exec;
- }
- if (info->hdr->e_type != ET_REL) {
- pr_err("Invalid ELF header type: %u != %u\n",
- info->hdr->e_type, ET_REL);
- goto no_exec;
- }
- if (!elf_check_arch(info->hdr)) {
- pr_err("Invalid architecture in ELF header: %u\n",
- info->hdr->e_machine);
- goto no_exec;
- }
- if (!module_elf_check_arch(info->hdr)) {
- pr_err("Invalid module architecture in ELF header: %u\n",
- info->hdr->e_machine);
- goto no_exec;
- }
if (info->hdr->e_shentsize != sizeof(Elf_Shdr)) {
pr_err("Invalid ELF section header size\n");
goto no_exec;