mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-11 21:38:32 +08:00
modules patches for 5.16-rc1
As requested by Jessica I'm stepping in to help with modules maintenance. This is my first pull request to you. I've collected only two patches for modules for the 5.16-rc1 merge window. These patches are from Shuah Khan as she debugged some corner case error with modules. The error messages are improved for elf_validity_check(). While doing this work a corner case fix was spotted on validate_section_offset() due to a possible overflow bug on 64-bit. The impact of this fix is low given this just limits module section headers placed within the 32-bit boundary, and we obviously don't have insane module sizes. Even if a specially crafted module is constructed later checks would invalidate the module right away. I've let this sit through 0-day testing since October 15th with no issues found. Signed-off-by: Luis Chamberlain <mcgrof@kernel.org> -----BEGIN PGP SIGNATURE----- iQJGBAABCgAwFiEENnNq2KuOejlQLZofziMdCjCSiKcFAmGFrvcSHG1jZ3JvZkBr ZXJuZWwub3JnAAoJEM4jHQowkoinhFAP/1BBXuM/vevC1IdZaEU4M8pg07NOpkZt PYJc8CxWKTtEg5hrLJMqOexXGwvAg/nq28IFWvUKh3bGtEghPyrQu6+I4mXsjnjJ t9/AO+BOYU14DJGDAYEuReNsaAcyeRooHLriuUaNvhhaN9q+v+FRyBWNphmA6Tz7 VkCtmCNMFJZlhd9Cu4jOZpJe6CIe9gZ0czYfRshAl/3ZRSQjYaddtbYf1Cs8Vwah by4o2YyvctrRzeOj/Fy+kbqZw2St39nZ5fKYwijRn1ZwHRQo6NQqrlMeS8rI0LgG 1YwWgNWO1FjaPzyIFcAhk2bUF2TxEf5/eVpXn2qXHnmVZ55oBPP/O7Th0/5OK9gD utOMbO1nqBLBXUyX/1dO/UT36XcrqtUP0Y9VgjIvj9n8Y82RGYmBScH/TOU1f7A7 sH56sW9/3YvIOe8AShBHJ7IKqZXU0inIGasFYwKKm2pAOLtajaC9Sr5fqVbuyfNF J2+nXipVzjI0f9SGTqmE41jynFGln6nfd1pgOOiysg9ZqxieINB0J8l0OHe6fZz/ zU4TehXZHE9DApP8D+rVpP0ltwR2YWs2u0zRqHr/0GEWYH00JZu2ymDR13W7izSp KiiveBxhwBpewgV5cyua8TDyeKhn3mEJFNmijlaq4yq1P2oKeWTQRDRZjwUP8EZY s16oV+BW7Kp+ =Evek -----END PGP SIGNATURE----- Merge tag 'modules-5.16-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/mcgrof/linux Pull module updates from Luis Chamberlain: "As requested by Jessica I'm stepping in to help with modules maintenance. This is my first pull request to you. I've collected only two patches for modules for the 5.16-rc1 merge window. These patches are from Shuah Khan as she debugged some corner case error with modules. The error messages are improved for elf_validity_check(). While doing this work a corner case fix was spotted on validate_section_offset() due to a possible overflow bug on 64-bit. The impact of this fix is low given this just limits module section headers placed within the 32-bit boundary, and we obviously don't have insane module sizes. Even if a specially crafted module is constructed later checks would invalidate the module right away. I've let this sit through 0-day testing since October 15th with no issues found" * tag 'modules-5.16-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/mcgrof/linux: module: change to print useful messages from elf_validity_check() module: fix validate_section_offset() overflow bug on 64-bit
This commit is contained in:
commit
67b7e1f241
@ -2942,7 +2942,11 @@ static int module_sig_check(struct load_info *info, int flags)
|
||||
|
||||
static int validate_section_offset(struct load_info *info, Elf_Shdr *shdr)
|
||||
{
|
||||
#if defined(CONFIG_64BIT)
|
||||
unsigned long long secend;
|
||||
#else
|
||||
unsigned long secend;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Check for both overflow and offset/size being
|
||||
@ -2967,14 +2971,29 @@ static int elf_validity_check(struct load_info *info)
|
||||
Elf_Shdr *shdr, *strhdr;
|
||||
int err;
|
||||
|
||||
if (info->len < sizeof(*(info->hdr)))
|
||||
return -ENOEXEC;
|
||||
if (info->len < sizeof(*(info->hdr))) {
|
||||
pr_err("Invalid ELF header len %lu\n", info->len);
|
||||
goto no_exec;
|
||||
}
|
||||
|
||||
if (memcmp(info->hdr->e_ident, ELFMAG, SELFMAG) != 0
|
||||
|| info->hdr->e_type != ET_REL
|
||||
|| !elf_check_arch(info->hdr)
|
||||
|| info->hdr->e_shentsize != sizeof(Elf_Shdr))
|
||||
return -ENOEXEC;
|
||||
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 (info->hdr->e_shentsize != sizeof(Elf_Shdr)) {
|
||||
pr_err("Invalid ELF section header size\n");
|
||||
goto no_exec;
|
||||
}
|
||||
|
||||
/*
|
||||
* e_shnum is 16 bits, and sizeof(Elf_Shdr) is
|
||||
@ -2983,8 +3002,10 @@ static int elf_validity_check(struct load_info *info)
|
||||
*/
|
||||
if (info->hdr->e_shoff >= info->len
|
||||
|| (info->hdr->e_shnum * sizeof(Elf_Shdr) >
|
||||
info->len - info->hdr->e_shoff))
|
||||
return -ENOEXEC;
|
||||
info->len - info->hdr->e_shoff)) {
|
||||
pr_err("Invalid ELF section header overflow\n");
|
||||
goto no_exec;
|
||||
}
|
||||
|
||||
info->sechdrs = (void *)info->hdr + info->hdr->e_shoff;
|
||||
|
||||
@ -2992,13 +3013,19 @@ static int elf_validity_check(struct load_info *info)
|
||||
* Verify if the section name table index is valid.
|
||||
*/
|
||||
if (info->hdr->e_shstrndx == SHN_UNDEF
|
||||
|| info->hdr->e_shstrndx >= info->hdr->e_shnum)
|
||||
return -ENOEXEC;
|
||||
|| info->hdr->e_shstrndx >= info->hdr->e_shnum) {
|
||||
pr_err("Invalid ELF section name index: %d || e_shstrndx (%d) >= e_shnum (%d)\n",
|
||||
info->hdr->e_shstrndx, info->hdr->e_shstrndx,
|
||||
info->hdr->e_shnum);
|
||||
goto no_exec;
|
||||
}
|
||||
|
||||
strhdr = &info->sechdrs[info->hdr->e_shstrndx];
|
||||
err = validate_section_offset(info, strhdr);
|
||||
if (err < 0)
|
||||
if (err < 0) {
|
||||
pr_err("Invalid ELF section hdr(type %u)\n", strhdr->sh_type);
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* The section name table must be NUL-terminated, as required
|
||||
@ -3006,8 +3033,10 @@ static int elf_validity_check(struct load_info *info)
|
||||
* strings in the section safe.
|
||||
*/
|
||||
info->secstrings = (void *)info->hdr + strhdr->sh_offset;
|
||||
if (info->secstrings[strhdr->sh_size - 1] != '\0')
|
||||
return -ENOEXEC;
|
||||
if (info->secstrings[strhdr->sh_size - 1] != '\0') {
|
||||
pr_err("ELF Spec violation: section name table isn't null terminated\n");
|
||||
goto no_exec;
|
||||
}
|
||||
|
||||
/*
|
||||
* The code assumes that section 0 has a length of zero and
|
||||
@ -3015,8 +3044,11 @@ static int elf_validity_check(struct load_info *info)
|
||||
*/
|
||||
if (info->sechdrs[0].sh_type != SHT_NULL
|
||||
|| info->sechdrs[0].sh_size != 0
|
||||
|| info->sechdrs[0].sh_addr != 0)
|
||||
return -ENOEXEC;
|
||||
|| info->sechdrs[0].sh_addr != 0) {
|
||||
pr_err("ELF Spec violation: section 0 type(%d)!=SH_NULL or non-zero len or addr\n",
|
||||
info->sechdrs[0].sh_type);
|
||||
goto no_exec;
|
||||
}
|
||||
|
||||
for (i = 1; i < info->hdr->e_shnum; i++) {
|
||||
shdr = &info->sechdrs[i];
|
||||
@ -3026,8 +3058,12 @@ static int elf_validity_check(struct load_info *info)
|
||||
continue;
|
||||
case SHT_SYMTAB:
|
||||
if (shdr->sh_link == SHN_UNDEF
|
||||
|| shdr->sh_link >= info->hdr->e_shnum)
|
||||
return -ENOEXEC;
|
||||
|| shdr->sh_link >= info->hdr->e_shnum) {
|
||||
pr_err("Invalid ELF sh_link!=SHN_UNDEF(%d) or (sh_link(%d) >= hdr->e_shnum(%d)\n",
|
||||
shdr->sh_link, shdr->sh_link,
|
||||
info->hdr->e_shnum);
|
||||
goto no_exec;
|
||||
}
|
||||
fallthrough;
|
||||
default:
|
||||
err = validate_section_offset(info, shdr);
|
||||
@ -3049,6 +3085,9 @@ static int elf_validity_check(struct load_info *info)
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
no_exec:
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
#define COPY_CHUNK_SIZE (16*PAGE_SIZE)
|
||||
@ -3940,10 +3979,8 @@ static int load_module(struct load_info *info, const char __user *uargs,
|
||||
* sections.
|
||||
*/
|
||||
err = elf_validity_check(info);
|
||||
if (err) {
|
||||
pr_err("Module has invalid ELF structures\n");
|
||||
if (err)
|
||||
goto free_copy;
|
||||
}
|
||||
|
||||
/*
|
||||
* Everything checks out, so set up the section info
|
||||
|
Loading…
Reference in New Issue
Block a user