diff options
Diffstat (limited to 'kernel/module.c')
-rw-r--r-- | kernel/module.c | 77 |
1 files changed, 34 insertions, 43 deletions
diff --git a/kernel/module.c b/kernel/module.c index fb11e2a88233..fd8d46c69766 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
@@ -1126,8 +1126,9 @@ static const struct kernel_symbol *resolve_symbol_wait(Elf_Shdr *sechdrs, | |||
1126 | * /sys/module/foo/sections stuff | 1126 | * /sys/module/foo/sections stuff |
1127 | * J. Corbet <corbet@lwn.net> | 1127 | * J. Corbet <corbet@lwn.net> |
1128 | */ | 1128 | */ |
1129 | #if defined(CONFIG_KALLSYMS) && defined(CONFIG_SYSFS) | 1129 | #ifdef CONFIG_SYSFS |
1130 | 1130 | ||
1131 | #ifdef CONFIG_KALLSYMS | ||
1131 | static inline bool sect_empty(const Elf_Shdr *sect) | 1132 | static inline bool sect_empty(const Elf_Shdr *sect) |
1132 | { | 1133 | { |
1133 | return !(sect->sh_flags & SHF_ALLOC) || sect->sh_size == 0; | 1134 | return !(sect->sh_flags & SHF_ALLOC) || sect->sh_size == 0; |
@@ -1164,8 +1165,7 @@ static void free_sect_attrs(struct module_sect_attrs *sect_attrs) | |||
1164 | kfree(sect_attrs); | 1165 | kfree(sect_attrs); |
1165 | } | 1166 | } |
1166 | 1167 | ||
1167 | static void add_sect_attrs(struct module *mod, unsigned int nsect, | 1168 | static void add_sect_attrs(struct module *mod, const struct load_info *info) |
1168 | char *secstrings, Elf_Shdr *sechdrs) | ||
1169 | { | 1169 | { |
1170 | unsigned int nloaded = 0, i, size[2]; | 1170 | unsigned int nloaded = 0, i, size[2]; |
1171 | struct module_sect_attrs *sect_attrs; | 1171 | struct module_sect_attrs *sect_attrs; |
@@ -1173,8 +1173,8 @@ static void add_sect_attrs(struct module *mod, unsigned int nsect, | |||
1173 | struct attribute **gattr; | 1173 | struct attribute **gattr; |
1174 | 1174 | ||
1175 | /* Count loaded sections and allocate structures */ | 1175 | /* Count loaded sections and allocate structures */ |
1176 | for (i = 0; i < nsect; i++) | 1176 | for (i = 0; i < info->hdr->e_shnum; i++) |
1177 | if (!sect_empty(&sechdrs[i])) | 1177 | if (!sect_empty(&info->sechdrs[i])) |
1178 | nloaded++; | 1178 | nloaded++; |
1179 | size[0] = ALIGN(sizeof(*sect_attrs) | 1179 | size[0] = ALIGN(sizeof(*sect_attrs) |
1180 | + nloaded * sizeof(sect_attrs->attrs[0]), | 1180 | + nloaded * sizeof(sect_attrs->attrs[0]), |
@@ -1191,11 +1191,12 @@ static void add_sect_attrs(struct module *mod, unsigned int nsect, | |||
1191 | sect_attrs->nsections = 0; | 1191 | sect_attrs->nsections = 0; |
1192 | sattr = §_attrs->attrs[0]; | 1192 | sattr = §_attrs->attrs[0]; |
1193 | gattr = §_attrs->grp.attrs[0]; | 1193 | gattr = §_attrs->grp.attrs[0]; |
1194 | for (i = 0; i < nsect; i++) { | 1194 | for (i = 0; i < info->hdr->e_shnum; i++) { |
1195 | if (sect_empty(&sechdrs[i])) | 1195 | Elf_Shdr *sec = &info->sechdrs[i]; |
1196 | if (sect_empty(sec)) | ||
1196 | continue; | 1197 | continue; |
1197 | sattr->address = sechdrs[i].sh_addr; | 1198 | sattr->address = sec->sh_addr; |
1198 | sattr->name = kstrdup(secstrings + sechdrs[i].sh_name, | 1199 | sattr->name = kstrdup(info->secstrings + sec->sh_name, |
1199 | GFP_KERNEL); | 1200 | GFP_KERNEL); |
1200 | if (sattr->name == NULL) | 1201 | if (sattr->name == NULL) |
1201 | goto out; | 1202 | goto out; |
@@ -1263,8 +1264,7 @@ static void free_notes_attrs(struct module_notes_attrs *notes_attrs, | |||
1263 | kfree(notes_attrs); | 1264 | kfree(notes_attrs); |
1264 | } | 1265 | } |
1265 | 1266 | ||
1266 | static void add_notes_attrs(struct module *mod, unsigned int nsect, | 1267 | static void add_notes_attrs(struct module *mod, const struct load_info *info) |
1267 | char *secstrings, Elf_Shdr *sechdrs) | ||
1268 | { | 1268 | { |
1269 | unsigned int notes, loaded, i; | 1269 | unsigned int notes, loaded, i; |
1270 | struct module_notes_attrs *notes_attrs; | 1270 | struct module_notes_attrs *notes_attrs; |
@@ -1276,9 +1276,9 @@ static void add_notes_attrs(struct module *mod, unsigned int nsect, | |||
1276 | 1276 | ||
1277 | /* Count notes sections and allocate structures. */ | 1277 | /* Count notes sections and allocate structures. */ |
1278 | notes = 0; | 1278 | notes = 0; |
1279 | for (i = 0; i < nsect; i++) | 1279 | for (i = 0; i < info->hdr->e_shnum; i++) |
1280 | if (!sect_empty(&sechdrs[i]) && | 1280 | if (!sect_empty(&info->sechdrs[i]) && |
1281 | (sechdrs[i].sh_type == SHT_NOTE)) | 1281 | (info->sechdrs[i].sh_type == SHT_NOTE)) |
1282 | ++notes; | 1282 | ++notes; |
1283 | 1283 | ||
1284 | if (notes == 0) | 1284 | if (notes == 0) |
@@ -1292,15 +1292,15 @@ static void add_notes_attrs(struct module *mod, unsigned int nsect, | |||
1292 | 1292 | ||
1293 | notes_attrs->notes = notes; | 1293 | notes_attrs->notes = notes; |
1294 | nattr = ¬es_attrs->attrs[0]; | 1294 | nattr = ¬es_attrs->attrs[0]; |
1295 | for (loaded = i = 0; i < nsect; ++i) { | 1295 | for (loaded = i = 0; i < info->hdr->e_shnum; ++i) { |
1296 | if (sect_empty(&sechdrs[i])) | 1296 | if (sect_empty(&info->sechdrs[i])) |
1297 | continue; | 1297 | continue; |
1298 | if (sechdrs[i].sh_type == SHT_NOTE) { | 1298 | if (info->sechdrs[i].sh_type == SHT_NOTE) { |
1299 | sysfs_bin_attr_init(nattr); | 1299 | sysfs_bin_attr_init(nattr); |
1300 | nattr->attr.name = mod->sect_attrs->attrs[loaded].name; | 1300 | nattr->attr.name = mod->sect_attrs->attrs[loaded].name; |
1301 | nattr->attr.mode = S_IRUGO; | 1301 | nattr->attr.mode = S_IRUGO; |
1302 | nattr->size = sechdrs[i].sh_size; | 1302 | nattr->size = info->sechdrs[i].sh_size; |
1303 | nattr->private = (void *) sechdrs[i].sh_addr; | 1303 | nattr->private = (void *) info->sechdrs[i].sh_addr; |
1304 | nattr->read = module_notes_read; | 1304 | nattr->read = module_notes_read; |
1305 | ++nattr; | 1305 | ++nattr; |
1306 | } | 1306 | } |
@@ -1331,8 +1331,8 @@ static void remove_notes_attrs(struct module *mod) | |||
1331 | 1331 | ||
1332 | #else | 1332 | #else |
1333 | 1333 | ||
1334 | static inline void add_sect_attrs(struct module *mod, unsigned int nsect, | 1334 | static inline void add_sect_attrs(struct module *mod, |
1335 | char *sectstrings, Elf_Shdr *sechdrs) | 1335 | const struct load_info *info) |
1336 | { | 1336 | { |
1337 | } | 1337 | } |
1338 | 1338 | ||
@@ -1340,17 +1340,16 @@ static inline void remove_sect_attrs(struct module *mod) | |||
1340 | { | 1340 | { |
1341 | } | 1341 | } |
1342 | 1342 | ||
1343 | static inline void add_notes_attrs(struct module *mod, unsigned int nsect, | 1343 | static inline void add_notes_attrs(struct module *mod, |
1344 | char *sectstrings, Elf_Shdr *sechdrs) | 1344 | const struct load_info *info) |
1345 | { | 1345 | { |
1346 | } | 1346 | } |
1347 | 1347 | ||
1348 | static inline void remove_notes_attrs(struct module *mod) | 1348 | static inline void remove_notes_attrs(struct module *mod) |
1349 | { | 1349 | { |
1350 | } | 1350 | } |
1351 | #endif | 1351 | #endif /* CONFIG_KALLSYMS */ |
1352 | 1352 | ||
1353 | #ifdef CONFIG_SYSFS | ||
1354 | static void add_usage_links(struct module *mod) | 1353 | static void add_usage_links(struct module *mod) |
1355 | { | 1354 | { |
1356 | #ifdef CONFIG_MODULE_UNLOAD | 1355 | #ifdef CONFIG_MODULE_UNLOAD |
@@ -1455,6 +1454,7 @@ out: | |||
1455 | } | 1454 | } |
1456 | 1455 | ||
1457 | static int mod_sysfs_setup(struct module *mod, | 1456 | static int mod_sysfs_setup(struct module *mod, |
1457 | const struct load_info *info, | ||
1458 | struct kernel_param *kparam, | 1458 | struct kernel_param *kparam, |
1459 | unsigned int num_params) | 1459 | unsigned int num_params) |
1460 | { | 1460 | { |
@@ -1479,6 +1479,8 @@ static int mod_sysfs_setup(struct module *mod, | |||
1479 | goto out_unreg_param; | 1479 | goto out_unreg_param; |
1480 | 1480 | ||
1481 | add_usage_links(mod); | 1481 | add_usage_links(mod); |
1482 | add_sect_attrs(mod, info); | ||
1483 | add_notes_attrs(mod, info); | ||
1482 | 1484 | ||
1483 | kobject_uevent(&mod->mkobj.kobj, KOBJ_ADD); | 1485 | kobject_uevent(&mod->mkobj.kobj, KOBJ_ADD); |
1484 | return 0; | 1486 | return 0; |
@@ -1495,32 +1497,26 @@ out: | |||
1495 | 1497 | ||
1496 | static void mod_sysfs_fini(struct module *mod) | 1498 | static void mod_sysfs_fini(struct module *mod) |
1497 | { | 1499 | { |
1500 | remove_notes_attrs(mod); | ||
1501 | remove_sect_attrs(mod); | ||
1498 | kobject_put(&mod->mkobj.kobj); | 1502 | kobject_put(&mod->mkobj.kobj); |
1499 | } | 1503 | } |
1500 | 1504 | ||
1501 | #else /* CONFIG_SYSFS */ | 1505 | #else /* !CONFIG_SYSFS */ |
1502 | 1506 | ||
1503 | static inline int mod_sysfs_init(struct module *mod) | 1507 | static int mod_sysfs_init(struct module *mod) |
1504 | { | 1508 | { |
1505 | return 0; | 1509 | return 0; |
1506 | } | 1510 | } |
1507 | 1511 | ||
1508 | static inline int mod_sysfs_setup(struct module *mod, | 1512 | static int mod_sysfs_setup(struct module *mod, |
1513 | const struct load_info *info, | ||
1509 | struct kernel_param *kparam, | 1514 | struct kernel_param *kparam, |
1510 | unsigned int num_params) | 1515 | unsigned int num_params) |
1511 | { | 1516 | { |
1512 | return 0; | 1517 | return 0; |
1513 | } | 1518 | } |
1514 | 1519 | ||
1515 | static inline int module_add_modinfo_attrs(struct module *mod) | ||
1516 | { | ||
1517 | return 0; | ||
1518 | } | ||
1519 | |||
1520 | static inline void module_remove_modinfo_attrs(struct module *mod) | ||
1521 | { | ||
1522 | } | ||
1523 | |||
1524 | static void mod_sysfs_fini(struct module *mod) | 1520 | static void mod_sysfs_fini(struct module *mod) |
1525 | { | 1521 | { |
1526 | } | 1522 | } |
@@ -1561,8 +1557,6 @@ static void free_module(struct module *mod) | |||
1561 | mutex_lock(&module_mutex); | 1557 | mutex_lock(&module_mutex); |
1562 | stop_machine(__unlink_module, mod, NULL); | 1558 | stop_machine(__unlink_module, mod, NULL); |
1563 | mutex_unlock(&module_mutex); | 1559 | mutex_unlock(&module_mutex); |
1564 | remove_notes_attrs(mod); | ||
1565 | remove_sect_attrs(mod); | ||
1566 | mod_kobject_remove(mod); | 1560 | mod_kobject_remove(mod); |
1567 | 1561 | ||
1568 | /* Remove dynamic debug info */ | 1562 | /* Remove dynamic debug info */ |
@@ -2691,13 +2685,10 @@ static noinline struct module *load_module(void __user *umod, | |||
2691 | if (err < 0) | 2685 | if (err < 0) |
2692 | goto unlink; | 2686 | goto unlink; |
2693 | 2687 | ||
2694 | err = mod_sysfs_setup(mod, mod->kp, mod->num_kp); | 2688 | err = mod_sysfs_setup(mod, &info, mod->kp, mod->num_kp); |
2695 | if (err < 0) | 2689 | if (err < 0) |
2696 | goto unlink; | 2690 | goto unlink; |
2697 | 2691 | ||
2698 | add_sect_attrs(mod, info.hdr->e_shnum, info.secstrings, info.sechdrs); | ||
2699 | add_notes_attrs(mod, info.hdr->e_shnum, info.secstrings, info.sechdrs); | ||
2700 | |||
2701 | /* Get rid of temporary copy and strmap. */ | 2692 | /* Get rid of temporary copy and strmap. */ |
2702 | kfree(info.strmap); | 2693 | kfree(info.strmap); |
2703 | free_copy(&info); | 2694 | free_copy(&info); |