[36/99] param: fix lots of bugs with writing charp params from sysfs, by leaking mem.

From: Greg KH
Date: Fri Nov 06 2009 - 17:23:07 EST

2.6.31-stable review patch. If anyone has any objections, please let us know.

From: Rusty Russell <rusty@xxxxxxxxxxxxxxx>

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@xxxxxxx>
Cc: Sitsofe Wheeler <sitsofe@xxxxxxxxx>
Cc: Frederic Weisbecker <fweisbec@xxxxxxxxx>
Cc: Christof Schmitt <christof.schmitt@xxxxxxxxxx>
Signed-off-by: Rusty Russell <rusty@xxxxxxxxxxxxxxx>
Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxx>

include/linux/moduleparam.h | 1 -
kernel/params.c | 10 +---------
2 files changed, 1 insertion(+), 10 deletions(-)

--- a/include/linux/moduleparam.h
+++ b/include/linux/moduleparam.h
@@ -37,7 +37,6 @@ typedef int (*param_set_fn)(const char *
typedef int (*param_get_fn)(char *buffer, struct kernel_param *kp);

/* Flag bits for kernel_param.flags */

struct kernel_param {
--- a/kernel/params.c
+++ b/kernel/params.c
@@ -217,13 +217,9 @@ int param_set_charp(const char *val, str
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 mo

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,

To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/