aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/module.h4
-rw-r--r--include/linux/moduleparam.h10
-rw-r--r--kernel/module.c14
-rw-r--r--kernel/params.c26
4 files changed, 47 insertions, 7 deletions
diff --git a/include/linux/module.h b/include/linux/module.h
index 145a75528cc1..08e5e75d6122 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -248,6 +248,10 @@ struct module
248 const unsigned long *crcs; 248 const unsigned long *crcs;
249 unsigned int num_syms; 249 unsigned int num_syms;
250 250
251 /* Kernel parameters. */
252 struct kernel_param *kp;
253 unsigned int num_kp;
254
251 /* GPL-only exported symbols. */ 255 /* GPL-only exported symbols. */
252 unsigned int num_gpl_syms; 256 unsigned int num_gpl_syms;
253 const struct kernel_symbol *gpl_syms; 257 const struct kernel_symbol *gpl_syms;
diff --git a/include/linux/moduleparam.h b/include/linux/moduleparam.h
index e4af3399ef48..a4f0b931846c 100644
--- a/include/linux/moduleparam.h
+++ b/include/linux/moduleparam.h
@@ -138,6 +138,16 @@ extern int parse_args(const char *name,
138 unsigned num, 138 unsigned num,
139 int (*unknown)(char *param, char *val)); 139 int (*unknown)(char *param, char *val));
140 140
141/* Called by module remove. */
142#ifdef CONFIG_SYSFS
143extern void destroy_params(const struct kernel_param *params, unsigned num);
144#else
145static inline void destroy_params(const struct kernel_param *params,
146 unsigned num)
147{
148}
149#endif /* !CONFIG_SYSFS */
150
141/* All the helper functions */ 151/* All the helper functions */
142/* The macros to do compile-time type checking stolen from Jakub 152/* The macros to do compile-time type checking stolen from Jakub
143 Jelinek, who IIRC came up with this idea for the 2.4 module init code. */ 153 Jelinek, who IIRC came up with this idea for the 2.4 module init code. */
diff --git a/kernel/module.c b/kernel/module.c
index f77ac320d0b5..b862fdb6a372 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -1491,6 +1491,9 @@ static void free_module(struct module *mod)
1491 /* Module unload stuff */ 1491 /* Module unload stuff */
1492 module_unload_free(mod); 1492 module_unload_free(mod);
1493 1493
1494 /* Free any allocated parameters. */
1495 destroy_params(mod->kp, mod->num_kp);
1496
1494 /* release any pointers to mcount in this module */ 1497 /* release any pointers to mcount in this module */
1495 ftrace_release(mod->module_core, mod->core_size); 1498 ftrace_release(mod->module_core, mod->core_size);
1496 1499
@@ -1898,8 +1901,7 @@ static noinline struct module *load_module(void __user *umod,
1898 unsigned int symindex = 0; 1901 unsigned int symindex = 0;
1899 unsigned int strindex = 0; 1902 unsigned int strindex = 0;
1900 unsigned int modindex, versindex, infoindex, pcpuindex; 1903 unsigned int modindex, versindex, infoindex, pcpuindex;
1901 unsigned int num_kp, num_mcount; 1904 unsigned int num_mcount;
1902 struct kernel_param *kp;
1903 struct module *mod; 1905 struct module *mod;
1904 long err = 0; 1906 long err = 0;
1905 void *percpu = NULL, *ptr = NULL; /* Stops spurious gcc warning */ 1907 void *percpu = NULL, *ptr = NULL; /* Stops spurious gcc warning */
@@ -2144,8 +2146,8 @@ static noinline struct module *load_module(void __user *umod,
2144 2146
2145 /* Now we've got everything in the final locations, we can 2147 /* Now we've got everything in the final locations, we can
2146 * find optional sections. */ 2148 * find optional sections. */
2147 kp = section_objs(hdr, sechdrs, secstrings, "__param", sizeof(*kp), 2149 mod->kp = section_objs(hdr, sechdrs, secstrings, "__param",
2148 &num_kp); 2150 sizeof(*mod->kp), &mod->num_kp);
2149 mod->syms = section_objs(hdr, sechdrs, secstrings, "__ksymtab", 2151 mod->syms = section_objs(hdr, sechdrs, secstrings, "__ksymtab",
2150 sizeof(*mod->syms), &mod->num_syms); 2152 sizeof(*mod->syms), &mod->num_syms);
2151 mod->crcs = section_addr(hdr, sechdrs, secstrings, "__kcrctab"); 2153 mod->crcs = section_addr(hdr, sechdrs, secstrings, "__kcrctab");
@@ -2291,11 +2293,11 @@ static noinline struct module *load_module(void __user *umod,
2291 */ 2293 */
2292 list_add_rcu(&mod->list, &modules); 2294 list_add_rcu(&mod->list, &modules);
2293 2295
2294 err = parse_args(mod->name, mod->args, kp, num_kp, NULL); 2296 err = parse_args(mod->name, mod->args, mod->kp, mod->num_kp, NULL);
2295 if (err < 0) 2297 if (err < 0)
2296 goto unlink; 2298 goto unlink;
2297 2299
2298 err = mod_sysfs_setup(mod, kp, num_kp); 2300 err = mod_sysfs_setup(mod, mod->kp, mod->num_kp);
2299 if (err < 0) 2301 if (err < 0)
2300 goto unlink; 2302 goto unlink;
2301 add_sect_attrs(mod, hdr->e_shnum, secstrings, sechdrs); 2303 add_sect_attrs(mod, hdr->e_shnum, secstrings, sechdrs);
diff --git a/kernel/params.c b/kernel/params.c
index a1e3025b19a9..de273ec85bd2 100644
--- a/kernel/params.c
+++ b/kernel/params.c
@@ -24,6 +24,9 @@
24#include <linux/err.h> 24#include <linux/err.h>
25#include <linux/slab.h> 25#include <linux/slab.h>
26 26
27/* We abuse the high bits of "perm" to record whether we kmalloc'ed. */
28#define KPARAM_KMALLOCED 0x80000000
29
27#if 0 30#if 0
28#define DEBUGP printk 31#define DEBUGP printk
29#else 32#else
@@ -217,7 +220,19 @@ int param_set_charp(const char *val, struct kernel_param *kp)
217 return -ENOSPC; 220 return -ENOSPC;
218 } 221 }
219 222
220 *(char **)kp->arg = (char *)val; 223 if (kp->perm & KPARAM_KMALLOCED)
224 kfree(*(char **)kp->arg);
225
226 /* This is a hack. We can't need to strdup in early boot, and we
227 * don't need to; this mangled commandline is preserved. */
228 if (slab_is_available()) {
229 kp->perm |= KPARAM_KMALLOCED;
230 *(char **)kp->arg = kstrdup(val, GFP_KERNEL);
231 if (!kp->arg)
232 return -ENOMEM;
233 } else
234 *(const char **)kp->arg = val;
235
221 return 0; 236 return 0;
222} 237}
223 238
@@ -571,6 +586,15 @@ void module_param_sysfs_remove(struct module *mod)
571} 586}
572#endif 587#endif
573 588
589void destroy_params(const struct kernel_param *params, unsigned num)
590{
591 unsigned int i;
592
593 for (i = 0; i < num; i++)
594 if (params[i].perm & KPARAM_KMALLOCED)
595 kfree(*(char **)params[i].arg);
596}
597
574static void __init kernel_add_sysfs_param(const char *name, 598static void __init kernel_add_sysfs_param(const char *name,
575 struct kernel_param *kparam, 599 struct kernel_param *kparam,
576 unsigned int name_skip) 600 unsigned int name_skip)