aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/module.c75
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
289static bool find_symbol_in_section(const struct symsearch *syms, 289static 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 */
333static unsigned long find_symbol(const char *name, 333static 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. */
1101static unsigned long resolve_symbol(Elf_Shdr *sechdrs, 1101static 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)
1516void *__symbol_get(const char *symbol) 1516void *__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}
1531EXPORT_SYMBOL_GPL(__symbol_get); 1529EXPORT_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;