diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/params.c | 52 |
1 files changed, 50 insertions, 2 deletions
diff --git a/kernel/params.c b/kernel/params.c index 458a09b886c4..ef60db14fae0 100644 --- a/kernel/params.c +++ b/kernel/params.c | |||
| @@ -31,6 +31,45 @@ | |||
| 31 | #define DEBUGP(fmt, a...) | 31 | #define DEBUGP(fmt, a...) |
| 32 | #endif | 32 | #endif |
| 33 | 33 | ||
| 34 | /* This just allows us to keep track of which parameters are kmalloced. */ | ||
| 35 | struct kmalloced_param { | ||
| 36 | struct list_head list; | ||
| 37 | char val[]; | ||
| 38 | }; | ||
| 39 | static DEFINE_MUTEX(param_lock); | ||
| 40 | static LIST_HEAD(kmalloced_params); | ||
| 41 | |||
| 42 | static void *kmalloc_parameter(unsigned int size) | ||
| 43 | { | ||
| 44 | struct kmalloced_param *p; | ||
| 45 | |||
| 46 | p = kmalloc(sizeof(*p) + size, GFP_KERNEL); | ||
| 47 | if (!p) | ||
| 48 | return NULL; | ||
| 49 | |||
| 50 | mutex_lock(¶m_lock); | ||
| 51 | list_add(&p->list, &kmalloced_params); | ||
| 52 | mutex_unlock(¶m_lock); | ||
| 53 | |||
| 54 | return p->val; | ||
| 55 | } | ||
| 56 | |||
| 57 | /* Does nothing if parameter wasn't kmalloced above. */ | ||
| 58 | static void maybe_kfree_parameter(void *param) | ||
| 59 | { | ||
| 60 | struct kmalloced_param *p; | ||
| 61 | |||
| 62 | mutex_lock(¶m_lock); | ||
| 63 | list_for_each_entry(p, &kmalloced_params, list) { | ||
| 64 | if (p->val == param) { | ||
| 65 | list_del(&p->list); | ||
| 66 | kfree(p); | ||
| 67 | break; | ||
| 68 | } | ||
| 69 | } | ||
| 70 | mutex_unlock(¶m_lock); | ||
| 71 | } | ||
| 72 | |||
| 34 | static inline char dash2underscore(char c) | 73 | static inline char dash2underscore(char c) |
| 35 | { | 74 | { |
| 36 | if (c == '-') | 75 | if (c == '-') |
| @@ -219,12 +258,15 @@ int param_set_charp(const char *val, const struct kernel_param *kp) | |||
| 219 | return -ENOSPC; | 258 | return -ENOSPC; |
| 220 | } | 259 | } |
| 221 | 260 | ||
| 222 | /* This is a hack. We can't need to strdup in early boot, and we | 261 | maybe_kfree_parameter(*(char **)kp->arg); |
| 262 | |||
| 263 | /* This is a hack. We can't kmalloc in early boot, and we | ||
| 223 | * don't need to; this mangled commandline is preserved. */ | 264 | * don't need to; this mangled commandline is preserved. */ |
| 224 | if (slab_is_available()) { | 265 | if (slab_is_available()) { |
| 225 | *(char **)kp->arg = kstrdup(val, GFP_KERNEL); | 266 | *(char **)kp->arg = kmalloc_parameter(strlen(val)+1); |
| 226 | if (!*(char **)kp->arg) | 267 | if (!*(char **)kp->arg) |
| 227 | return -ENOMEM; | 268 | return -ENOMEM; |
| 269 | strcpy(*(char **)kp->arg, val); | ||
| 228 | } else | 270 | } else |
| 229 | *(const char **)kp->arg = val; | 271 | *(const char **)kp->arg = val; |
| 230 | 272 | ||
| @@ -238,9 +280,15 @@ int param_get_charp(char *buffer, const struct kernel_param *kp) | |||
| 238 | } | 280 | } |
| 239 | EXPORT_SYMBOL(param_get_charp); | 281 | EXPORT_SYMBOL(param_get_charp); |
| 240 | 282 | ||
| 283 | static void param_free_charp(void *arg) | ||
| 284 | { | ||
| 285 | maybe_kfree_parameter(*((char **)arg)); | ||
| 286 | } | ||
| 287 | |||
| 241 | struct kernel_param_ops param_ops_charp = { | 288 | struct kernel_param_ops param_ops_charp = { |
| 242 | .set = param_set_charp, | 289 | .set = param_set_charp, |
| 243 | .get = param_get_charp, | 290 | .get = param_get_charp, |
| 291 | .free = param_free_charp, | ||
| 244 | }; | 292 | }; |
| 245 | EXPORT_SYMBOL(param_ops_charp); | 293 | EXPORT_SYMBOL(param_ops_charp); |
| 246 | 294 | ||
