diff options
Diffstat (limited to 'kernel/module.c')
-rw-r--r-- | kernel/module.c | 53 |
1 files changed, 25 insertions, 28 deletions
diff --git a/kernel/module.c b/kernel/module.c index 38d4270925d4..3d8f126208e3 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
@@ -389,16 +389,16 @@ extern const struct kernel_symbol __start___ksymtab_gpl[]; | |||
389 | extern const struct kernel_symbol __stop___ksymtab_gpl[]; | 389 | extern const struct kernel_symbol __stop___ksymtab_gpl[]; |
390 | extern const struct kernel_symbol __start___ksymtab_gpl_future[]; | 390 | extern const struct kernel_symbol __start___ksymtab_gpl_future[]; |
391 | extern const struct kernel_symbol __stop___ksymtab_gpl_future[]; | 391 | extern const struct kernel_symbol __stop___ksymtab_gpl_future[]; |
392 | extern const unsigned long __start___kcrctab[]; | 392 | extern const s32 __start___kcrctab[]; |
393 | extern const unsigned long __start___kcrctab_gpl[]; | 393 | extern const s32 __start___kcrctab_gpl[]; |
394 | extern const unsigned long __start___kcrctab_gpl_future[]; | 394 | extern const s32 __start___kcrctab_gpl_future[]; |
395 | #ifdef CONFIG_UNUSED_SYMBOLS | 395 | #ifdef CONFIG_UNUSED_SYMBOLS |
396 | extern const struct kernel_symbol __start___ksymtab_unused[]; | 396 | extern const struct kernel_symbol __start___ksymtab_unused[]; |
397 | extern const struct kernel_symbol __stop___ksymtab_unused[]; | 397 | extern const struct kernel_symbol __stop___ksymtab_unused[]; |
398 | extern const struct kernel_symbol __start___ksymtab_unused_gpl[]; | 398 | extern const struct kernel_symbol __start___ksymtab_unused_gpl[]; |
399 | extern const struct kernel_symbol __stop___ksymtab_unused_gpl[]; | 399 | extern const struct kernel_symbol __stop___ksymtab_unused_gpl[]; |
400 | extern const unsigned long __start___kcrctab_unused[]; | 400 | extern const s32 __start___kcrctab_unused[]; |
401 | extern const unsigned long __start___kcrctab_unused_gpl[]; | 401 | extern const s32 __start___kcrctab_unused_gpl[]; |
402 | #endif | 402 | #endif |
403 | 403 | ||
404 | #ifndef CONFIG_MODVERSIONS | 404 | #ifndef CONFIG_MODVERSIONS |
@@ -497,7 +497,7 @@ struct find_symbol_arg { | |||
497 | 497 | ||
498 | /* Output */ | 498 | /* Output */ |
499 | struct module *owner; | 499 | struct module *owner; |
500 | const unsigned long *crc; | 500 | const s32 *crc; |
501 | const struct kernel_symbol *sym; | 501 | const struct kernel_symbol *sym; |
502 | }; | 502 | }; |
503 | 503 | ||
@@ -563,7 +563,7 @@ static bool find_symbol_in_section(const struct symsearch *syms, | |||
563 | * (optional) module which owns it. Needs preempt disabled or module_mutex. */ | 563 | * (optional) module which owns it. Needs preempt disabled or module_mutex. */ |
564 | const struct kernel_symbol *find_symbol(const char *name, | 564 | const struct kernel_symbol *find_symbol(const char *name, |
565 | struct module **owner, | 565 | struct module **owner, |
566 | const unsigned long **crc, | 566 | const s32 **crc, |
567 | bool gplok, | 567 | bool gplok, |
568 | bool warn) | 568 | bool warn) |
569 | { | 569 | { |
@@ -1249,23 +1249,17 @@ static int try_to_force_load(struct module *mod, const char *reason) | |||
1249 | } | 1249 | } |
1250 | 1250 | ||
1251 | #ifdef CONFIG_MODVERSIONS | 1251 | #ifdef CONFIG_MODVERSIONS |
1252 | /* If the arch applies (non-zero) relocations to kernel kcrctab, unapply it. */ | 1252 | |
1253 | static unsigned long maybe_relocated(unsigned long crc, | 1253 | static u32 resolve_rel_crc(const s32 *crc) |
1254 | const struct module *crc_owner) | ||
1255 | { | 1254 | { |
1256 | #ifdef ARCH_RELOCATES_KCRCTAB | 1255 | return *(u32 *)((void *)crc + *crc); |
1257 | if (crc_owner == NULL) | ||
1258 | return crc - (unsigned long)reloc_start; | ||
1259 | #endif | ||
1260 | return crc; | ||
1261 | } | 1256 | } |
1262 | 1257 | ||
1263 | static int check_version(Elf_Shdr *sechdrs, | 1258 | static int check_version(Elf_Shdr *sechdrs, |
1264 | unsigned int versindex, | 1259 | unsigned int versindex, |
1265 | const char *symname, | 1260 | const char *symname, |
1266 | struct module *mod, | 1261 | struct module *mod, |
1267 | const unsigned long *crc, | 1262 | const s32 *crc) |
1268 | const struct module *crc_owner) | ||
1269 | { | 1263 | { |
1270 | unsigned int i, num_versions; | 1264 | unsigned int i, num_versions; |
1271 | struct modversion_info *versions; | 1265 | struct modversion_info *versions; |
@@ -1283,13 +1277,19 @@ static int check_version(Elf_Shdr *sechdrs, | |||
1283 | / sizeof(struct modversion_info); | 1277 | / sizeof(struct modversion_info); |
1284 | 1278 | ||
1285 | for (i = 0; i < num_versions; i++) { | 1279 | for (i = 0; i < num_versions; i++) { |
1280 | u32 crcval; | ||
1281 | |||
1286 | if (strcmp(versions[i].name, symname) != 0) | 1282 | if (strcmp(versions[i].name, symname) != 0) |
1287 | continue; | 1283 | continue; |
1288 | 1284 | ||
1289 | if (versions[i].crc == maybe_relocated(*crc, crc_owner)) | 1285 | if (IS_ENABLED(CONFIG_MODULE_REL_CRCS)) |
1286 | crcval = resolve_rel_crc(crc); | ||
1287 | else | ||
1288 | crcval = *crc; | ||
1289 | if (versions[i].crc == crcval) | ||
1290 | return 1; | 1290 | return 1; |
1291 | pr_debug("Found checksum %lX vs module %lX\n", | 1291 | pr_debug("Found checksum %X vs module %lX\n", |
1292 | maybe_relocated(*crc, crc_owner), versions[i].crc); | 1292 | crcval, versions[i].crc); |
1293 | goto bad_version; | 1293 | goto bad_version; |
1294 | } | 1294 | } |
1295 | 1295 | ||
@@ -1307,7 +1307,7 @@ static inline int check_modstruct_version(Elf_Shdr *sechdrs, | |||
1307 | unsigned int versindex, | 1307 | unsigned int versindex, |
1308 | struct module *mod) | 1308 | struct module *mod) |
1309 | { | 1309 | { |
1310 | const unsigned long *crc; | 1310 | const s32 *crc; |
1311 | 1311 | ||
1312 | /* | 1312 | /* |
1313 | * Since this should be found in kernel (which can't be removed), no | 1313 | * Since this should be found in kernel (which can't be removed), no |
@@ -1321,8 +1321,7 @@ static inline int check_modstruct_version(Elf_Shdr *sechdrs, | |||
1321 | } | 1321 | } |
1322 | preempt_enable(); | 1322 | preempt_enable(); |
1323 | return check_version(sechdrs, versindex, | 1323 | return check_version(sechdrs, versindex, |
1324 | VMLINUX_SYMBOL_STR(module_layout), mod, crc, | 1324 | VMLINUX_SYMBOL_STR(module_layout), mod, crc); |
1325 | NULL); | ||
1326 | } | 1325 | } |
1327 | 1326 | ||
1328 | /* First part is kernel version, which we ignore if module has crcs. */ | 1327 | /* First part is kernel version, which we ignore if module has crcs. */ |
@@ -1340,8 +1339,7 @@ static inline int check_version(Elf_Shdr *sechdrs, | |||
1340 | unsigned int versindex, | 1339 | unsigned int versindex, |
1341 | const char *symname, | 1340 | const char *symname, |
1342 | struct module *mod, | 1341 | struct module *mod, |
1343 | const unsigned long *crc, | 1342 | const s32 *crc) |
1344 | const struct module *crc_owner) | ||
1345 | { | 1343 | { |
1346 | return 1; | 1344 | return 1; |
1347 | } | 1345 | } |
@@ -1368,7 +1366,7 @@ static const struct kernel_symbol *resolve_symbol(struct module *mod, | |||
1368 | { | 1366 | { |
1369 | struct module *owner; | 1367 | struct module *owner; |
1370 | const struct kernel_symbol *sym; | 1368 | const struct kernel_symbol *sym; |
1371 | const unsigned long *crc; | 1369 | const s32 *crc; |
1372 | int err; | 1370 | int err; |
1373 | 1371 | ||
1374 | /* | 1372 | /* |
@@ -1383,8 +1381,7 @@ static const struct kernel_symbol *resolve_symbol(struct module *mod, | |||
1383 | if (!sym) | 1381 | if (!sym) |
1384 | goto unlock; | 1382 | goto unlock; |
1385 | 1383 | ||
1386 | if (!check_version(info->sechdrs, info->index.vers, name, mod, crc, | 1384 | if (!check_version(info->sechdrs, info->index.vers, name, mod, crc)) { |
1387 | owner)) { | ||
1388 | sym = ERR_PTR(-EINVAL); | 1385 | sym = ERR_PTR(-EINVAL); |
1389 | goto getname; | 1386 | goto getname; |
1390 | } | 1387 | } |