}
 
        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;
        }
 
 }
 #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;
 
            || 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;
 }
 
 
        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
 {
        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)
        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;