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

Configure Feed

Select the types of activity you want to include in your feed.

module: harden ELF info handling

5fdc7db644 ("module: setup load info before module_sig_check()")
moved the ELF setup, so that it was done before the signature
check. This made the module name available to signature error
messages.

However, the checks for ELF correctness in setup_load_info
are not sufficient to prevent bad memory references due to
corrupted offset fields, indices, etc.

So, there's a regression in behavior here: a corrupt and unsigned
(or badly signed) module, which might previously have been rejected
immediately, can now cause an oops/crash.

Harden ELF handling for module loading by doing the following:

- Move the signature check back up so that it comes before ELF
initialization. It's best to do the signature check to see
if we can trust the module, before using the ELF structures
inside it. This also makes checks against info->len
more accurate again, as this field will be reduced by the
length of the signature in mod_check_sig().

The module name is now once again not available for error
messages during the signature check, but that seems like
a fair tradeoff.

- Check if sections have offset / size fields that at least don't
exceed the length of the module.

- Check if sections have section name offsets that don't fall
outside the section name table.

- Add a few other sanity checks against invalid section indices,
etc.

This is not an exhaustive consistency check, but the idea is to
at least get through the signature and blacklist checks without
crashing because of corrupted ELF info, and to error out gracefully
for most issues that would have caused problems later on.

Fixes: 5fdc7db6448a ("module: setup load info before module_sig_check()")
Signed-off-by: Frank van der Linden <fllinden@amazon.com>
Signed-off-by: Jessica Yu <jeyu@kernel.org>

authored by

Frank van der Linden and committed by
Jessica Yu
ec2a2959 ebfac7b7

+126 -21
+124 -19
kernel/module.c
··· 2981 2981 } 2982 2982 2983 2983 if (is_module_sig_enforced()) { 2984 - pr_notice("%s: loading of %s is rejected\n", info->name, reason); 2984 + pr_notice("Loading of %s is rejected\n", reason); 2985 2985 return -EKEYREJECTED; 2986 2986 } 2987 2987 ··· 2994 2994 } 2995 2995 #endif /* !CONFIG_MODULE_SIG */ 2996 2996 2997 - /* Sanity checks against invalid binaries, wrong arch, weird elf version. */ 2998 - static int elf_header_check(struct load_info *info) 2997 + static int validate_section_offset(struct load_info *info, Elf_Shdr *shdr) 2999 2998 { 2999 + unsigned long secend; 3000 + 3001 + /* 3002 + * Check for both overflow and offset/size being 3003 + * too large. 3004 + */ 3005 + secend = shdr->sh_offset + shdr->sh_size; 3006 + if (secend < shdr->sh_offset || secend > info->len) 3007 + return -ENOEXEC; 3008 + 3009 + return 0; 3010 + } 3011 + 3012 + /* 3013 + * Sanity checks against invalid binaries, wrong arch, weird elf version. 3014 + * 3015 + * Also do basic validity checks against section offsets and sizes, the 3016 + * section name string table, and the indices used for it (sh_name). 3017 + */ 3018 + static int elf_validity_check(struct load_info *info) 3019 + { 3020 + unsigned int i; 3021 + Elf_Shdr *shdr, *strhdr; 3022 + int err; 3023 + 3000 3024 if (info->len < sizeof(*(info->hdr))) 3001 3025 return -ENOEXEC; 3002 3026 ··· 3030 3006 || info->hdr->e_shentsize != sizeof(Elf_Shdr)) 3031 3007 return -ENOEXEC; 3032 3008 3009 + /* 3010 + * e_shnum is 16 bits, and sizeof(Elf_Shdr) is 3011 + * known and small. So e_shnum * sizeof(Elf_Shdr) 3012 + * will not overflow unsigned long on any platform. 3013 + */ 3033 3014 if (info->hdr->e_shoff >= info->len 3034 3015 || (info->hdr->e_shnum * sizeof(Elf_Shdr) > 3035 3016 info->len - info->hdr->e_shoff)) 3036 3017 return -ENOEXEC; 3018 + 3019 + info->sechdrs = (void *)info->hdr + info->hdr->e_shoff; 3020 + 3021 + /* 3022 + * Verify if the section name table index is valid. 3023 + */ 3024 + if (info->hdr->e_shstrndx == SHN_UNDEF 3025 + || info->hdr->e_shstrndx >= info->hdr->e_shnum) 3026 + return -ENOEXEC; 3027 + 3028 + strhdr = &info->sechdrs[info->hdr->e_shstrndx]; 3029 + err = validate_section_offset(info, strhdr); 3030 + if (err < 0) 3031 + return err; 3032 + 3033 + /* 3034 + * The section name table must be NUL-terminated, as required 3035 + * by the spec. This makes strcmp and pr_* calls that access 3036 + * strings in the section safe. 3037 + */ 3038 + info->secstrings = (void *)info->hdr + strhdr->sh_offset; 3039 + if (info->secstrings[strhdr->sh_size - 1] != '\0') 3040 + return -ENOEXEC; 3041 + 3042 + /* 3043 + * The code assumes that section 0 has a length of zero and 3044 + * an addr of zero, so check for it. 3045 + */ 3046 + if (info->sechdrs[0].sh_type != SHT_NULL 3047 + || info->sechdrs[0].sh_size != 0 3048 + || info->sechdrs[0].sh_addr != 0) 3049 + return -ENOEXEC; 3050 + 3051 + for (i = 1; i < info->hdr->e_shnum; i++) { 3052 + shdr = &info->sechdrs[i]; 3053 + switch (shdr->sh_type) { 3054 + case SHT_NULL: 3055 + case SHT_NOBITS: 3056 + continue; 3057 + case SHT_SYMTAB: 3058 + if (shdr->sh_link == SHN_UNDEF 3059 + || shdr->sh_link >= info->hdr->e_shnum) 3060 + return -ENOEXEC; 3061 + fallthrough; 3062 + default: 3063 + err = validate_section_offset(info, shdr); 3064 + if (err < 0) { 3065 + pr_err("Invalid ELF section in module (section %u type %u)\n", 3066 + i, shdr->sh_type); 3067 + return err; 3068 + } 3069 + 3070 + if (shdr->sh_flags & SHF_ALLOC) { 3071 + if (shdr->sh_name >= strhdr->sh_size) { 3072 + pr_err("Invalid ELF section name in module (section %u type %u)\n", 3073 + i, shdr->sh_type); 3074 + return -ENOEXEC; 3075 + } 3076 + } 3077 + break; 3078 + } 3079 + } 3037 3080 3038 3081 return 0; 3039 3082 } ··· 3203 3112 3204 3113 for (i = 1; i < info->hdr->e_shnum; i++) { 3205 3114 Elf_Shdr *shdr = &info->sechdrs[i]; 3206 - if (shdr->sh_type != SHT_NOBITS 3207 - && info->len < shdr->sh_offset + shdr->sh_size) { 3208 - pr_err("Module len %lu truncated\n", info->len); 3209 - return -ENOEXEC; 3210 - } 3211 3115 3212 3116 /* 3213 3117 * Mark all sections sh_addr with their address in the ··· 3235 3149 static int setup_load_info(struct load_info *info, int flags) 3236 3150 { 3237 3151 unsigned int i; 3238 - 3239 - /* Set up the convenience variables */ 3240 - info->sechdrs = (void *)info->hdr + info->hdr->e_shoff; 3241 - info->secstrings = (void *)info->hdr 3242 - + info->sechdrs[info->hdr->e_shstrndx].sh_offset; 3243 3152 3244 3153 /* Try to find a name early so we can log errors with a module name */ 3245 3154 info->index.info = find_sec(info, ".modinfo"); ··· 3992 3911 long err = 0; 3993 3912 char *after_dashes; 3994 3913 3995 - err = elf_header_check(info); 3914 + /* 3915 + * Do the signature check (if any) first. All that 3916 + * the signature check needs is info->len, it does 3917 + * not need any of the section info. That can be 3918 + * set up later. This will minimize the chances 3919 + * of a corrupt module causing problems before 3920 + * we even get to the signature check. 3921 + * 3922 + * The check will also adjust info->len by stripping 3923 + * off the sig length at the end of the module, making 3924 + * checks against info->len more correct. 3925 + */ 3926 + err = module_sig_check(info, flags); 3927 + if (err) 3928 + goto free_copy; 3929 + 3930 + /* 3931 + * Do basic sanity checks against the ELF header and 3932 + * sections. 3933 + */ 3934 + err = elf_validity_check(info); 3996 3935 if (err) { 3997 - pr_err("Module has invalid ELF header\n"); 3936 + pr_err("Module has invalid ELF structures\n"); 3998 3937 goto free_copy; 3999 3938 } 4000 3939 3940 + /* 3941 + * Everything checks out, so set up the section info 3942 + * in the info structure. 3943 + */ 4001 3944 err = setup_load_info(info, flags); 4002 3945 if (err) 4003 3946 goto free_copy; 4004 3947 3948 + /* 3949 + * Now that we know we have the correct module name, check 3950 + * if it's blacklisted. 3951 + */ 4005 3952 if (blacklisted(info->name)) { 4006 3953 err = -EPERM; 4007 3954 pr_err("Module %s is blacklisted\n", info->name); 4008 3955 goto free_copy; 4009 3956 } 4010 - 4011 - err = module_sig_check(info, flags); 4012 - if (err) 4013 - goto free_copy; 4014 3957 4015 3958 err = rewrite_section_headers(info, flags); 4016 3959 if (err)
+1 -1
kernel/module_signature.c
··· 25 25 return -EBADMSG; 26 26 27 27 if (ms->id_type != PKEY_ID_PKCS7) { 28 - pr_err("%s: Module is not signed with expected PKCS#7 message\n", 28 + pr_err("%s: not signed with expected PKCS#7 message\n", 29 29 name); 30 30 return -ENOPKG; 31 31 }
+1 -1
kernel/module_signing.c
··· 30 30 31 31 memcpy(&ms, mod + (modlen - sizeof(ms)), sizeof(ms)); 32 32 33 - ret = mod_check_sig(&ms, modlen, info->name); 33 + ret = mod_check_sig(&ms, modlen, "module"); 34 34 if (ret) 35 35 return ret; 36 36