|
@@ -2940,7 +2940,7 @@ static int module_sig_check(struct load_info *info, int flags)
|
|
|
}
|
|
|
|
|
|
if (is_module_sig_enforced()) {
|
|
|
- pr_notice("%s: loading of %s is rejected\n", info->name, reason);
|
|
|
+ pr_notice("Loading of %s is rejected\n", reason);
|
|
|
return -EKEYREJECTED;
|
|
|
}
|
|
|
|
|
@@ -2953,9 +2953,33 @@ static int module_sig_check(struct load_info *info, int flags)
|
|
|
}
|
|
|
#endif /* !CONFIG_MODULE_SIG */
|
|
|
|
|
|
-/* Sanity checks against invalid binaries, wrong arch, weird elf version. */
|
|
|
-static int elf_header_check(struct load_info *info)
|
|
|
+static int validate_section_offset(struct load_info *info, Elf_Shdr *shdr)
|
|
|
{
|
|
|
+ unsigned long secend;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Check for both overflow and offset/size being
|
|
|
+ * too large.
|
|
|
+ */
|
|
|
+ secend = shdr->sh_offset + shdr->sh_size;
|
|
|
+ if (secend < shdr->sh_offset || secend > info->len)
|
|
|
+ return -ENOEXEC;
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * Sanity checks against invalid binaries, wrong arch, weird elf version.
|
|
|
+ *
|
|
|
+ * Also do basic validity checks against section offsets and sizes, the
|
|
|
+ * section name string table, and the indices used for it (sh_name).
|
|
|
+ */
|
|
|
+static int elf_validity_check(struct load_info *info)
|
|
|
+{
|
|
|
+ unsigned int i;
|
|
|
+ Elf_Shdr *shdr, *strhdr;
|
|
|
+ int err;
|
|
|
+
|
|
|
if (info->len < sizeof(*(info->hdr)))
|
|
|
return -ENOEXEC;
|
|
|
|
|
@@ -2965,11 +2989,78 @@ static int elf_header_check(struct load_info *info)
|
|
|
|| info->hdr->e_shentsize != sizeof(Elf_Shdr))
|
|
|
return -ENOEXEC;
|
|
|
|
|
|
+ /*
|
|
|
+ * e_shnum is 16 bits, and sizeof(Elf_Shdr) is
|
|
|
+ * known and small. So e_shnum * sizeof(Elf_Shdr)
|
|
|
+ * will not overflow unsigned long on any platform.
|
|
|
+ */
|
|
|
if (info->hdr->e_shoff >= info->len
|
|
|
|| (info->hdr->e_shnum * sizeof(Elf_Shdr) >
|
|
|
info->len - info->hdr->e_shoff))
|
|
|
return -ENOEXEC;
|
|
|
|
|
|
+ info->sechdrs = (void *)info->hdr + info->hdr->e_shoff;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * 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;
|
|
|
+
|
|
|
+ strhdr = &info->sechdrs[info->hdr->e_shstrndx];
|
|
|
+ err = validate_section_offset(info, strhdr);
|
|
|
+ if (err < 0)
|
|
|
+ return err;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * The section name table must be NUL-terminated, as required
|
|
|
+ * by the spec. This makes strcmp and pr_* calls that access
|
|
|
+ * strings in the section safe.
|
|
|
+ */
|
|
|
+ info->secstrings = (void *)info->hdr + strhdr->sh_offset;
|
|
|
+ if (info->secstrings[strhdr->sh_size - 1] != '\0')
|
|
|
+ return -ENOEXEC;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * The code assumes that section 0 has a length of zero and
|
|
|
+ * an addr of zero, so check for it.
|
|
|
+ */
|
|
|
+ if (info->sechdrs[0].sh_type != SHT_NULL
|
|
|
+ || info->sechdrs[0].sh_size != 0
|
|
|
+ || info->sechdrs[0].sh_addr != 0)
|
|
|
+ return -ENOEXEC;
|
|
|
+
|
|
|
+ for (i = 1; i < info->hdr->e_shnum; i++) {
|
|
|
+ shdr = &info->sechdrs[i];
|
|
|
+ switch (shdr->sh_type) {
|
|
|
+ case SHT_NULL:
|
|
|
+ case SHT_NOBITS:
|
|
|
+ continue;
|
|
|
+ case SHT_SYMTAB:
|
|
|
+ if (shdr->sh_link == SHN_UNDEF
|
|
|
+ || shdr->sh_link >= info->hdr->e_shnum)
|
|
|
+ return -ENOEXEC;
|
|
|
+ fallthrough;
|
|
|
+ default:
|
|
|
+ err = validate_section_offset(info, shdr);
|
|
|
+ if (err < 0) {
|
|
|
+ pr_err("Invalid ELF section in module (section %u type %u)\n",
|
|
|
+ i, shdr->sh_type);
|
|
|
+ return err;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (shdr->sh_flags & SHF_ALLOC) {
|
|
|
+ if (shdr->sh_name >= strhdr->sh_size) {
|
|
|
+ pr_err("Invalid ELF section name in module (section %u type %u)\n",
|
|
|
+ i, shdr->sh_type);
|
|
|
+ return -ENOEXEC;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -3071,11 +3162,6 @@ static int rewrite_section_headers(struct load_info *info, int flags)
|
|
|
|
|
|
for (i = 1; i < info->hdr->e_shnum; i++) {
|
|
|
Elf_Shdr *shdr = &info->sechdrs[i];
|
|
|
- if (shdr->sh_type != SHT_NOBITS
|
|
|
- && info->len < shdr->sh_offset + shdr->sh_size) {
|
|
|
- pr_err("Module len %lu truncated\n", info->len);
|
|
|
- return -ENOEXEC;
|
|
|
- }
|
|
|
|
|
|
/* Mark all sections sh_addr with their address in the
|
|
|
temporary image. */
|
|
@@ -3107,11 +3193,6 @@ static int setup_load_info(struct load_info *info, int flags)
|
|
|
{
|
|
|
unsigned int i;
|
|
|
|
|
|
- /* Set up the convenience variables */
|
|
|
- info->sechdrs = (void *)info->hdr + info->hdr->e_shoff;
|
|
|
- info->secstrings = (void *)info->hdr
|
|
|
- + info->sechdrs[info->hdr->e_shstrndx].sh_offset;
|
|
|
-
|
|
|
/* Try to find a name early so we can log errors with a module name */
|
|
|
info->index.info = find_sec(info, ".modinfo");
|
|
|
if (info->index.info)
|
|
@@ -3855,26 +3936,50 @@ static int load_module(struct load_info *info, const char __user *uargs,
|
|
|
long err = 0;
|
|
|
char *after_dashes;
|
|
|
|
|
|
- err = elf_header_check(info);
|
|
|
+ /*
|
|
|
+ * Do the signature check (if any) first. All that
|
|
|
+ * the signature check needs is info->len, it does
|
|
|
+ * not need any of the section info. That can be
|
|
|
+ * set up later. This will minimize the chances
|
|
|
+ * of a corrupt module causing problems before
|
|
|
+ * we even get to the signature check.
|
|
|
+ *
|
|
|
+ * The check will also adjust info->len by stripping
|
|
|
+ * off the sig length at the end of the module, making
|
|
|
+ * checks against info->len more correct.
|
|
|
+ */
|
|
|
+ err = module_sig_check(info, flags);
|
|
|
+ if (err)
|
|
|
+ goto free_copy;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Do basic sanity checks against the ELF header and
|
|
|
+ * sections.
|
|
|
+ */
|
|
|
+ err = elf_validity_check(info);
|
|
|
if (err) {
|
|
|
- pr_err("Module has invalid ELF header\n");
|
|
|
+ pr_err("Module has invalid ELF structures\n");
|
|
|
goto free_copy;
|
|
|
}
|
|
|
|
|
|
+ /*
|
|
|
+ * Everything checks out, so set up the section info
|
|
|
+ * in the info structure.
|
|
|
+ */
|
|
|
err = setup_load_info(info, flags);
|
|
|
if (err)
|
|
|
goto free_copy;
|
|
|
|
|
|
+ /*
|
|
|
+ * Now that we know we have the correct module name, check
|
|
|
+ * if it's blacklisted.
|
|
|
+ */
|
|
|
if (blacklisted(info->name)) {
|
|
|
err = -EPERM;
|
|
|
pr_err("Module %s is blacklisted\n", info->name);
|
|
|
goto free_copy;
|
|
|
}
|
|
|
|
|
|
- err = module_sig_check(info, flags);
|
|
|
- if (err)
|
|
|
- goto free_copy;
|
|
|
-
|
|
|
err = rewrite_section_headers(info, flags);
|
|
|
if (err)
|
|
|
goto free_copy;
|