diff options
-rw-r--r-- | include/linux/kmod.h | 2 | ||||
-rw-r--r-- | kernel/kmod.c | 120 | ||||
-rw-r--r-- | kernel/module.c | 26 | ||||
-rw-r--r-- | kernel/params.c | 1 |
4 files changed, 10 insertions, 139 deletions
diff --git a/include/linux/kmod.h b/include/linux/kmod.h index cc8e674ae27a..10f505c8431d 100644 --- a/include/linux/kmod.h +++ b/include/linux/kmod.h | |||
@@ -28,10 +28,8 @@ | |||
28 | #ifdef CONFIG_KMOD | 28 | #ifdef CONFIG_KMOD |
29 | /* modprobe exit status on success, -ve on error. Return value | 29 | /* modprobe exit status on success, -ve on error. Return value |
30 | * usually useless though. */ | 30 | * usually useless though. */ |
31 | extern void kmod_sysfs_init(void); | ||
32 | extern int request_module(const char * name, ...) __attribute__ ((format (printf, 1, 2))); | 31 | extern int request_module(const char * name, ...) __attribute__ ((format (printf, 1, 2))); |
33 | #else | 32 | #else |
34 | static inline void kmod_sysfs_init(void) {}; | ||
35 | static inline int request_module(const char * name, ...) { return -ENOSYS; } | 33 | static inline int request_module(const char * name, ...) { return -ENOSYS; } |
36 | #endif | 34 | #endif |
37 | 35 | ||
diff --git a/kernel/kmod.c b/kernel/kmod.c index f936108f2963..796276141e51 100644 --- a/kernel/kmod.c +++ b/kernel/kmod.c | |||
@@ -36,8 +36,6 @@ | |||
36 | #include <linux/resource.h> | 36 | #include <linux/resource.h> |
37 | #include <asm/uaccess.h> | 37 | #include <asm/uaccess.h> |
38 | 38 | ||
39 | extern int delete_module(const char *name, unsigned int flags); | ||
40 | |||
41 | extern int max_threads; | 39 | extern int max_threads; |
42 | 40 | ||
43 | static struct workqueue_struct *khelper_wq; | 41 | static struct workqueue_struct *khelper_wq; |
@@ -48,7 +46,6 @@ static struct workqueue_struct *khelper_wq; | |||
48 | modprobe_path is set via /proc/sys. | 46 | modprobe_path is set via /proc/sys. |
49 | */ | 47 | */ |
50 | char modprobe_path[KMOD_PATH_LEN] = "/sbin/modprobe"; | 48 | char modprobe_path[KMOD_PATH_LEN] = "/sbin/modprobe"; |
51 | static struct module_kobject kmod_mk; | ||
52 | 49 | ||
53 | /** | 50 | /** |
54 | * request_module - try to load a kernel module | 51 | * request_module - try to load a kernel module |
@@ -78,11 +75,6 @@ int request_module(const char *fmt, ...) | |||
78 | static atomic_t kmod_concurrent = ATOMIC_INIT(0); | 75 | static atomic_t kmod_concurrent = ATOMIC_INIT(0); |
79 | #define MAX_KMOD_CONCURRENT 50 /* Completely arbitrary value - KAO */ | 76 | #define MAX_KMOD_CONCURRENT 50 /* Completely arbitrary value - KAO */ |
80 | static int kmod_loop_msg; | 77 | static int kmod_loop_msg; |
81 | char modalias[16 + MODULE_NAME_LEN] = "MODALIAS="; | ||
82 | char *uevent_envp[2] = { | ||
83 | modalias, | ||
84 | NULL | ||
85 | }; | ||
86 | 78 | ||
87 | va_start(args, fmt); | 79 | va_start(args, fmt); |
88 | ret = vsnprintf(module_name, MODULE_NAME_LEN, fmt, args); | 80 | ret = vsnprintf(module_name, MODULE_NAME_LEN, fmt, args); |
@@ -90,12 +82,6 @@ int request_module(const char *fmt, ...) | |||
90 | if (ret >= MODULE_NAME_LEN) | 82 | if (ret >= MODULE_NAME_LEN) |
91 | return -ENAMETOOLONG; | 83 | return -ENAMETOOLONG; |
92 | 84 | ||
93 | strcpy(&modalias[strlen("MODALIAS=")], module_name); | ||
94 | kobject_uevent_env(&kmod_mk.kobj, KOBJ_CHANGE, uevent_envp); | ||
95 | |||
96 | if (modprobe_path[0] == '\0') | ||
97 | goto out; | ||
98 | |||
99 | /* If modprobe needs a service that is in a module, we get a recursive | 85 | /* If modprobe needs a service that is in a module, we get a recursive |
100 | * loop. Limit the number of running kmod threads to max_threads/2 or | 86 | * loop. Limit the number of running kmod threads to max_threads/2 or |
101 | * MAX_KMOD_CONCURRENT, whichever is the smaller. A cleaner method | 87 | * MAX_KMOD_CONCURRENT, whichever is the smaller. A cleaner method |
@@ -122,115 +108,9 @@ int request_module(const char *fmt, ...) | |||
122 | 108 | ||
123 | ret = call_usermodehelper(modprobe_path, argv, envp, 1); | 109 | ret = call_usermodehelper(modprobe_path, argv, envp, 1); |
124 | atomic_dec(&kmod_concurrent); | 110 | atomic_dec(&kmod_concurrent); |
125 | out: | ||
126 | return ret; | 111 | return ret; |
127 | } | 112 | } |
128 | EXPORT_SYMBOL(request_module); | 113 | EXPORT_SYMBOL(request_module); |
129 | |||
130 | static ssize_t store_mod_request(struct module_attribute *mattr, | ||
131 | struct module *mod, | ||
132 | const char *buffer, size_t count) | ||
133 | { | ||
134 | char name[MODULE_NAME_LEN]; | ||
135 | int ret; | ||
136 | |||
137 | if (count < 1 || count+1 > MODULE_NAME_LEN) | ||
138 | return -EINVAL; | ||
139 | memcpy(name, buffer, count); | ||
140 | name[count] = '\0'; | ||
141 | if (name[count-1] == '\n') | ||
142 | name[count-1] = '\0'; | ||
143 | |||
144 | ret = request_module(name); | ||
145 | if (ret < 0) | ||
146 | return ret; | ||
147 | return count; | ||
148 | } | ||
149 | |||
150 | static struct module_attribute mod_request = { | ||
151 | .attr = { .name = "mod_request", .mode = S_IWUSR, .owner = THIS_MODULE }, | ||
152 | .store = store_mod_request, | ||
153 | }; | ||
154 | |||
155 | #ifdef CONFIG_MODULE_UNLOAD | ||
156 | static ssize_t store_mod_unload(struct module_attribute *mattr, | ||
157 | struct module *mod, | ||
158 | const char *buffer, size_t count) | ||
159 | { | ||
160 | char name[MODULE_NAME_LEN]; | ||
161 | int ret; | ||
162 | |||
163 | if (count < 1 || count+1 > MODULE_NAME_LEN) | ||
164 | return -EINVAL; | ||
165 | memcpy(name, buffer, count); | ||
166 | name[count] = '\0'; | ||
167 | if (name[count-1] == '\n') | ||
168 | name[count-1] = '\0'; | ||
169 | |||
170 | ret = delete_module(name, O_NONBLOCK); | ||
171 | if (ret < 0) | ||
172 | return ret; | ||
173 | return count; | ||
174 | } | ||
175 | |||
176 | static struct module_attribute mod_unload = { | ||
177 | .attr = { .name = "mod_unload", .mode = S_IWUSR, .owner = THIS_MODULE }, | ||
178 | .store = store_mod_unload, | ||
179 | }; | ||
180 | #endif | ||
181 | |||
182 | static ssize_t show_mod_request_helper(struct module_attribute *mattr, | ||
183 | struct module *mod, | ||
184 | char *buffer) | ||
185 | { | ||
186 | return sprintf(buffer, "%s\n", modprobe_path); | ||
187 | } | ||
188 | |||
189 | static ssize_t store_mod_request_helper(struct module_attribute *mattr, | ||
190 | struct module *mod, | ||
191 | const char *buffer, size_t count) | ||
192 | { | ||
193 | if (count < 1 || count+1 > KMOD_PATH_LEN) | ||
194 | return -EINVAL; | ||
195 | memcpy(modprobe_path, buffer, count); | ||
196 | modprobe_path[count] = '\0'; | ||
197 | if (modprobe_path[count-1] == '\n') | ||
198 | modprobe_path[count-1] = '\0'; | ||
199 | return count; | ||
200 | } | ||
201 | |||
202 | static struct module_attribute mod_request_helper = { | ||
203 | .attr = { | ||
204 | .name = "mod_request_helper", | ||
205 | .mode = S_IWUSR | S_IRUGO, | ||
206 | .owner = THIS_MODULE | ||
207 | }, | ||
208 | .show = show_mod_request_helper, | ||
209 | .store = store_mod_request_helper, | ||
210 | }; | ||
211 | |||
212 | void __init kmod_sysfs_init(void) | ||
213 | { | ||
214 | int ret; | ||
215 | |||
216 | kmod_mk.mod = THIS_MODULE; | ||
217 | kobj_set_kset_s(&kmod_mk, module_subsys); | ||
218 | kobject_set_name(&kmod_mk.kobj, "kmod"); | ||
219 | kobject_init(&kmod_mk.kobj); | ||
220 | ret = kobject_add(&kmod_mk.kobj); | ||
221 | if (ret < 0) | ||
222 | goto out; | ||
223 | |||
224 | ret = sysfs_create_file(&kmod_mk.kobj, &mod_request_helper.attr); | ||
225 | ret = sysfs_create_file(&kmod_mk.kobj, &mod_request.attr); | ||
226 | #ifdef CONFIG_MODULE_UNLOAD | ||
227 | ret = sysfs_create_file(&kmod_mk.kobj, &mod_unload.attr); | ||
228 | #endif | ||
229 | |||
230 | kobject_uevent(&kmod_mk.kobj, KOBJ_ADD); | ||
231 | out: | ||
232 | return; | ||
233 | } | ||
234 | #endif /* CONFIG_KMOD */ | 114 | #endif /* CONFIG_KMOD */ |
235 | 115 | ||
236 | struct subprocess_info { | 116 | struct subprocess_info { |
diff --git a/kernel/module.c b/kernel/module.c index 1ecf08106381..f77e893e4620 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
@@ -653,11 +653,20 @@ static void wait_for_zero_refcount(struct module *mod) | |||
653 | mutex_lock(&module_mutex); | 653 | mutex_lock(&module_mutex); |
654 | } | 654 | } |
655 | 655 | ||
656 | int delete_module(const char *name, unsigned int flags) | 656 | asmlinkage long |
657 | sys_delete_module(const char __user *name_user, unsigned int flags) | ||
657 | { | 658 | { |
658 | struct module *mod; | 659 | struct module *mod; |
660 | char name[MODULE_NAME_LEN]; | ||
659 | int ret, forced = 0; | 661 | int ret, forced = 0; |
660 | 662 | ||
663 | if (!capable(CAP_SYS_MODULE)) | ||
664 | return -EPERM; | ||
665 | |||
666 | if (strncpy_from_user(name, name_user, MODULE_NAME_LEN-1) < 0) | ||
667 | return -EFAULT; | ||
668 | name[MODULE_NAME_LEN-1] = '\0'; | ||
669 | |||
661 | if (mutex_lock_interruptible(&module_mutex) != 0) | 670 | if (mutex_lock_interruptible(&module_mutex) != 0) |
662 | return -EINTR; | 671 | return -EINTR; |
663 | 672 | ||
@@ -718,21 +727,6 @@ int delete_module(const char *name, unsigned int flags) | |||
718 | return ret; | 727 | return ret; |
719 | } | 728 | } |
720 | 729 | ||
721 | asmlinkage long | ||
722 | sys_delete_module(const char __user *name_user, unsigned int flags) | ||
723 | { | ||
724 | char name[MODULE_NAME_LEN]; | ||
725 | |||
726 | if (!capable(CAP_SYS_MODULE)) | ||
727 | return -EPERM; | ||
728 | |||
729 | if (strncpy_from_user(name, name_user, MODULE_NAME_LEN-1) < 0) | ||
730 | return -EFAULT; | ||
731 | name[MODULE_NAME_LEN-1] = '\0'; | ||
732 | |||
733 | return delete_module(name, flags); | ||
734 | } | ||
735 | |||
736 | static void print_unload_info(struct seq_file *m, struct module *mod) | 730 | static void print_unload_info(struct seq_file *m, struct module *mod) |
737 | { | 731 | { |
738 | struct module_use *use; | 732 | struct module_use *use; |
diff --git a/kernel/params.c b/kernel/params.c index 7a751570b56d..e265b13195b1 100644 --- a/kernel/params.c +++ b/kernel/params.c | |||
@@ -707,7 +707,6 @@ static int __init param_sysfs_init(void) | |||
707 | } | 707 | } |
708 | 708 | ||
709 | param_sysfs_builtin(); | 709 | param_sysfs_builtin(); |
710 | kmod_sysfs_init(); | ||
711 | 710 | ||
712 | return 0; | 711 | return 0; |
713 | } | 712 | } |