Skip to content

Commit e9f331b

Browse files
shuahkhgregkh
authored andcommitted
module: change to print useful messages from elf_validity_check()
[ Upstream commit 7fd982f ] elf_validity_check() checks ELF headers for errors and ELF Spec. compliance and if any of them fail it returns -ENOEXEC from all of these error paths. Almost all of them don't print any messages. When elf_validity_check() returns an error, load_module() prints an error message without error code. It is hard to determine why the module ELF structure is invalid, even if load_module() prints the error code which is -ENOEXEC in all of these cases. Change to print useful error messages from elf_validity_check() to clearly say what went wrong and why the ELF validity checks failed. Remove the load_module() error message which is no longer needed. This patch includes changes to fix build warns on 32-bit platforms: warning: format '%llu' expects argument of type 'long long unsigned int', but argument 3 has type 'Elf32_Off' {aka 'unsigned int'} Reported-by: kernel test robot <[email protected]> Signed-off-by: Shuah Khan <[email protected]> Signed-off-by: Luis Chamberlain <[email protected]> Signed-off-by: Sasha Levin <[email protected]>
1 parent 82b5021 commit e9f331b

File tree

1 file changed

+54
-21
lines changed

1 file changed

+54
-21
lines changed

kernel/module.c

Lines changed: 54 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2967,14 +2967,29 @@ static int elf_validity_check(struct load_info *info)
29672967
Elf_Shdr *shdr, *strhdr;
29682968
int err;
29692969

2970-
if (info->len < sizeof(*(info->hdr)))
2971-
return -ENOEXEC;
2970+
if (info->len < sizeof(*(info->hdr))) {
2971+
pr_err("Invalid ELF header len %lu\n", info->len);
2972+
goto no_exec;
2973+
}
29722974

2973-
if (memcmp(info->hdr->e_ident, ELFMAG, SELFMAG) != 0
2974-
|| info->hdr->e_type != ET_REL
2975-
|| !elf_check_arch(info->hdr)
2976-
|| info->hdr->e_shentsize != sizeof(Elf_Shdr))
2977-
return -ENOEXEC;
2975+
if (memcmp(info->hdr->e_ident, ELFMAG, SELFMAG) != 0) {
2976+
pr_err("Invalid ELF header magic: != %s\n", ELFMAG);
2977+
goto no_exec;
2978+
}
2979+
if (info->hdr->e_type != ET_REL) {
2980+
pr_err("Invalid ELF header type: %u != %u\n",
2981+
info->hdr->e_type, ET_REL);
2982+
goto no_exec;
2983+
}
2984+
if (!elf_check_arch(info->hdr)) {
2985+
pr_err("Invalid architecture in ELF header: %u\n",
2986+
info->hdr->e_machine);
2987+
goto no_exec;
2988+
}
2989+
if (info->hdr->e_shentsize != sizeof(Elf_Shdr)) {
2990+
pr_err("Invalid ELF section header size\n");
2991+
goto no_exec;
2992+
}
29782993

29792994
/*
29802995
* e_shnum is 16 bits, and sizeof(Elf_Shdr) is
@@ -2983,40 +2998,53 @@ static int elf_validity_check(struct load_info *info)
29832998
*/
29842999
if (info->hdr->e_shoff >= info->len
29853000
|| (info->hdr->e_shnum * sizeof(Elf_Shdr) >
2986-
info->len - info->hdr->e_shoff))
2987-
return -ENOEXEC;
3001+
info->len - info->hdr->e_shoff)) {
3002+
pr_err("Invalid ELF section header overflow\n");
3003+
goto no_exec;
3004+
}
29883005

29893006
info->sechdrs = (void *)info->hdr + info->hdr->e_shoff;
29903007

29913008
/*
29923009
* Verify if the section name table index is valid.
29933010
*/
29943011
if (info->hdr->e_shstrndx == SHN_UNDEF
2995-
|| info->hdr->e_shstrndx >= info->hdr->e_shnum)
2996-
return -ENOEXEC;
3012+
|| info->hdr->e_shstrndx >= info->hdr->e_shnum) {
3013+
pr_err("Invalid ELF section name index: %d || e_shstrndx (%d) >= e_shnum (%d)\n",
3014+
info->hdr->e_shstrndx, info->hdr->e_shstrndx,
3015+
info->hdr->e_shnum);
3016+
goto no_exec;
3017+
}
29973018

29983019
strhdr = &info->sechdrs[info->hdr->e_shstrndx];
29993020
err = validate_section_offset(info, strhdr);
3000-
if (err < 0)
3021+
if (err < 0) {
3022+
pr_err("Invalid ELF section hdr(type %u)\n", strhdr->sh_type);
30013023
return err;
3024+
}
30023025

30033026
/*
30043027
* The section name table must be NUL-terminated, as required
30053028
* by the spec. This makes strcmp and pr_* calls that access
30063029
* strings in the section safe.
30073030
*/
30083031
info->secstrings = (void *)info->hdr + strhdr->sh_offset;
3009-
if (info->secstrings[strhdr->sh_size - 1] != '\0')
3010-
return -ENOEXEC;
3032+
if (info->secstrings[strhdr->sh_size - 1] != '\0') {
3033+
pr_err("ELF Spec violation: section name table isn't null terminated\n");
3034+
goto no_exec;
3035+
}
30113036

30123037
/*
30133038
* The code assumes that section 0 has a length of zero and
30143039
* an addr of zero, so check for it.
30153040
*/
30163041
if (info->sechdrs[0].sh_type != SHT_NULL
30173042
|| info->sechdrs[0].sh_size != 0
3018-
|| info->sechdrs[0].sh_addr != 0)
3019-
return -ENOEXEC;
3043+
|| info->sechdrs[0].sh_addr != 0) {
3044+
pr_err("ELF Spec violation: section 0 type(%d)!=SH_NULL or non-zero len or addr\n",
3045+
info->sechdrs[0].sh_type);
3046+
goto no_exec;
3047+
}
30203048

30213049
for (i = 1; i < info->hdr->e_shnum; i++) {
30223050
shdr = &info->sechdrs[i];
@@ -3026,8 +3054,12 @@ static int elf_validity_check(struct load_info *info)
30263054
continue;
30273055
case SHT_SYMTAB:
30283056
if (shdr->sh_link == SHN_UNDEF
3029-
|| shdr->sh_link >= info->hdr->e_shnum)
3030-
return -ENOEXEC;
3057+
|| shdr->sh_link >= info->hdr->e_shnum) {
3058+
pr_err("Invalid ELF sh_link!=SHN_UNDEF(%d) or (sh_link(%d) >= hdr->e_shnum(%d)\n",
3059+
shdr->sh_link, shdr->sh_link,
3060+
info->hdr->e_shnum);
3061+
goto no_exec;
3062+
}
30313063
fallthrough;
30323064
default:
30333065
err = validate_section_offset(info, shdr);
@@ -3049,6 +3081,9 @@ static int elf_validity_check(struct load_info *info)
30493081
}
30503082

30513083
return 0;
3084+
3085+
no_exec:
3086+
return -ENOEXEC;
30523087
}
30533088

30543089
#define COPY_CHUNK_SIZE (16*PAGE_SIZE)
@@ -3925,10 +3960,8 @@ static int load_module(struct load_info *info, const char __user *uargs,
39253960
* sections.
39263961
*/
39273962
err = elf_validity_check(info);
3928-
if (err) {
3929-
pr_err("Module has invalid ELF structures\n");
3963+
if (err)
39303964
goto free_copy;
3931-
}
39323965

39333966
/*
39343967
* Everything checks out, so set up the section info

0 commit comments

Comments
 (0)