diff options
author | Rusty Russell <rusty@rustcorp.com.au> | 2009-10-29 08:56:16 -0600 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2009-11-09 16:22:17 -0800 |
commit | 9f00eee2ffab59cb85ecf1de54282c7fb4669565 (patch) | |
tree | e92ca436db4ee3f89004a5018086664bc09926d7 /kernel | |
parent | 05fe6c842ab23f6e823ad87a84adab73ab60beaa (diff) | |
download | lwn-9f00eee2ffab59cb85ecf1de54282c7fb4669565.tar.gz lwn-9f00eee2ffab59cb85ecf1de54282c7fb4669565.zip |
param: fix lots of bugs with writing charp params from sysfs, by leaking mem.
commit 65afac7d80ab3bc9f81e75eafb71eeb92a3ebdef upstream.
e180a6b7759a "param: fix charp parameters set via sysfs" fixed the case
where charp parameters written via sysfs were freed, leaving drivers
accessing random memory.
Unfortunately, storing a flag in the kparam struct was a bad idea: it's
rodata so setting it causes an oops on some archs. But that's not all:
1) module_param_array() on charp doesn't work reliably, since we use an
uninitialized temporary struct kernel_param.
2) there's a fundamental race if a module uses this parameter and then
it's changed: they will still access the old, freed, memory.
The simplest fix (ie. for 2.6.32) is to never free the memory. This
prevents all these problems, at cost of a memory leak. In practice, there
are only 18 places where a charp is writable via sysfs, and all are
root-only writable.
Reported-by: Takashi Iwai <tiwai@suse.de>
Cc: Sitsofe Wheeler <sitsofe@yahoo.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Christof Schmitt <christof.schmitt@de.ibm.com>
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/params.c | 10 |
1 files changed, 1 insertions, 9 deletions
diff --git a/kernel/params.c b/kernel/params.c index 7f6912ced2ba..276fd63bc780 100644 --- a/kernel/params.c +++ b/kernel/params.c @@ -217,13 +217,9 @@ int param_set_charp(const char *val, struct kernel_param *kp) return -ENOSPC; } - if (kp->flags & KPARAM_KMALLOCED) - kfree(*(char **)kp->arg); - /* This is a hack. We can't need to strdup in early boot, and we * don't need to; this mangled commandline is preserved. */ if (slab_is_available()) { - kp->flags |= KPARAM_KMALLOCED; *(char **)kp->arg = kstrdup(val, GFP_KERNEL); if (!kp->arg) return -ENOMEM; @@ -604,11 +600,7 @@ void module_param_sysfs_remove(struct module *mod) void destroy_params(const struct kernel_param *params, unsigned num) { - unsigned int i; - - for (i = 0; i < num; i++) - if (params[i].flags & KPARAM_KMALLOCED) - kfree(*(char **)params[i].arg); + /* FIXME: This should free kmalloced charp parameters. It doesn't. */ } static void __init kernel_add_sysfs_param(const char *name, |