diff options
author | Rusty Russell <rusty@rustcorp.com.au> | 2014-08-26 16:55:23 -0400 |
---|---|---|
committer | Rusty Russell <rusty@rustcorp.com.au> | 2014-08-27 08:24:10 -0400 |
commit | 7a486d3781295b5298cbf9556928a76d26896863 (patch) | |
tree | 7a4d6592ed62a04c125d654f5ea6c15669c67b36 | |
parent | fc9740cebc3ab7c65f3c5f6ce0caf3e4969013ca (diff) |
param: check for tainting before calling set op.
This means every set op doesn't need to call it, and it can move into
params.c.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
-rw-r--r-- | include/linux/moduleparam.h | 16 | ||||
-rw-r--r-- | kernel/params.c | 22 |
2 files changed, 11 insertions, 27 deletions
diff --git a/include/linux/moduleparam.h b/include/linux/moduleparam.h index 9531f9f9729e..593501996574 100644 --- a/include/linux/moduleparam.h +++ b/include/linux/moduleparam.h | |||
@@ -374,22 +374,6 @@ static inline void destroy_params(const struct kernel_param *params, | |||
374 | #define __param_check(name, p, type) \ | 374 | #define __param_check(name, p, type) \ |
375 | static inline type __always_unused *__check_##name(void) { return(p); } | 375 | static inline type __always_unused *__check_##name(void) { return(p); } |
376 | 376 | ||
377 | /** | ||
378 | * param_check_unsafe - Warn and taint the kernel if setting dangerous options. | ||
379 | * | ||
380 | * This gets called from all the standard param setters, but can be used from | ||
381 | * custom setters as well. | ||
382 | */ | ||
383 | static inline void | ||
384 | param_check_unsafe(const struct kernel_param *kp) | ||
385 | { | ||
386 | if (kp->flags & KERNEL_PARAM_FL_UNSAFE) { | ||
387 | pr_warn("Setting dangerous option %s - tainting kernel\n", | ||
388 | kp->name); | ||
389 | add_taint(TAINT_USER, LOCKDEP_STILL_OK); | ||
390 | } | ||
391 | } | ||
392 | |||
393 | extern struct kernel_param_ops param_ops_byte; | 377 | extern struct kernel_param_ops param_ops_byte; |
394 | extern int param_set_byte(const char *val, const struct kernel_param *kp); | 378 | extern int param_set_byte(const char *val, const struct kernel_param *kp); |
395 | extern int param_get_byte(char *buffer, const struct kernel_param *kp); | 379 | extern int param_get_byte(char *buffer, const struct kernel_param *kp); |
diff --git a/kernel/params.c b/kernel/params.c index ad8d04563c3a..041b5899d5e2 100644 --- a/kernel/params.c +++ b/kernel/params.c | |||
@@ -83,6 +83,15 @@ bool parameq(const char *a, const char *b) | |||
83 | return parameqn(a, b, strlen(a)+1); | 83 | return parameqn(a, b, strlen(a)+1); |
84 | } | 84 | } |
85 | 85 | ||
86 | static void param_check_unsafe(const struct kernel_param *kp) | ||
87 | { | ||
88 | if (kp->flags & KERNEL_PARAM_FL_UNSAFE) { | ||
89 | pr_warn("Setting dangerous option %s - tainting kernel\n", | ||
90 | kp->name); | ||
91 | add_taint(TAINT_USER, LOCKDEP_STILL_OK); | ||
92 | } | ||
93 | } | ||
94 | |||
86 | static int parse_one(char *param, | 95 | static int parse_one(char *param, |
87 | char *val, | 96 | char *val, |
88 | const char *doing, | 97 | const char *doing, |
@@ -109,6 +118,7 @@ static int parse_one(char *param, | |||
109 | pr_debug("handling %s with %p\n", param, | 118 | pr_debug("handling %s with %p\n", param, |
110 | params[i].ops->set); | 119 | params[i].ops->set); |
111 | mutex_lock(¶m_lock); | 120 | mutex_lock(¶m_lock); |
121 | param_check_unsafe(¶ms[i]); | ||
112 | err = params[i].ops->set(val, ¶ms[i]); | 122 | err = params[i].ops->set(val, ¶ms[i]); |
113 | mutex_unlock(¶m_lock); | 123 | mutex_unlock(¶m_lock); |
114 | return err; | 124 | return err; |
@@ -233,7 +243,6 @@ char *parse_args(const char *doing, | |||
233 | #define STANDARD_PARAM_DEF(name, type, format, strtolfn) \ | 243 | #define STANDARD_PARAM_DEF(name, type, format, strtolfn) \ |
234 | int param_set_##name(const char *val, const struct kernel_param *kp) \ | 244 | int param_set_##name(const char *val, const struct kernel_param *kp) \ |
235 | { \ | 245 | { \ |
236 | param_check_unsafe(kp); \ | ||
237 | return strtolfn(val, 0, (type *)kp->arg); \ | 246 | return strtolfn(val, 0, (type *)kp->arg); \ |
238 | } \ | 247 | } \ |
239 | int param_get_##name(char *buffer, const struct kernel_param *kp) \ | 248 | int param_get_##name(char *buffer, const struct kernel_param *kp) \ |
@@ -266,8 +275,6 @@ int param_set_charp(const char *val, const struct kernel_param *kp) | |||
266 | return -ENOSPC; | 275 | return -ENOSPC; |
267 | } | 276 | } |
268 | 277 | ||
269 | param_check_unsafe(kp); | ||
270 | |||
271 | maybe_kfree_parameter(*(char **)kp->arg); | 278 | maybe_kfree_parameter(*(char **)kp->arg); |
272 | 279 | ||
273 | /* This is a hack. We can't kmalloc in early boot, and we | 280 | /* This is a hack. We can't kmalloc in early boot, and we |
@@ -305,8 +312,6 @@ EXPORT_SYMBOL(param_ops_charp); | |||
305 | /* Actually could be a bool or an int, for historical reasons. */ | 312 | /* Actually could be a bool or an int, for historical reasons. */ |
306 | int param_set_bool(const char *val, const struct kernel_param *kp) | 313 | int param_set_bool(const char *val, const struct kernel_param *kp) |
307 | { | 314 | { |
308 | param_check_unsafe(kp); | ||
309 | |||
310 | /* No equals means "set"... */ | 315 | /* No equals means "set"... */ |
311 | if (!val) val = "1"; | 316 | if (!val) val = "1"; |
312 | 317 | ||
@@ -336,8 +341,6 @@ int param_set_invbool(const char *val, const struct kernel_param *kp) | |||
336 | bool boolval; | 341 | bool boolval; |
337 | struct kernel_param dummy; | 342 | struct kernel_param dummy; |
338 | 343 | ||
339 | param_check_unsafe(kp); | ||
340 | |||
341 | dummy.arg = &boolval; | 344 | dummy.arg = &boolval; |
342 | ret = param_set_bool(val, &dummy); | 345 | ret = param_set_bool(val, &dummy); |
343 | if (ret == 0) | 346 | if (ret == 0) |
@@ -364,8 +367,6 @@ int param_set_bint(const char *val, const struct kernel_param *kp) | |||
364 | bool v; | 367 | bool v; |
365 | int ret; | 368 | int ret; |
366 | 369 | ||
367 | param_check_unsafe(kp); | ||
368 | |||
369 | /* Match bool exactly, by re-using it. */ | 370 | /* Match bool exactly, by re-using it. */ |
370 | boolkp = *kp; | 371 | boolkp = *kp; |
371 | boolkp.arg = &v; | 372 | boolkp.arg = &v; |
@@ -485,8 +486,6 @@ int param_set_copystring(const char *val, const struct kernel_param *kp) | |||
485 | { | 486 | { |
486 | const struct kparam_string *kps = kp->str; | 487 | const struct kparam_string *kps = kp->str; |
487 | 488 | ||
488 | param_check_unsafe(kp); | ||
489 | |||
490 | if (strlen(val)+1 > kps->maxlen) { | 489 | if (strlen(val)+1 > kps->maxlen) { |
491 | pr_err("%s: string doesn't fit in %u chars.\n", | 490 | pr_err("%s: string doesn't fit in %u chars.\n", |
492 | kp->name, kps->maxlen-1); | 491 | kp->name, kps->maxlen-1); |
@@ -563,6 +562,7 @@ static ssize_t param_attr_store(struct module_attribute *mattr, | |||
563 | return -EPERM; | 562 | return -EPERM; |
564 | 563 | ||
565 | mutex_lock(¶m_lock); | 564 | mutex_lock(¶m_lock); |
565 | param_check_unsafe(attribute->param); | ||
566 | err = attribute->param->ops->set(buf, attribute->param); | 566 | err = attribute->param->ops->set(buf, attribute->param); |
567 | mutex_unlock(¶m_lock); | 567 | mutex_unlock(¶m_lock); |
568 | if (!err) | 568 | if (!err) |