aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/module.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/module.c')
-rw-r--r--kernel/module.c130
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
1055struct module_notes_attrs {
1056 struct kobject *dir;
1057 unsigned int notes;
1058 struct bin_attribute attrs[0];
1059};
1060
1061static 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
1072static 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 &notes_attrs->attrs[i]);
1079 kobject_del(notes_attrs->dir);
1080 }
1081 kfree(notes_attrs);
1082}
1083
1084static 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 = &notes_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 &notes_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
1139static 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
1058static inline void add_sect_attrs(struct module *mod, unsigned int nsect, 1147static 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,
1063static inline void remove_sect_attrs(struct module *mod) 1152static inline void remove_sect_attrs(struct module *mod)
1064{ 1153{
1065} 1154}
1155
1156static inline void add_notes_attrs(struct module *mod, unsigned int nsect,
1157 char *sectstrings, Elf_Shdr *sechdrs)
1158{
1159}
1160
1161static 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