diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/module.c | 75 |
1 files changed, 37 insertions, 38 deletions
diff --git a/kernel/module.c b/kernel/module.c index 7af72bbe4cc0..2f0fddf3c114 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
@@ -283,7 +283,7 @@ struct find_symbol_arg { | |||
283 | /* Output */ | 283 | /* Output */ |
284 | struct module *owner; | 284 | struct module *owner; |
285 | const unsigned long *crc; | 285 | const unsigned long *crc; |
286 | unsigned long value; | 286 | const struct kernel_symbol *sym; |
287 | }; | 287 | }; |
288 | 288 | ||
289 | static bool find_symbol_in_section(const struct symsearch *syms, | 289 | static bool find_symbol_in_section(const struct symsearch *syms, |
@@ -324,17 +324,17 @@ static bool find_symbol_in_section(const struct symsearch *syms, | |||
324 | 324 | ||
325 | fsa->owner = owner; | 325 | fsa->owner = owner; |
326 | fsa->crc = symversion(syms->crcs, symnum); | 326 | fsa->crc = symversion(syms->crcs, symnum); |
327 | fsa->value = syms->start[symnum].value; | 327 | fsa->sym = &syms->start[symnum]; |
328 | return true; | 328 | return true; |
329 | } | 329 | } |
330 | 330 | ||
331 | /* Find a symbol, return value, (optional) crc and (optional) module | 331 | /* Find a symbol and return it, along with, (optional) crc and |
332 | * which owns it */ | 332 | * (optional) module which owns it */ |
333 | static unsigned long find_symbol(const char *name, | 333 | static const struct kernel_symbol *find_symbol(const char *name, |
334 | struct module **owner, | 334 | struct module **owner, |
335 | const unsigned long **crc, | 335 | const unsigned long **crc, |
336 | bool gplok, | 336 | bool gplok, |
337 | bool warn) | 337 | bool warn) |
338 | { | 338 | { |
339 | struct find_symbol_arg fsa; | 339 | struct find_symbol_arg fsa; |
340 | 340 | ||
@@ -347,11 +347,11 @@ static unsigned long find_symbol(const char *name, | |||
347 | *owner = fsa.owner; | 347 | *owner = fsa.owner; |
348 | if (crc) | 348 | if (crc) |
349 | *crc = fsa.crc; | 349 | *crc = fsa.crc; |
350 | return fsa.value; | 350 | return fsa.sym; |
351 | } | 351 | } |
352 | 352 | ||
353 | DEBUGP("Failed to find symbol %s\n", name); | 353 | DEBUGP("Failed to find symbol %s\n", name); |
354 | return -ENOENT; | 354 | return NULL; |
355 | } | 355 | } |
356 | 356 | ||
357 | /* Search for module by name: must hold module_mutex. */ | 357 | /* Search for module by name: must hold module_mutex. */ |
@@ -894,7 +894,7 @@ void __symbol_put(const char *symbol) | |||
894 | struct module *owner; | 894 | struct module *owner; |
895 | 895 | ||
896 | preempt_disable(); | 896 | preempt_disable(); |
897 | if (IS_ERR_VALUE(find_symbol(symbol, &owner, NULL, true, false))) | 897 | if (!find_symbol(symbol, &owner, NULL, true, false)) |
898 | BUG(); | 898 | BUG(); |
899 | module_put(owner); | 899 | module_put(owner); |
900 | preempt_enable(); | 900 | preempt_enable(); |
@@ -1057,7 +1057,7 @@ static inline int check_modstruct_version(Elf_Shdr *sechdrs, | |||
1057 | { | 1057 | { |
1058 | const unsigned long *crc; | 1058 | const unsigned long *crc; |
1059 | 1059 | ||
1060 | if (IS_ERR_VALUE(find_symbol("struct_module", NULL, &crc, true, false))) | 1060 | if (!find_symbol("struct_module", NULL, &crc, true, false)) |
1061 | BUG(); | 1061 | BUG(); |
1062 | return check_version(sechdrs, versindex, "struct_module", mod, crc); | 1062 | return check_version(sechdrs, versindex, "struct_module", mod, crc); |
1063 | } | 1063 | } |
@@ -1098,25 +1098,25 @@ static inline int same_magic(const char *amagic, const char *bmagic, | |||
1098 | 1098 | ||
1099 | /* Resolve a symbol for this module. I.e. if we find one, record usage. | 1099 | /* Resolve a symbol for this module. I.e. if we find one, record usage. |
1100 | Must be holding module_mutex. */ | 1100 | Must be holding module_mutex. */ |
1101 | static unsigned long resolve_symbol(Elf_Shdr *sechdrs, | 1101 | static const struct kernel_symbol *resolve_symbol(Elf_Shdr *sechdrs, |
1102 | unsigned int versindex, | 1102 | unsigned int versindex, |
1103 | const char *name, | 1103 | const char *name, |
1104 | struct module *mod) | 1104 | struct module *mod) |
1105 | { | 1105 | { |
1106 | struct module *owner; | 1106 | struct module *owner; |
1107 | unsigned long ret; | 1107 | const struct kernel_symbol *sym; |
1108 | const unsigned long *crc; | 1108 | const unsigned long *crc; |
1109 | 1109 | ||
1110 | ret = find_symbol(name, &owner, &crc, | 1110 | sym = find_symbol(name, &owner, &crc, |
1111 | !(mod->taints & (1 << TAINT_PROPRIETARY_MODULE)), true); | 1111 | !(mod->taints & (1 << TAINT_PROPRIETARY_MODULE)), true); |
1112 | if (!IS_ERR_VALUE(ret)) { | 1112 | /* use_module can fail due to OOM, |
1113 | /* use_module can fail due to OOM, | 1113 | or module initialization or unloading */ |
1114 | or module initialization or unloading */ | 1114 | if (sym) { |
1115 | if (!check_version(sechdrs, versindex, name, mod, crc) || | 1115 | if (!check_version(sechdrs, versindex, name, mod, crc) || |
1116 | !use_module(mod, owner)) | 1116 | !use_module(mod, owner)) |
1117 | ret = -EINVAL; | 1117 | sym = NULL; |
1118 | } | 1118 | } |
1119 | return ret; | 1119 | return sym; |
1120 | } | 1120 | } |
1121 | 1121 | ||
1122 | /* | 1122 | /* |
@@ -1516,17 +1516,15 @@ static void free_module(struct module *mod) | |||
1516 | void *__symbol_get(const char *symbol) | 1516 | void *__symbol_get(const char *symbol) |
1517 | { | 1517 | { |
1518 | struct module *owner; | 1518 | struct module *owner; |
1519 | unsigned long value; | 1519 | const struct kernel_symbol *sym; |
1520 | 1520 | ||
1521 | preempt_disable(); | 1521 | preempt_disable(); |
1522 | value = find_symbol(symbol, &owner, NULL, true, true); | 1522 | sym = find_symbol(symbol, &owner, NULL, true, true); |
1523 | if (IS_ERR_VALUE(value)) | 1523 | if (sym && strong_try_module_get(owner)) |
1524 | value = 0; | 1524 | sym = NULL; |
1525 | else if (strong_try_module_get(owner)) | ||
1526 | value = 0; | ||
1527 | preempt_enable(); | 1525 | preempt_enable(); |
1528 | 1526 | ||
1529 | return (void *)value; | 1527 | return sym ? (void *)sym->value : NULL; |
1530 | } | 1528 | } |
1531 | EXPORT_SYMBOL_GPL(__symbol_get); | 1529 | EXPORT_SYMBOL_GPL(__symbol_get); |
1532 | 1530 | ||
@@ -1554,8 +1552,7 @@ static int verify_export_symbols(struct module *mod) | |||
1554 | 1552 | ||
1555 | for (i = 0; i < ARRAY_SIZE(arr); i++) { | 1553 | for (i = 0; i < ARRAY_SIZE(arr); i++) { |
1556 | for (s = arr[i].sym; s < arr[i].sym + arr[i].num; s++) { | 1554 | for (s = arr[i].sym; s < arr[i].sym + arr[i].num; s++) { |
1557 | if (!IS_ERR_VALUE(find_symbol(s->name, &owner, | 1555 | if (find_symbol(s->name, &owner, NULL, true, false)) { |
1558 | NULL, true, false))) { | ||
1559 | printk(KERN_ERR | 1556 | printk(KERN_ERR |
1560 | "%s: exports duplicate symbol %s" | 1557 | "%s: exports duplicate symbol %s" |
1561 | " (owned by %s)\n", | 1558 | " (owned by %s)\n", |
@@ -1579,6 +1576,7 @@ static int simplify_symbols(Elf_Shdr *sechdrs, | |||
1579 | unsigned long secbase; | 1576 | unsigned long secbase; |
1580 | unsigned int i, n = sechdrs[symindex].sh_size / sizeof(Elf_Sym); | 1577 | unsigned int i, n = sechdrs[symindex].sh_size / sizeof(Elf_Sym); |
1581 | int ret = 0; | 1578 | int ret = 0; |
1579 | const struct kernel_symbol *ksym; | ||
1582 | 1580 | ||
1583 | for (i = 1; i < n; i++) { | 1581 | for (i = 1; i < n; i++) { |
1584 | switch (sym[i].st_shndx) { | 1582 | switch (sym[i].st_shndx) { |
@@ -1598,13 +1596,14 @@ static int simplify_symbols(Elf_Shdr *sechdrs, | |||
1598 | break; | 1596 | break; |
1599 | 1597 | ||
1600 | case SHN_UNDEF: | 1598 | case SHN_UNDEF: |
1601 | sym[i].st_value | 1599 | ksym = resolve_symbol(sechdrs, versindex, |
1602 | = resolve_symbol(sechdrs, versindex, | 1600 | strtab + sym[i].st_name, mod); |
1603 | strtab + sym[i].st_name, mod); | ||
1604 | |||
1605 | /* Ok if resolved. */ | 1601 | /* Ok if resolved. */ |
1606 | if (!IS_ERR_VALUE(sym[i].st_value)) | 1602 | if (ksym) { |
1603 | sym[i].st_value = ksym->value; | ||
1607 | break; | 1604 | break; |
1605 | } | ||
1606 | |||
1608 | /* Ok if weak. */ | 1607 | /* Ok if weak. */ |
1609 | if (ELF_ST_BIND(sym[i].st_info) == STB_WEAK) | 1608 | if (ELF_ST_BIND(sym[i].st_info) == STB_WEAK) |
1610 | break; | 1609 | break; |