module: change to print useful messages from elf_validity_check()
[sfrench/cifs-2.6.git] / kernel / module.c
index c7ad738074466706c90e8212193ed592cf172e10..84a9141a5e159a01642c6a67e4250e016de39797 100644 (file)
@@ -2971,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
@@ -2987,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;
 
@@ -2996,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
@@ -3010,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
@@ -3019,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];
@@ -3030,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);
@@ -3053,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)
@@ -3944,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