mirror of
https://github.com/adulau/aha.git
synced 2024-12-28 03:36:19 +00:00
param: fix lots of bugs with writing charp params from sysfs, by leaking mem.
e180a6b775
"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>
Cc: stable@kernel.org
This commit is contained in:
parent
964fe080d9
commit
65afac7d80
2 changed files with 1 additions and 10 deletions
|
@ -37,7 +37,6 @@ typedef int (*param_set_fn)(const char *val, struct kernel_param *kp);
|
||||||
typedef int (*param_get_fn)(char *buffer, struct kernel_param *kp);
|
typedef int (*param_get_fn)(char *buffer, struct kernel_param *kp);
|
||||||
|
|
||||||
/* Flag bits for kernel_param.flags */
|
/* Flag bits for kernel_param.flags */
|
||||||
#define KPARAM_KMALLOCED 1
|
|
||||||
#define KPARAM_ISBOOL 2
|
#define KPARAM_ISBOOL 2
|
||||||
|
|
||||||
struct kernel_param {
|
struct kernel_param {
|
||||||
|
|
|
@ -218,13 +218,9 @@ int param_set_charp(const char *val, struct kernel_param *kp)
|
||||||
return -ENOSPC;
|
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
|
/* This is a hack. We can't need to strdup in early boot, and we
|
||||||
* don't need to; this mangled commandline is preserved. */
|
* don't need to; this mangled commandline is preserved. */
|
||||||
if (slab_is_available()) {
|
if (slab_is_available()) {
|
||||||
kp->flags |= KPARAM_KMALLOCED;
|
|
||||||
*(char **)kp->arg = kstrdup(val, GFP_KERNEL);
|
*(char **)kp->arg = kstrdup(val, GFP_KERNEL);
|
||||||
if (!kp->arg)
|
if (!kp->arg)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
@ -605,11 +601,7 @@ void module_param_sysfs_remove(struct module *mod)
|
||||||
|
|
||||||
void destroy_params(const struct kernel_param *params, unsigned num)
|
void destroy_params(const struct kernel_param *params, unsigned num)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
/* FIXME: This should free kmalloced charp parameters. It doesn't. */
|
||||||
|
|
||||||
for (i = 0; i < num; i++)
|
|
||||||
if (params[i].flags & KPARAM_KMALLOCED)
|
|
||||||
kfree(*(char **)params[i].arg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __init kernel_add_sysfs_param(const char *name,
|
static void __init kernel_add_sysfs_param(const char *name,
|
||||||
|
|
Loading…
Reference in a new issue