aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJani Nikula <jani.nikula@intel.com>2014-08-26 16:52:23 -0400
committerRusty Russell <rusty@rustcorp.com.au>2014-08-27 08:24:08 -0400
commit91f9d330cc14932084c37751997213cb0e7ea882 (patch)
tree8a7494e64787ea72ce4ed86c5298a1b1b7195111
parent6a4c264313c4ae32dc53821a9c57e0dc9696fb81 (diff)
module: make it possible to have unsafe, tainting module params
Add flags field to struct kernel_params, and add the first flag: unsafe parameter. Modifying a kernel parameter with the unsafe flag set, either via the kernel command line or sysfs, will issue a warning and taint the kernel. Cc: Rusty Russell <rusty@rustcorp.com.au> Cc: Jean Delvare <khali@linux-fr.org> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Li Zhong <zhong@linux.vnet.ibm.com> Cc: Jon Mason <jon.mason@intel.com> Cc: Daniel Vetter <daniel.vetter@ffwll.ch> Signed-off-by: Jani Nikula <jani.nikula@intel.com> Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
-rw-r--r--drivers/tty/serial/8250/8250_core.c2
-rw-r--r--include/linux/moduleparam.h44
-rw-r--r--kernel/params.c11
3 files changed, 47 insertions, 10 deletions
diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c
index 1d42dba6121d..bd672948f2f1 100644
--- a/drivers/tty/serial/8250/8250_core.c
+++ b/drivers/tty/serial/8250/8250_core.c
@@ -3587,7 +3587,7 @@ static void __used s8250_options(void)
3587#ifdef CONFIG_SERIAL_8250_RSA 3587#ifdef CONFIG_SERIAL_8250_RSA
3588 __module_param_call(MODULE_PARAM_PREFIX, probe_rsa, 3588 __module_param_call(MODULE_PARAM_PREFIX, probe_rsa,
3589 &param_array_ops, .arr = &__param_arr_probe_rsa, 3589 &param_array_ops, .arr = &__param_arr_probe_rsa,
3590 0444, -1); 3590 0444, -1, 0);
3591#endif 3591#endif
3592} 3592}
3593#else 3593#else
diff --git a/include/linux/moduleparam.h b/include/linux/moduleparam.h
index 16fdddab856a..1e3ffb839daa 100644
--- a/include/linux/moduleparam.h
+++ b/include/linux/moduleparam.h
@@ -56,11 +56,21 @@ struct kernel_param_ops {
56 void (*free)(void *arg); 56 void (*free)(void *arg);
57}; 57};
58 58
59/*
60 * Flags available for kernel_param
61 *
62 * UNSAFE - the parameter is dangerous and setting it will taint the kernel
63 */
64enum {
65 KERNEL_PARAM_FL_UNSAFE = (1 << 0)
66};
67
59struct kernel_param { 68struct kernel_param {
60 const char *name; 69 const char *name;
61 const struct kernel_param_ops *ops; 70 const struct kernel_param_ops *ops;
62 u16 perm; 71 u16 perm;
63 s16 level; 72 s8 level;
73 u8 flags;
64 union { 74 union {
65 void *arg; 75 void *arg;
66 const struct kparam_string *str; 76 const struct kparam_string *str;
@@ -137,7 +147,7 @@ struct kparam_array
137 * The ops can have NULL set or get functions. 147 * The ops can have NULL set or get functions.
138 */ 148 */
139#define module_param_cb(name, ops, arg, perm) \ 149#define module_param_cb(name, ops, arg, perm) \
140 __module_param_call(MODULE_PARAM_PREFIX, name, ops, arg, perm, -1) 150 __module_param_call(MODULE_PARAM_PREFIX, name, ops, arg, perm, -1, 0)
141 151
142/** 152/**
143 * <level>_param_cb - general callback for a module/cmdline parameter 153 * <level>_param_cb - general callback for a module/cmdline parameter
@@ -149,7 +159,7 @@ struct kparam_array
149 * The ops can have NULL set or get functions. 159 * The ops can have NULL set or get functions.
150 */ 160 */
151#define __level_param_cb(name, ops, arg, perm, level) \ 161#define __level_param_cb(name, ops, arg, perm, level) \
152 __module_param_call(MODULE_PARAM_PREFIX, name, ops, arg, perm, level) 162 __module_param_call(MODULE_PARAM_PREFIX, name, ops, arg, perm, level, 0)
153 163
154#define core_param_cb(name, ops, arg, perm) \ 164#define core_param_cb(name, ops, arg, perm) \
155 __level_param_cb(name, ops, arg, perm, 1) 165 __level_param_cb(name, ops, arg, perm, 1)
@@ -184,14 +194,14 @@ struct kparam_array
184 194
185/* This is the fundamental function for registering boot/module 195/* This is the fundamental function for registering boot/module
186 parameters. */ 196 parameters. */
187#define __module_param_call(prefix, name, ops, arg, perm, level) \ 197#define __module_param_call(prefix, name, ops, arg, perm, level, flags) \
188 /* Default value instead of permissions? */ \ 198 /* Default value instead of permissions? */ \
189 static const char __param_str_##name[] = prefix #name; \ 199 static const char __param_str_##name[] = prefix #name; \
190 static struct kernel_param __moduleparam_const __param_##name \ 200 static struct kernel_param __moduleparam_const __param_##name \
191 __used \ 201 __used \
192 __attribute__ ((unused,__section__ ("__param"),aligned(sizeof(void *)))) \ 202 __attribute__ ((unused,__section__ ("__param"),aligned(sizeof(void *)))) \
193 = { __param_str_##name, ops, VERIFY_OCTAL_PERMISSIONS(perm), \ 203 = { __param_str_##name, ops, VERIFY_OCTAL_PERMISSIONS(perm), \
194 level, { arg } } 204 level, flags, { arg } }
195 205
196/* Obsolete - use module_param_cb() */ 206/* Obsolete - use module_param_cb() */
197#define module_param_call(name, set, get, arg, perm) \ 207#define module_param_call(name, set, get, arg, perm) \
@@ -199,7 +209,7 @@ struct kparam_array
199 { 0, (void *)set, (void *)get }; \ 209 { 0, (void *)set, (void *)get }; \
200 __module_param_call(MODULE_PARAM_PREFIX, \ 210 __module_param_call(MODULE_PARAM_PREFIX, \
201 name, &__param_ops_##name, arg, \ 211 name, &__param_ops_##name, arg, \
202 (perm) + sizeof(__check_old_set_param(set))*0, -1) 212 (perm) + sizeof(__check_old_set_param(set))*0, -1, 0)
203 213
204/* We don't get oldget: it's often a new-style param_get_uint, etc. */ 214/* We don't get oldget: it's often a new-style param_get_uint, etc. */
205static inline int 215static inline int
@@ -279,7 +289,7 @@ static inline void __kernel_param_unlock(void)
279 */ 289 */
280#define core_param(name, var, type, perm) \ 290#define core_param(name, var, type, perm) \
281 param_check_##type(name, &(var)); \ 291 param_check_##type(name, &(var)); \
282 __module_param_call("", name, &param_ops_##type, &var, perm, -1) 292 __module_param_call("", name, &param_ops_##type, &var, perm, -1, 0)
283#endif /* !MODULE */ 293#endif /* !MODULE */
284 294
285/** 295/**
@@ -297,7 +307,7 @@ static inline void __kernel_param_unlock(void)
297 = { len, string }; \ 307 = { len, string }; \
298 __module_param_call(MODULE_PARAM_PREFIX, name, \ 308 __module_param_call(MODULE_PARAM_PREFIX, name, \
299 &param_ops_string, \ 309 &param_ops_string, \
300 .str = &__param_string_##name, perm, -1); \ 310 .str = &__param_string_##name, perm, -1, 0);\
301 __MODULE_PARM_TYPE(name, "string") 311 __MODULE_PARM_TYPE(name, "string")
302 312
303/** 313/**
@@ -346,6 +356,22 @@ static inline void destroy_params(const struct kernel_param *params,
346#define __param_check(name, p, type) \ 356#define __param_check(name, p, type) \
347 static inline type __always_unused *__check_##name(void) { return(p); } 357 static inline type __always_unused *__check_##name(void) { return(p); }
348 358
359/**
360 * param_check_unsafe - Warn and taint the kernel if setting dangerous options.
361 *
362 * This gets called from all the standard param setters, but can be used from
363 * custom setters as well.
364 */
365static inline void
366param_check_unsafe(const struct kernel_param *kp)
367{
368 if (kp->flags & KERNEL_PARAM_FL_UNSAFE) {
369 pr_warn("Setting dangerous option %s - tainting kernel\n",
370 kp->name);
371 add_taint(TAINT_USER, LOCKDEP_STILL_OK);
372 }
373}
374
349extern struct kernel_param_ops param_ops_byte; 375extern struct kernel_param_ops param_ops_byte;
350extern int param_set_byte(const char *val, const struct kernel_param *kp); 376extern int param_set_byte(const char *val, const struct kernel_param *kp);
351extern int param_get_byte(char *buffer, const struct kernel_param *kp); 377extern int param_get_byte(char *buffer, const struct kernel_param *kp);
@@ -444,7 +470,7 @@ extern int param_set_bint(const char *val, const struct kernel_param *kp);
444 __module_param_call(MODULE_PARAM_PREFIX, name, \ 470 __module_param_call(MODULE_PARAM_PREFIX, name, \
445 &param_array_ops, \ 471 &param_array_ops, \
446 .arr = &__param_arr_##name, \ 472 .arr = &__param_arr_##name, \
447 perm, -1); \ 473 perm, -1, 0); \
448 __MODULE_PARM_TYPE(name, "array of " #type) 474 __MODULE_PARM_TYPE(name, "array of " #type)
449 475
450extern struct kernel_param_ops param_array_ops; 476extern struct kernel_param_ops param_array_ops;
diff --git a/kernel/params.c b/kernel/params.c
index 8a484fc8bde8..ad8d04563c3a 100644
--- a/kernel/params.c
+++ b/kernel/params.c
@@ -233,6 +233,7 @@ char *parse_args(const char *doing,
233#define STANDARD_PARAM_DEF(name, type, format, strtolfn) \ 233#define STANDARD_PARAM_DEF(name, type, format, strtolfn) \
234 int param_set_##name(const char *val, const struct kernel_param *kp) \ 234 int param_set_##name(const char *val, const struct kernel_param *kp) \
235 { \ 235 { \
236 param_check_unsafe(kp); \
236 return strtolfn(val, 0, (type *)kp->arg); \ 237 return strtolfn(val, 0, (type *)kp->arg); \
237 } \ 238 } \
238 int param_get_##name(char *buffer, const struct kernel_param *kp) \ 239 int param_get_##name(char *buffer, const struct kernel_param *kp) \
@@ -265,6 +266,8 @@ int param_set_charp(const char *val, const struct kernel_param *kp)
265 return -ENOSPC; 266 return -ENOSPC;
266 } 267 }
267 268
269 param_check_unsafe(kp);
270
268 maybe_kfree_parameter(*(char **)kp->arg); 271 maybe_kfree_parameter(*(char **)kp->arg);
269 272
270 /* This is a hack. We can't kmalloc in early boot, and we 273 /* This is a hack. We can't kmalloc in early boot, and we
@@ -302,6 +305,8 @@ EXPORT_SYMBOL(param_ops_charp);
302/* Actually could be a bool or an int, for historical reasons. */ 305/* Actually could be a bool or an int, for historical reasons. */
303int param_set_bool(const char *val, const struct kernel_param *kp) 306int param_set_bool(const char *val, const struct kernel_param *kp)
304{ 307{
308 param_check_unsafe(kp);
309
305 /* No equals means "set"... */ 310 /* No equals means "set"... */
306 if (!val) val = "1"; 311 if (!val) val = "1";
307 312
@@ -331,6 +336,8 @@ int param_set_invbool(const char *val, const struct kernel_param *kp)
331 bool boolval; 336 bool boolval;
332 struct kernel_param dummy; 337 struct kernel_param dummy;
333 338
339 param_check_unsafe(kp);
340
334 dummy.arg = &boolval; 341 dummy.arg = &boolval;
335 ret = param_set_bool(val, &dummy); 342 ret = param_set_bool(val, &dummy);
336 if (ret == 0) 343 if (ret == 0)
@@ -357,6 +364,8 @@ int param_set_bint(const char *val, const struct kernel_param *kp)
357 bool v; 364 bool v;
358 int ret; 365 int ret;
359 366
367 param_check_unsafe(kp);
368
360 /* Match bool exactly, by re-using it. */ 369 /* Match bool exactly, by re-using it. */
361 boolkp = *kp; 370 boolkp = *kp;
362 boolkp.arg = &v; 371 boolkp.arg = &v;
@@ -476,6 +485,8 @@ int param_set_copystring(const char *val, const struct kernel_param *kp)
476{ 485{
477 const struct kparam_string *kps = kp->str; 486 const struct kparam_string *kps = kp->str;
478 487
488 param_check_unsafe(kp);
489
479 if (strlen(val)+1 > kps->maxlen) { 490 if (strlen(val)+1 > kps->maxlen) {
480 pr_err("%s: string doesn't fit in %u chars.\n", 491 pr_err("%s: string doesn't fit in %u chars.\n",
481 kp->name, kps->maxlen-1); 492 kp->name, kps->maxlen-1);