diff options
-rw-r--r-- | include/linux/module.h | 4 | ||||
-rw-r--r-- | include/linux/moduleparam.h | 10 | ||||
-rw-r--r-- | kernel/module.c | 14 | ||||
-rw-r--r-- | kernel/params.c | 26 |
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 | ||
143 | extern void destroy_params(const struct kernel_param *params, unsigned num); | ||
144 | #else | ||
145 | static 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 | ||
589 | void 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 | |||
574 | static void __init kernel_add_sysfs_param(const char *name, | 598 | static 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) |