History

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.

Frank van der Linden committed 5 years ago

Commit ec2a2951 parent ebfac7b3 files · +126 −21Browse files

Showing the changes to kernel (3 of 3 files). Show all

Unified · Split

3 files
  1. kernel/module.c +124 −19
  2. kernel/module_signature.c +1 −1
  3. kernel/module_signing.c +1 −1
kernel/module.c+124−19
@@ -2981,7 +2981,7 @@ static int module_sig_check(struct load_info *info, int flags) · 2980 unmodified lines
2981 }2981 }
2982 2982
2983 if (is_module_sig_enforced()) {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 return -EKEYREJECTED;2985 return -EKEYREJECTED;
2986 }2986 }
2987 2987
@@ -2994,9 +2994,33 @@ static int module_sig_check(struct load_info *info, int flags) · 6 unmodified lines
2994}2994}
2995#endif /* !CONFIG_MODULE_SIG */2995#endif /* !CONFIG_MODULE_SIG */
2996 2996
2997/* Sanity checks against invalid binaries, wrong arch, weird elf version. */2997static int validate_section_offset(struct load_info *info, Elf_Shdr *shdr)
2998static int elf_header_check(struct load_info *info)
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 */
3018static int elf_validity_check(struct load_info *info)
3019{
3020 unsigned int i;
3021 Elf_Shdr *shdr, *strhdr;
3022 int err;
3023
3000 if (info->len < sizeof(*(info->hdr)))3024 if (info->len < sizeof(*(info->hdr)))
3001 return -ENOEXEC;3025 return -ENOEXEC;
3002 3026
@@ -3006,11 +3030,78 @@ static int elf_header_check(struct load_info *info) · 3 unmodified lines
3006 || info->hdr->e_shentsize != sizeof(Elf_Shdr))3030 || info->hdr->e_shentsize != sizeof(Elf_Shdr))
3007 return -ENOEXEC;3031 return -ENOEXEC;
3008 3032
3033 /*
3034 * e_shnum is 16 bits, and sizeof(Elf_Shdr) is
3035 * known and small. So e_shnum * sizeof(Elf_Shdr)
3036 * will not overflow unsigned long on any platform.
3037 */
3009 if (info->hdr->e_shoff >= info->len3038 if (info->hdr->e_shoff >= info->len
3010 || (info->hdr->e_shnum * sizeof(Elf_Shdr) >3039 || (info->hdr->e_shnum * sizeof(Elf_Shdr) >
3011 info->len - info->hdr->e_shoff))3040 info->len - info->hdr->e_shoff))
3012 return -ENOEXEC;3041 return -ENOEXEC;
3013 3042
3043 info->sechdrs = (void *)info->hdr + info->hdr->e_shoff;
3044
3045 /*
3046 * Verify if the section name table index is valid.
3047 */
3048 if (info->hdr->e_shstrndx == SHN_UNDEF
3049 || info->hdr->e_shstrndx >= info->hdr->e_shnum)
3050 return -ENOEXEC;
3051
3052 strhdr = &info->sechdrs[info->hdr->e_shstrndx];
3053 err = validate_section_offset(info, strhdr);
3054 if (err < 0)
3055 return err;
3056
3057 /*
3058 * The section name table must be NUL-terminated, as required
3059 * by the spec. This makes strcmp and pr_* calls that access
3060 * strings in the section safe.
3061 */
3062 info->secstrings = (void *)info->hdr + strhdr->sh_offset;
3063 if (info->secstrings[strhdr->sh_size - 1] != '\0')
3064 return -ENOEXEC;
3065
3066 /*
3067 * The code assumes that section 0 has a length of zero and
3068 * an addr of zero, so check for it.
3069 */
3070 if (info->sechdrs[0].sh_type != SHT_NULL
3071 || info->sechdrs[0].sh_size != 0
3072 || info->sechdrs[0].sh_addr != 0)
3073 return -ENOEXEC;
3074
3075 for (i = 1; i < info->hdr->e_shnum; i++) {
3076 shdr = &info->sechdrs[i];
3077 switch (shdr->sh_type) {
3078 case SHT_NULL:
3079 case SHT_NOBITS:
3080 continue;
3081 case SHT_SYMTAB:
3082 if (shdr->sh_link == SHN_UNDEF
3083 || shdr->sh_link >= info->hdr->e_shnum)
3084 return -ENOEXEC;
3085 fallthrough;
3086 default:
3087 err = validate_section_offset(info, shdr);
3088 if (err < 0) {
3089 pr_err("Invalid ELF section in module (section %u type %u)\n",
3090 i, shdr->sh_type);
3091 return err;
3092 }
3093
3094 if (shdr->sh_flags & SHF_ALLOC) {
3095 if (shdr->sh_name >= strhdr->sh_size) {
3096 pr_err("Invalid ELF section name in module (section %u type %u)\n",
3097 i, shdr->sh_type);
3098 return -ENOEXEC;
3099 }
3100 }
3101 break;
3102 }
3103 }
3104
3014 return 0;3105 return 0;
3015}3106}
3016 3107
@@ -3112,11 +3203,6 @@ static int rewrite_section_headers(struct load_info *info, int flags) · 95 unmodified lines
3112 3203
3113 for (i = 1; i < info->hdr->e_shnum; i++) {3204 for (i = 1; i < info->hdr->e_shnum; i++) {
3114 Elf_Shdr *shdr = &info->sechdrs[i];3205 Elf_Shdr *shdr = &info->sechdrs[i];
3115 if (shdr->sh_type != SHT_NOBITS
3116 && info->len < shdr->sh_offset + shdr->sh_size) {
3117 pr_err("Module len %lu truncated\n", info->len);
3118 return -ENOEXEC;
3119 }
3120 3206
3121 /*3207 /*
3122 * Mark all sections sh_addr with their address in the3208 * Mark all sections sh_addr with their address in the
@@ -3150,11 +3236,6 @@ static int setup_load_info(struct load_info *info, int flags) · 27 unmodified lines
3150{3236{
3151 unsigned int i;3237 unsigned int i;
3152 3238
3153 /* Set up the convenience variables */
3154 info->sechdrs = (void *)info->hdr + info->hdr->e_shoff;
3155 info->secstrings = (void *)info->hdr
3156 + info->sechdrs[info->hdr->e_shstrndx].sh_offset;
3157
3158 /* Try to find a name early so we can log errors with a module name */3239 /* Try to find a name early so we can log errors with a module name */
3159 info->index.info = find_sec(info, ".modinfo");3240 info->index.info = find_sec(info, ".modinfo");
3160 if (info->index.info)3241 if (info->index.info)
@@ -3911,26 +3992,50 @@ static int load_module(struct load_info *info, const char __user *uargs, · 750 unmodified lines
3911 long err = 0;3992 long err = 0;
3912 char *after_dashes;3993 char *after_dashes;
3913 3994
3914 err = elf_header_check(info);3995 /*
3996 * Do the signature check (if any) first. All that
3997 * the signature check needs is info->len, it does
3998 * not need any of the section info. That can be
3999 * set up later. This will minimize the chances
4000 * of a corrupt module causing problems before
4001 * we even get to the signature check.
4002 *
4003 * The check will also adjust info->len by stripping
4004 * off the sig length at the end of the module, making
4005 * checks against info->len more correct.
4006 */
4007 err = module_sig_check(info, flags);
4008 if (err)
4009 goto free_copy;
4010
4011 /*
4012 * Do basic sanity checks against the ELF header and
4013 * sections.
4014 */
4015 err = elf_validity_check(info);
3915 if (err) {4016 if (err) {
3916 pr_err("Module has invalid ELF header\n");4017 pr_err("Module has invalid ELF structures\n");
3917 goto free_copy;4018 goto free_copy;
3918 }4019 }
3919 4020
4021 /*
4022 * Everything checks out, so set up the section info
4023 * in the info structure.
4024 */
3920 err = setup_load_info(info, flags);4025 err = setup_load_info(info, flags);
3921 if (err)4026 if (err)
3922 goto free_copy;4027 goto free_copy;
3923 4028
4029 /*
4030 * Now that we know we have the correct module name, check
4031 * if it's blacklisted.
4032 */
3924 if (blacklisted(info->name)) {4033 if (blacklisted(info->name)) {
3925 err = -EPERM;4034 err = -EPERM;
3926 pr_err("Module %s is blacklisted\n", info->name);4035 pr_err("Module %s is blacklisted\n", info->name);
3927 goto free_copy;4036 goto free_copy;
3928 }4037 }
3929 4038
3930 err = module_sig_check(info, flags);
3931 if (err)
3932 goto free_copy;
3933
3934 err = rewrite_section_headers(info, flags);4039 err = rewrite_section_headers(info, flags);
3935 if (err)4040 if (err)
3936 goto free_copy;4041 goto free_copy;
kernel/module_signature.c+1−1
@@ -25,7 +25,7 @@ int mod_check_sig(const struct module_signature *ms, size_t file_len, · 24 unmodified lines
25 return -EBADMSG;25 return -EBADMSG;
26 26
27 if (ms->id_type != PKEY_ID_PKCS7) {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 name);29 name);
30 return -ENOPKG;30 return -ENOPKG;
31 }31 }
kernel/module_signing.c+1−1
@@ -30,7 +30,7 @@ int mod_verify_sig(const void *mod, struct load_info *info) · 29 unmodified lines
30 30
31 memcpy(&ms, mod + (modlen - sizeof(ms)), sizeof(ms));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 if (ret)34 if (ret)
35 return ret;35 return ret;
36 36

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t