diff options
| -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); |
