summaryrefslogtreecommitdiff
path: root/kernel/params.c
diff options
context:
space:
mode:
authorRusty Russell <rusty@rustcorp.com.au>2014-08-27 06:25:23 +0930
committerRusty Russell <rusty@rustcorp.com.au>2014-08-27 21:54:10 +0930
commit7a486d3781295b5298cbf9556928a76d26896863 (patch)
tree7a4d6592ed62a04c125d654f5ea6c15669c67b36 /kernel/params.c
parentfc9740cebc3ab7c65f3c5f6ce0caf3e4969013ca (diff)
downloadlwn-7a486d3781295b5298cbf9556928a76d26896863.tar.gz
lwn-7a486d3781295b5298cbf9556928a76d26896863.zip
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>
Diffstat (limited to 'kernel/params.c')
-rw-r--r--kernel/params.c22
1 files changed, 11 insertions, 11 deletions
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)
return parameqn(a, b, strlen(a)+1);
}
+static void param_check_unsafe(const struct kernel_param *kp)
+{
+ if (kp->flags & KERNEL_PARAM_FL_UNSAFE) {
+ pr_warn("Setting dangerous option %s - tainting kernel\n",
+ kp->name);
+ add_taint(TAINT_USER, LOCKDEP_STILL_OK);
+ }
+}
+
static int parse_one(char *param,
char *val,
const char *doing,
@@ -109,6 +118,7 @@ static int parse_one(char *param,
pr_debug("handling %s with %p\n", param,
params[i].ops->set);
mutex_lock(&param_lock);
+ param_check_unsafe(&params[i]);
err = params[i].ops->set(val, &params[i]);
mutex_unlock(&param_lock);
return err;
@@ -233,7 +243,6 @@ char *parse_args(const char *doing,
#define STANDARD_PARAM_DEF(name, type, format, strtolfn) \
int param_set_##name(const char *val, const struct kernel_param *kp) \
{ \
- param_check_unsafe(kp); \
return strtolfn(val, 0, (type *)kp->arg); \
} \
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)
return -ENOSPC;
}
- param_check_unsafe(kp);
-
maybe_kfree_parameter(*(char **)kp->arg);
/* This is a hack. We can't kmalloc in early boot, and we
@@ -305,8 +312,6 @@ EXPORT_SYMBOL(param_ops_charp);
/* Actually could be a bool or an int, for historical reasons. */
int param_set_bool(const char *val, const struct kernel_param *kp)
{
- param_check_unsafe(kp);
-
/* No equals means "set"... */
if (!val) val = "1";
@@ -336,8 +341,6 @@ int param_set_invbool(const char *val, const struct kernel_param *kp)
bool boolval;
struct kernel_param dummy;
- param_check_unsafe(kp);
-
dummy.arg = &boolval;
ret = param_set_bool(val, &dummy);
if (ret == 0)
@@ -364,8 +367,6 @@ int param_set_bint(const char *val, const struct kernel_param *kp)
bool v;
int ret;
- param_check_unsafe(kp);
-
/* Match bool exactly, by re-using it. */
boolkp = *kp;
boolkp.arg = &v;
@@ -485,8 +486,6 @@ int param_set_copystring(const char *val, const struct kernel_param *kp)
{
const struct kparam_string *kps = kp->str;
- param_check_unsafe(kp);
-
if (strlen(val)+1 > kps->maxlen) {
pr_err("%s: string doesn't fit in %u chars.\n",
kp->name, kps->maxlen-1);
@@ -563,6 +562,7 @@ static ssize_t param_attr_store(struct module_attribute *mattr,
return -EPERM;
mutex_lock(&param_lock);
+ param_check_unsafe(attribute->param);
err = attribute->param->ops->set(buf, attribute->param);
mutex_unlock(&param_lock);
if (!err)