param: check for tainting before calling set op.
authorRusty Russell <rusty@rustcorp.com.au>
Tue, 26 Aug 2014 20:55:23 +0000 (06:25 +0930)
committerRusty Russell <rusty@rustcorp.com.au>
Wed, 27 Aug 2014 12:24:10 +0000 (21:54 +0930)
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>
include/linux/moduleparam.h
kernel/params.c

index 9531f9f9729efd1bcd0bb845b8aecf7dd5361e69..593501996574f7893b1633e471350f35f76731e4 100644 (file)
@@ -374,22 +374,6 @@ static inline void destroy_params(const struct kernel_param *params,
 #define __param_check(name, p, type) \
        static inline type __always_unused *__check_##name(void) { return(p); }
 
-/**
- * param_check_unsafe - Warn and taint the kernel if setting dangerous options.
- *
- * This gets called from all the standard param setters, but can be used from
- * custom setters as well.
- */
-static inline 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);
-       }
-}
-
 extern struct kernel_param_ops param_ops_byte;
 extern int param_set_byte(const char *val, const struct kernel_param *kp);
 extern int param_get_byte(char *buffer, const struct kernel_param *kp);
index ad8d04563c3a02bf3fa81fe6ff29b0317c972c3c..041b5899d5e2d0c70f791224d4e5697ddff2880b 100644 (file)
@@ -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)