Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

+58 -21
+58 -21
kernel/module.c
··· 2942 2942 2943 2943 static int validate_section_offset(struct load_info *info, Elf_Shdr *shdr) 2944 2944 { 2945 + #if defined(CONFIG_64BIT) 2946 + unsigned long long secend; 2947 + #else 2945 2948 unsigned long secend; 2949 + #endif 2946 2950 2947 2951 /* 2948 2952 * Check for both overflow and offset/size being ··· 2971 2967 Elf_Shdr *shdr, *strhdr; 2972 2968 int err; 2973 2969 2974 - if (info->len < sizeof(*(info->hdr))) 2975 - 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 + } 2976 2974 2977 - if (memcmp(info->hdr->e_ident, ELFMAG, SELFMAG) != 0 2978 - || info->hdr->e_type != ET_REL 2979 - || !elf_check_arch(info->hdr) 2980 - || info->hdr->e_shentsize != sizeof(Elf_Shdr)) 2981 - 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 + } 2982 2993 2983 2994 /* 2984 2995 * e_shnum is 16 bits, and sizeof(Elf_Shdr) is ··· 3002 2983 */ 3003 2984 if (info->hdr->e_shoff >= info->len 3004 2985 || (info->hdr->e_shnum * sizeof(Elf_Shdr) > 3005 - info->len - info->hdr->e_shoff)) 3006 - return -ENOEXEC; 2986 + info->len - info->hdr->e_shoff)) { 2987 + pr_err("Invalid ELF section header overflow\n"); 2988 + goto no_exec; 2989 + } 3007 2990 3008 2991 info->sechdrs = (void *)info->hdr + info->hdr->e_shoff; 3009 2992 ··· 3013 2992 * Verify if the section name table index is valid. 3014 2993 */ 3015 2994 if (info->hdr->e_shstrndx == SHN_UNDEF 3016 - || info->hdr->e_shstrndx >= info->hdr->e_shnum) 3017 - return -ENOEXEC; 2995 + || info->hdr->e_shstrndx >= info->hdr->e_shnum) { 2996 + pr_err("Invalid ELF section name index: %d || e_shstrndx (%d) >= e_shnum (%d)\n", 2997 + info->hdr->e_shstrndx, info->hdr->e_shstrndx, 2998 + info->hdr->e_shnum); 2999 + goto no_exec; 3000 + } 3018 3001 3019 3002 strhdr = &info->sechdrs[info->hdr->e_shstrndx]; 3020 3003 err = validate_section_offset(info, strhdr); 3021 - if (err < 0) 3004 + if (err < 0) { 3005 + pr_err("Invalid ELF section hdr(type %u)\n", strhdr->sh_type); 3022 3006 return err; 3007 + } 3023 3008 3024 3009 /* 3025 3010 * The section name table must be NUL-terminated, as required ··· 3033 3006 * strings in the section safe. 3034 3007 */ 3035 3008 info->secstrings = (void *)info->hdr + strhdr->sh_offset; 3036 - if (info->secstrings[strhdr->sh_size - 1] != '\0') 3037 - return -ENOEXEC; 3009 + if (info->secstrings[strhdr->sh_size - 1] != '\0') { 3010 + pr_err("ELF Spec violation: section name table isn't null terminated\n"); 3011 + goto no_exec; 3012 + } 3038 3013 3039 3014 /* 3040 3015 * The code assumes that section 0 has a length of zero and ··· 3044 3015 */ 3045 3016 if (info->sechdrs[0].sh_type != SHT_NULL 3046 3017 || info->sechdrs[0].sh_size != 0 3047 - || info->sechdrs[0].sh_addr != 0) 3048 - return -ENOEXEC; 3018 + || info->sechdrs[0].sh_addr != 0) { 3019 + pr_err("ELF Spec violation: section 0 type(%d)!=SH_NULL or non-zero len or addr\n", 3020 + info->sechdrs[0].sh_type); 3021 + goto no_exec; 3022 + } 3049 3023 3050 3024 for (i = 1; i < info->hdr->e_shnum; i++) { 3051 3025 shdr = &info->sechdrs[i]; ··· 3058 3026 continue; 3059 3027 case SHT_SYMTAB: 3060 3028 if (shdr->sh_link == SHN_UNDEF 3061 - || shdr->sh_link >= info->hdr->e_shnum) 3062 - return -ENOEXEC; 3029 + || shdr->sh_link >= info->hdr->e_shnum) { 3030 + pr_err("Invalid ELF sh_link!=SHN_UNDEF(%d) or (sh_link(%d) >= hdr->e_shnum(%d)\n", 3031 + shdr->sh_link, shdr->sh_link, 3032 + info->hdr->e_shnum); 3033 + goto no_exec; 3034 + } 3063 3035 fallthrough; 3064 3036 default: 3065 3037 err = validate_section_offset(info, shdr); ··· 3085 3049 } 3086 3050 3087 3051 return 0; 3052 + 3053 + no_exec: 3054 + return -ENOEXEC; 3088 3055 } 3089 3056 3090 3057 #define COPY_CHUNK_SIZE (16*PAGE_SIZE) ··· 3979 3940 * sections. 3980 3941 */ 3981 3942 err = elf_validity_check(info); 3982 - if (err) { 3983 - pr_err("Module has invalid ELF structures\n"); 3943 + if (err) 3984 3944 goto free_copy; 3985 - } 3986 3945 3987 3946 /* 3988 3947 * Everything checks out, so set up the section info