diff options
Diffstat (limited to 'kernel/module.c')
-rw-r--r-- | kernel/module.c | 130 |
1 files changed, 113 insertions, 17 deletions
diff --git a/kernel/module.c b/kernel/module.c index db0ead0363e2..a389b423c279 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/moduleloader.h> | 20 | #include <linux/moduleloader.h> |
21 | #include <linux/init.h> | 21 | #include <linux/init.h> |
22 | #include <linux/kallsyms.h> | 22 | #include <linux/kallsyms.h> |
23 | #include <linux/sysfs.h> | ||
23 | #include <linux/kernel.h> | 24 | #include <linux/kernel.h> |
24 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
25 | #include <linux/vmalloc.h> | 26 | #include <linux/vmalloc.h> |
@@ -692,8 +693,7 @@ sys_delete_module(const char __user *name_user, unsigned int flags) | |||
692 | } | 693 | } |
693 | 694 | ||
694 | /* If it has an init func, it must have an exit func to unload */ | 695 | /* If it has an init func, it must have an exit func to unload */ |
695 | if ((mod->init != NULL && mod->exit == NULL) | 696 | if (mod->init && !mod->exit) { |
696 | || mod->unsafe) { | ||
697 | forced = try_force_unload(flags); | 697 | forced = try_force_unload(flags); |
698 | if (!forced) { | 698 | if (!forced) { |
699 | /* This module can't be removed */ | 699 | /* This module can't be removed */ |
@@ -741,11 +741,6 @@ static void print_unload_info(struct seq_file *m, struct module *mod) | |||
741 | seq_printf(m, "%s,", use->module_which_uses->name); | 741 | seq_printf(m, "%s,", use->module_which_uses->name); |
742 | } | 742 | } |
743 | 743 | ||
744 | if (mod->unsafe) { | ||
745 | printed_something = 1; | ||
746 | seq_printf(m, "[unsafe],"); | ||
747 | } | ||
748 | |||
749 | if (mod->init != NULL && mod->exit == NULL) { | 744 | if (mod->init != NULL && mod->exit == NULL) { |
750 | printed_something = 1; | 745 | printed_something = 1; |
751 | seq_printf(m, "[permanent],"); | 746 | seq_printf(m, "[permanent],"); |
@@ -1053,6 +1048,100 @@ static void remove_sect_attrs(struct module *mod) | |||
1053 | } | 1048 | } |
1054 | } | 1049 | } |
1055 | 1050 | ||
1051 | /* | ||
1052 | * /sys/module/foo/notes/.section.name gives contents of SHT_NOTE sections. | ||
1053 | */ | ||
1054 | |||
1055 | struct module_notes_attrs { | ||
1056 | struct kobject *dir; | ||
1057 | unsigned int notes; | ||
1058 | struct bin_attribute attrs[0]; | ||
1059 | }; | ||
1060 | |||
1061 | static ssize_t module_notes_read(struct kobject *kobj, | ||
1062 | struct bin_attribute *bin_attr, | ||
1063 | char *buf, loff_t pos, size_t count) | ||
1064 | { | ||
1065 | /* | ||
1066 | * The caller checked the pos and count against our size. | ||
1067 | */ | ||
1068 | memcpy(buf, bin_attr->private + pos, count); | ||
1069 | return count; | ||
1070 | } | ||
1071 | |||
1072 | static void free_notes_attrs(struct module_notes_attrs *notes_attrs, | ||
1073 | unsigned int i) | ||
1074 | { | ||
1075 | if (notes_attrs->dir) { | ||
1076 | while (i-- > 0) | ||
1077 | sysfs_remove_bin_file(notes_attrs->dir, | ||
1078 | ¬es_attrs->attrs[i]); | ||
1079 | kobject_del(notes_attrs->dir); | ||
1080 | } | ||
1081 | kfree(notes_attrs); | ||
1082 | } | ||
1083 | |||
1084 | static void add_notes_attrs(struct module *mod, unsigned int nsect, | ||
1085 | char *secstrings, Elf_Shdr *sechdrs) | ||
1086 | { | ||
1087 | unsigned int notes, loaded, i; | ||
1088 | struct module_notes_attrs *notes_attrs; | ||
1089 | struct bin_attribute *nattr; | ||
1090 | |||
1091 | /* Count notes sections and allocate structures. */ | ||
1092 | notes = 0; | ||
1093 | for (i = 0; i < nsect; i++) | ||
1094 | if ((sechdrs[i].sh_flags & SHF_ALLOC) && | ||
1095 | (sechdrs[i].sh_type == SHT_NOTE)) | ||
1096 | ++notes; | ||
1097 | |||
1098 | if (notes == 0) | ||
1099 | return; | ||
1100 | |||
1101 | notes_attrs = kzalloc(sizeof(*notes_attrs) | ||
1102 | + notes * sizeof(notes_attrs->attrs[0]), | ||
1103 | GFP_KERNEL); | ||
1104 | if (notes_attrs == NULL) | ||
1105 | return; | ||
1106 | |||
1107 | notes_attrs->notes = notes; | ||
1108 | nattr = ¬es_attrs->attrs[0]; | ||
1109 | for (loaded = i = 0; i < nsect; ++i) { | ||
1110 | if (!(sechdrs[i].sh_flags & SHF_ALLOC)) | ||
1111 | continue; | ||
1112 | if (sechdrs[i].sh_type == SHT_NOTE) { | ||
1113 | nattr->attr.name = mod->sect_attrs->attrs[loaded].name; | ||
1114 | nattr->attr.mode = S_IRUGO; | ||
1115 | nattr->size = sechdrs[i].sh_size; | ||
1116 | nattr->private = (void *) sechdrs[i].sh_addr; | ||
1117 | nattr->read = module_notes_read; | ||
1118 | ++nattr; | ||
1119 | } | ||
1120 | ++loaded; | ||
1121 | } | ||
1122 | |||
1123 | notes_attrs->dir = kobject_add_dir(&mod->mkobj.kobj, "notes"); | ||
1124 | if (!notes_attrs->dir) | ||
1125 | goto out; | ||
1126 | |||
1127 | for (i = 0; i < notes; ++i) | ||
1128 | if (sysfs_create_bin_file(notes_attrs->dir, | ||
1129 | ¬es_attrs->attrs[i])) | ||
1130 | goto out; | ||
1131 | |||
1132 | mod->notes_attrs = notes_attrs; | ||
1133 | return; | ||
1134 | |||
1135 | out: | ||
1136 | free_notes_attrs(notes_attrs, i); | ||
1137 | } | ||
1138 | |||
1139 | static void remove_notes_attrs(struct module *mod) | ||
1140 | { | ||
1141 | if (mod->notes_attrs) | ||
1142 | free_notes_attrs(mod->notes_attrs, mod->notes_attrs->notes); | ||
1143 | } | ||
1144 | |||
1056 | #else | 1145 | #else |
1057 | 1146 | ||
1058 | static inline void add_sect_attrs(struct module *mod, unsigned int nsect, | 1147 | static inline void add_sect_attrs(struct module *mod, unsigned int nsect, |
@@ -1063,6 +1152,15 @@ static inline void add_sect_attrs(struct module *mod, unsigned int nsect, | |||
1063 | static inline void remove_sect_attrs(struct module *mod) | 1152 | static inline void remove_sect_attrs(struct module *mod) |
1064 | { | 1153 | { |
1065 | } | 1154 | } |
1155 | |||
1156 | static inline void add_notes_attrs(struct module *mod, unsigned int nsect, | ||
1157 | char *sectstrings, Elf_Shdr *sechdrs) | ||
1158 | { | ||
1159 | } | ||
1160 | |||
1161 | static inline void remove_notes_attrs(struct module *mod) | ||
1162 | { | ||
1163 | } | ||
1066 | #endif /* CONFIG_KALLSYMS */ | 1164 | #endif /* CONFIG_KALLSYMS */ |
1067 | 1165 | ||
1068 | #ifdef CONFIG_SYSFS | 1166 | #ifdef CONFIG_SYSFS |
@@ -1197,6 +1295,7 @@ static void free_module(struct module *mod) | |||
1197 | { | 1295 | { |
1198 | /* Delete from various lists */ | 1296 | /* Delete from various lists */ |
1199 | stop_machine_run(__unlink_module, mod, NR_CPUS); | 1297 | stop_machine_run(__unlink_module, mod, NR_CPUS); |
1298 | remove_notes_attrs(mod); | ||
1200 | remove_sect_attrs(mod); | 1299 | remove_sect_attrs(mod); |
1201 | mod_kobject_remove(mod); | 1300 | mod_kobject_remove(mod); |
1202 | 1301 | ||
@@ -1782,7 +1881,8 @@ static struct module *load_module(void __user *umod, | |||
1782 | module_unload_init(mod); | 1881 | module_unload_init(mod); |
1783 | 1882 | ||
1784 | /* Initialize kobject, so we can reference it. */ | 1883 | /* Initialize kobject, so we can reference it. */ |
1785 | if (mod_sysfs_init(mod) != 0) | 1884 | err = mod_sysfs_init(mod); |
1885 | if (err) | ||
1786 | goto cleanup; | 1886 | goto cleanup; |
1787 | 1887 | ||
1788 | /* Set up license info based on the info section */ | 1888 | /* Set up license info based on the info section */ |
@@ -1924,6 +2024,7 @@ static struct module *load_module(void __user *umod, | |||
1924 | if (err < 0) | 2024 | if (err < 0) |
1925 | goto arch_cleanup; | 2025 | goto arch_cleanup; |
1926 | add_sect_attrs(mod, hdr->e_shnum, secstrings, sechdrs); | 2026 | add_sect_attrs(mod, hdr->e_shnum, secstrings, sechdrs); |
2027 | add_notes_attrs(mod, hdr->e_shnum, secstrings, sechdrs); | ||
1927 | 2028 | ||
1928 | /* Size of section 0 is 0, so this works well if no unwind info. */ | 2029 | /* Size of section 0 is 0, so this works well if no unwind info. */ |
1929 | mod->unwind_info = unwind_add_table(mod, | 2030 | mod->unwind_info = unwind_add_table(mod, |
@@ -2011,15 +2112,10 @@ sys_init_module(void __user *umod, | |||
2011 | buggy refcounters. */ | 2112 | buggy refcounters. */ |
2012 | mod->state = MODULE_STATE_GOING; | 2113 | mod->state = MODULE_STATE_GOING; |
2013 | synchronize_sched(); | 2114 | synchronize_sched(); |
2014 | if (mod->unsafe) | 2115 | module_put(mod); |
2015 | printk(KERN_ERR "%s: module is now stuck!\n", | 2116 | mutex_lock(&module_mutex); |
2016 | mod->name); | 2117 | free_module(mod); |
2017 | else { | 2118 | mutex_unlock(&module_mutex); |
2018 | module_put(mod); | ||
2019 | mutex_lock(&module_mutex); | ||
2020 | free_module(mod); | ||
2021 | mutex_unlock(&module_mutex); | ||
2022 | } | ||
2023 | return ret; | 2119 | return ret; |
2024 | } | 2120 | } |
2025 | 2121 | ||