1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Module version support 4 * 5 * Copyright (C) 2008 Rusty Russell 6 */ 7 8 #include <linux/module.h> 9 #include <linux/string.h> 10 #include <linux/printk.h> 11 #include "internal.h" 12 13 int check_version(const struct load_info *info, 14 const char *symname, 15 struct module *mod, 16 const s32 *crc) 17 { 18 Elf_Shdr *sechdrs = info->sechdrs; 19 unsigned int versindex = info->index.vers; 20 unsigned int i, num_versions; 21 struct modversion_info *versions; 22 23 /* Exporting module didn't supply crcs? OK, we're already tainted. */ 24 if (!crc) 25 return 1; 26 27 /* No versions at all? modprobe --force does this. */ 28 if (versindex == 0) 29 return try_to_force_load(mod, symname) == 0; 30 31 versions = (void *)sechdrs[versindex].sh_addr; 32 num_versions = sechdrs[versindex].sh_size 33 / sizeof(struct modversion_info); 34 35 for (i = 0; i < num_versions; i++) { 36 u32 crcval; 37 38 if (strcmp(versions[i].name, symname) != 0) 39 continue; 40 41 crcval = *crc; 42 if (versions[i].crc == crcval) 43 return 1; 44 pr_debug("Found checksum %X vs module %lX\n", 45 crcval, versions[i].crc); 46 goto bad_version; 47 } 48 49 /* Broken toolchain. Warn once, then let it go.. */ 50 pr_warn_once("%s: no symbol version for %s\n", info->name, symname); 51 return 1; 52 53 bad_version: 54 pr_warn("%s: disagrees about version of symbol %s\n", info->name, symname); 55 return 0; 56 } 57 58 int check_modstruct_version(const struct load_info *info, 59 struct module *mod) 60 { 61 struct find_symbol_arg fsa = { 62 .name = "module_layout", 63 .gplok = true, 64 }; 65 66 /* 67 * Since this should be found in kernel (which can't be removed), no 68 * locking is necessary -- use preempt_disable() to placate lockdep. 69 */ 70 preempt_disable(); 71 if (!find_symbol(&fsa)) { 72 preempt_enable(); 73 BUG(); 74 } 75 preempt_enable(); 76 return check_version(info, "module_layout", mod, fsa.crc); 77 } 78 79 /* First part is kernel version, which we ignore if module has crcs. */ 80 int same_magic(const char *amagic, const char *bmagic, 81 bool has_crcs) 82 { 83 if (has_crcs) { 84 amagic += strcspn(amagic, " "); 85 bmagic += strcspn(bmagic, " "); 86 } 87 return strcmp(amagic, bmagic) == 0; 88 } 89 90 /* 91 * Generate the signature for all relevant module structures here. 92 * If these change, we don't want to try to parse the module. 93 */ 94 void module_layout(struct module *mod, 95 struct modversion_info *ver, 96 struct kernel_param *kp, 97 struct kernel_symbol *ks, 98 struct tracepoint * const *tp) 99 { 100 } 101 EXPORT_SYMBOL(module_layout); 102