Merge tag 'modules-next-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 11 Jun 2014 23:09:14 +0000 (16:09 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 11 Jun 2014 23:09:14 +0000 (16:09 -0700)
Pull module updates from Rusty Russell:
 "Most of this is cleaning up various driver sysfs permissions so we can
  re-add the perm check (we unified the module param and sysfs checks,
  but the module ones were stronger so we weakened them temporarily).

  Param parsing gets documented, and also "--" now forces args to be
  handed to init (and ignored by the kernel).

  Module NX/RO protections get tightened: we now set them before calling
  parse_args()"

* tag 'modules-next-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux:
  module: set nx before marking module MODULE_STATE_COMING.
  samples/kobject/: avoid world-writable sysfs files.
  drivers/hid/hid-picolcd_fb: avoid world-writable sysfs files.
  drivers/staging/speakup/: avoid world-writable sysfs files.
  drivers/regulator/virtual: avoid world-writable sysfs files.
  drivers/scsi/pm8001/pm8001_ctl.c: avoid world-writable sysfs files.
  drivers/hid/hid-lg4ff.c: avoid world-writable sysfs files.
  drivers/video/fbdev/sm501fb.c: avoid world-writable sysfs files.
  drivers/mtd/devices/docg3.c: avoid world-writable sysfs files.
  speakup: fix incorrect perms on speakup_acntsa.c
  cpumask.h: silence warning with -Wsign-compare
  Documentation: Update kernel-parameters.tx
  param: hand arguments after -- straight to init
  modpost: Fix resource leak in read_dump()

15 files changed:
Documentation/kernel-parameters.txt
drivers/hid/hid-lg4ff.c
drivers/hid/hid-picolcd_fb.c
drivers/mtd/devices/docg3.c
drivers/regulator/virtual.c
drivers/scsi/pm8001/pm8001_ctl.c
drivers/video/fbdev/sm501fb.c
include/linux/cpumask.h
include/linux/moduleparam.h
init/main.c
kernel/module.c
kernel/params.c
samples/kobject/kobject-example.c
samples/kobject/kset-example.c
scripts/mod/modpost.c

index b9f67781c577d04118de98dee652baa32568618b..6eaa9cdb7094b5785aecc54e55d4cb5bd08a8de9 100644 (file)
@@ -1,27 +1,37 @@
                           Kernel Parameters
                           ~~~~~~~~~~~~~~~~~
 
-The following is a consolidated list of the kernel parameters as implemented
-(mostly) by the __setup() macro and sorted into English Dictionary order
-(defined as ignoring all punctuation and sorting digits before letters in a
-case insensitive manner), and with descriptions where known.
-
-Module parameters for loadable modules are specified only as the
-parameter name with optional '=' and value as appropriate, such as:
-
-       modprobe usbcore blinkenlights=1
-
-Module parameters for modules that are built into the kernel image
-are specified on the kernel command line with the module name plus
-'.' plus parameter name, with '=' and value if appropriate, such as:
-
-       usbcore.blinkenlights=1
+The following is a consolidated list of the kernel parameters as
+implemented by the __setup(), core_param() and module_param() macros
+and sorted into English Dictionary order (defined as ignoring all
+punctuation and sorting digits before letters in a case insensitive
+manner), and with descriptions where known.
+
+The kernel parses parameters from the kernel command line up to "--";
+if it doesn't recognize a parameter and it doesn't contain a '.', the
+parameter gets passed to init: parameters with '=' go into init's
+environment, others are passed as command line arguments to init.
+Everything after "--" is passed as an argument to init.
+
+Module parameters can be specified in two ways: via the kernel command
+line with a module name prefix, or via modprobe, e.g.:
+
+       (kernel command line) usbcore.blinkenlights=1
+       (modprobe command line) modprobe usbcore blinkenlights=1
+
+Parameters for modules which are built into the kernel need to be
+specified on the kernel command line.  modprobe looks through the
+kernel command line (/proc/cmdline) and collects module parameters
+when it loads a module, so the kernel command line can be used for
+loadable modules too.
 
 Hyphens (dashes) and underscores are equivalent in parameter names, so
        log_buf_len=1M print-fatal-signals=1
 can also be entered as
        log-buf-len=1M print_fatal_signals=1
 
+Double-quotes can be used to protect spaces in values, e.g.:
+       param="spaces in here"
 
 This document may not be entirely up to date and comprehensive. The command
 "modinfo -p ${modulename}" shows a current list of all parameters of a loadable
index 24883b4d1a49d40a2bb3462ee36ed094f474b3cd..cc2bd20221989aa0284269cce533c28ab2e7295c 100644 (file)
@@ -52,7 +52,7 @@ static void hid_lg4ff_set_range_g25(struct hid_device *hid, u16 range);
 static ssize_t lg4ff_range_show(struct device *dev, struct device_attribute *attr, char *buf);
 static ssize_t lg4ff_range_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
 
-static DEVICE_ATTR(range, S_IRWXU | S_IRWXG | S_IRWXO, lg4ff_range_show, lg4ff_range_store);
+static DEVICE_ATTR(range, S_IRWXU | S_IRWXG | S_IROTH, lg4ff_range_show, lg4ff_range_store);
 
 struct lg4ff_device_entry {
        __u32 product_id;
index c930ab8554eac830dd8d615e86c01926bb716be0..7f965e2314335857df32bb70c5b9472f7620e96d 100644 (file)
@@ -501,7 +501,7 @@ static ssize_t picolcd_fb_update_rate_store(struct device *dev,
        return count;
 }
 
-static DEVICE_ATTR(fb_update_rate, 0666, picolcd_fb_update_rate_show,
+static DEVICE_ATTR(fb_update_rate, 0664, picolcd_fb_update_rate_show,
                picolcd_fb_update_rate_store);
 
 /* initialize Framebuffer device */
index dd5e1018d37b39e9301c9c43e01195f4f363a66c..91a169c44b390b29dc320b987b98acd804f5417e 100644 (file)
@@ -1608,8 +1608,8 @@ static ssize_t dps1_insert_key(struct device *dev,
 #define FLOOR_SYSFS(id) { \
        __ATTR(f##id##_dps0_is_keylocked, S_IRUGO, dps0_is_key_locked, NULL), \
        __ATTR(f##id##_dps1_is_keylocked, S_IRUGO, dps1_is_key_locked, NULL), \
-       __ATTR(f##id##_dps0_protection_key, S_IWUGO, NULL, dps0_insert_key), \
-       __ATTR(f##id##_dps1_protection_key, S_IWUGO, NULL, dps1_insert_key), \
+       __ATTR(f##id##_dps0_protection_key, S_IWUSR|S_IWGRP, NULL, dps0_insert_key), \
+       __ATTR(f##id##_dps1_protection_key, S_IWUSR|S_IWGRP, NULL, dps1_insert_key), \
 }
 
 static struct device_attribute doc_sys_attrs[DOC_MAX_NBFLOORS][4] = {
index f53e78b9a84eadf1c9b2cded2c1ac00f7b7f055c..6ff95b0459849c84a1d206548defc40f469ec963 100644 (file)
@@ -266,11 +266,11 @@ static ssize_t set_mode(struct device *dev, struct device_attribute *attr,
        return count;
 }
 
-static DEVICE_ATTR(min_microvolts, 0666, show_min_uV, set_min_uV);
-static DEVICE_ATTR(max_microvolts, 0666, show_max_uV, set_max_uV);
-static DEVICE_ATTR(min_microamps, 0666, show_min_uA, set_min_uA);
-static DEVICE_ATTR(max_microamps, 0666, show_max_uA, set_max_uA);
-static DEVICE_ATTR(mode, 0666, show_mode, set_mode);
+static DEVICE_ATTR(min_microvolts, 0664, show_min_uV, set_min_uV);
+static DEVICE_ATTR(max_microvolts, 0664, show_max_uV, set_max_uV);
+static DEVICE_ATTR(min_microamps, 0664, show_min_uA, set_min_uA);
+static DEVICE_ATTR(max_microamps, 0664, show_max_uA, set_max_uA);
+static DEVICE_ATTR(mode, 0664, show_mode, set_mode);
 
 static struct attribute *regulator_virtual_attributes[] = {
        &dev_attr_min_microvolts.attr,
index fe5eee4d0a1133645116fb7af6e799e0154bddf7..a368d77b8d4100dbe267da5f9f419e0a2dbaa68f 100644 (file)
@@ -732,7 +732,7 @@ static ssize_t pm8001_show_update_fw(struct device *cdev,
                        flash_error_table[i].reason);
 }
 
-static DEVICE_ATTR(update_fw, S_IRUGO|S_IWUGO,
+static DEVICE_ATTR(update_fw, S_IRUGO|S_IWUSR|S_IWGRP,
        pm8001_show_update_fw, pm8001_store_update_fw);
 struct device_attribute *pm8001_host_attrs[] = {
        &dev_attr_interface_rev,
index 1501979099dce08b1b17cff6d0dc281135a9dcb0..c2c8eb668784f08766444b1cabb159c37c92f455 100644 (file)
@@ -1215,7 +1215,7 @@ static ssize_t sm501fb_crtsrc_store(struct device *dev,
 }
 
 /* Prepare the device_attr for registration with sysfs later */
-static DEVICE_ATTR(crt_src, 0666, sm501fb_crtsrc_show, sm501fb_crtsrc_store);
+static DEVICE_ATTR(crt_src, 0664, sm501fb_crtsrc_show, sm501fb_crtsrc_store);
 
 /* sm501fb_show_regs
  *
index d08e4d2a9b92550af4b395bb62d101873d9d7731..3557ea7b2049fb0f930efd1b4d7f8b815fb6fd4d 100644 (file)
@@ -600,7 +600,7 @@ static inline int cpulist_scnprintf(char *buf, int len,
 static inline int cpumask_parse(const char *buf, struct cpumask *dstp)
 {
        char *nl = strchr(buf, '\n');
-       int len = nl ? nl - buf : strlen(buf);
+       unsigned int len = nl ? (unsigned int)(nl - buf) : strlen(buf);
 
        return bitmap_parse(buf, len, cpumask_bits(dstp), nr_cpumask_bits);
 }
index 204a677438049b13570e779f36078e0450298614..b1990c5524e1cea5a0d52f618f0846a1fd442dfe 100644 (file)
@@ -321,7 +321,7 @@ extern bool parameq(const char *name1, const char *name2);
 extern bool parameqn(const char *name1, const char *name2, size_t n);
 
 /* Called on module insert or kernel boot */
-extern int parse_args(const char *name,
+extern char *parse_args(const char *name,
                      char *args,
                      const struct kernel_param *params,
                      unsigned num,
index 0ec25157deef71160819c326e7c229d431c5de00..e8ae1fef0908965b0c5fff7ba7ab8f043e83a980 100644 (file)
@@ -253,6 +253,27 @@ static int __init repair_env_string(char *param, char *val, const char *unused)
        return 0;
 }
 
+/* Anything after -- gets handed straight to init. */
+static int __init set_init_arg(char *param, char *val, const char *unused)
+{
+       unsigned int i;
+
+       if (panic_later)
+               return 0;
+
+       repair_env_string(param, val, unused);
+
+       for (i = 0; argv_init[i]; i++) {
+               if (i == MAX_INIT_ARGS) {
+                       panic_later = "init";
+                       panic_param = param;
+                       return 0;
+               }
+       }
+       argv_init[i] = param;
+       return 0;
+}
+
 /*
  * Unknown boot options get handed to init, unless they look like
  * unused parameters (modprobe will find them in /proc/cmdline).
@@ -479,7 +500,7 @@ static void __init mm_init(void)
 
 asmlinkage __visible void __init start_kernel(void)
 {
-       char * command_line;
+       char * command_line, *after_dashes;
        extern const struct kernel_param __start___param[], __stop___param[];
 
        /*
@@ -519,9 +540,13 @@ asmlinkage __visible void __init start_kernel(void)
 
        pr_notice("Kernel command line: %s\n", boot_command_line);
        parse_early_param();
-       parse_args("Booting kernel", static_command_line, __start___param,
-                  __stop___param - __start___param,
-                  -1, -1, &unknown_bootoption);
+       after_dashes = parse_args("Booting kernel",
+                                 static_command_line, __start___param,
+                                 __stop___param - __start___param,
+                                 -1, -1, &unknown_bootoption);
+       if (after_dashes)
+               parse_args("Setting init args", after_dashes, NULL, 0, -1, -1,
+                          set_init_arg);
 
        jump_label_init();
 
index 079c4615607d6ed266330a5416529bfcc37e4db0..81e727cf6df97d8477edad3e69f97c0f3242dae3 100644 (file)
@@ -3020,21 +3020,6 @@ static int do_init_module(struct module *mod)
         */
        current->flags &= ~PF_USED_ASYNC;
 
-       blocking_notifier_call_chain(&module_notify_list,
-                       MODULE_STATE_COMING, mod);
-
-       /* Set RO and NX regions for core */
-       set_section_ro_nx(mod->module_core,
-                               mod->core_text_size,
-                               mod->core_ro_size,
-                               mod->core_size);
-
-       /* Set RO and NX regions for init */
-       set_section_ro_nx(mod->module_init,
-                               mod->init_text_size,
-                               mod->init_ro_size,
-                               mod->init_size);
-
        do_mod_ctors(mod);
        /* Start the module */
        if (mod->init != NULL)
@@ -3165,9 +3150,26 @@ static int complete_formation(struct module *mod, struct load_info *info)
        /* This relies on module_mutex for list integrity. */
        module_bug_finalize(info->hdr, info->sechdrs, mod);
 
+       /* Set RO and NX regions for core */
+       set_section_ro_nx(mod->module_core,
+                               mod->core_text_size,
+                               mod->core_ro_size,
+                               mod->core_size);
+
+       /* Set RO and NX regions for init */
+       set_section_ro_nx(mod->module_init,
+                               mod->init_text_size,
+                               mod->init_ro_size,
+                               mod->init_size);
+
        /* Mark state as coming so strong_try_module_get() ignores us,
         * but kallsyms etc. can see us. */
        mod->state = MODULE_STATE_COMING;
+       mutex_unlock(&module_mutex);
+
+       blocking_notifier_call_chain(&module_notify_list,
+                                    MODULE_STATE_COMING, mod);
+       return 0;
 
 out:
        mutex_unlock(&module_mutex);
@@ -3190,6 +3192,7 @@ static int load_module(struct load_info *info, const char __user *uargs,
 {
        struct module *mod;
        long err;
+       char *after_dashes;
 
        err = module_sig_check(info);
        if (err)
@@ -3277,10 +3280,15 @@ static int load_module(struct load_info *info, const char __user *uargs,
                goto ddebug_cleanup;
 
        /* Module is ready to execute: parsing args may do that. */
-       err = parse_args(mod->name, mod->args, mod->kp, mod->num_kp,
-                        -32768, 32767, unknown_module_param_cb);
-       if (err < 0)
+       after_dashes = parse_args(mod->name, mod->args, mod->kp, mod->num_kp,
+                                 -32768, 32767, unknown_module_param_cb);
+       if (IS_ERR(after_dashes)) {
+               err = PTR_ERR(after_dashes);
                goto bug_cleanup;
+       } else if (after_dashes) {
+               pr_warn("%s: parameters '%s' after `--' ignored\n",
+                      mod->name, after_dashes);
+       }
 
        /* Link in to syfs. */
        err = mod_sysfs_setup(mod, info, mod->kp, mod->num_kp);
index b00142e7f3ba18d52f41e19427f145eb6e95cf2d..1e52ca233fd9a45484418f14820c40b95e89d6ba 100644 (file)
@@ -177,13 +177,13 @@ static char *next_arg(char *args, char **param, char **val)
 }
 
 /* Args looks like "foo=bar,bar2 baz=fuz wiz". */
-int parse_args(const char *doing,
-              char *args,
-              const struct kernel_param *params,
-              unsigned num,
-              s16 min_level,
-              s16 max_level,
-              int (*unknown)(char *param, char *val, const char *doing))
+char *parse_args(const char *doing,
+                char *args,
+                const struct kernel_param *params,
+                unsigned num,
+                s16 min_level,
+                s16 max_level,
+                int (*unknown)(char *param, char *val, const char *doing))
 {
        char *param, *val;
 
@@ -198,6 +198,9 @@ int parse_args(const char *doing,
                int irq_was_disabled;
 
                args = next_arg(args, &param, &val);
+               /* Stop at -- */
+               if (!val && strcmp(param, "--") == 0)
+                       return args;
                irq_was_disabled = irqs_disabled();
                ret = parse_one(param, val, doing, params, num,
                                min_level, max_level, unknown);
@@ -208,22 +211,22 @@ int parse_args(const char *doing,
                switch (ret) {
                case -ENOENT:
                        pr_err("%s: Unknown parameter `%s'\n", doing, param);
-                       return ret;
+                       return ERR_PTR(ret);
                case -ENOSPC:
                        pr_err("%s: `%s' too large for parameter `%s'\n",
                               doing, val ?: "", param);
-                       return ret;
+                       return ERR_PTR(ret);
                case 0:
                        break;
                default:
                        pr_err("%s: `%s' invalid for parameter `%s'\n",
                               doing, val ?: "", param);
-                       return ret;
+                       return ERR_PTR(ret);
                }
        }
 
        /* All parsed OK. */
-       return 0;
+       return NULL;
 }
 
 /* Lazy bastard, eh? */
index 86ea0c3ad97511e02a75003dc3c8556990b0e9a9..01562e0d499202a0005c61443f36bdf11a33160c 100644 (file)
@@ -40,8 +40,9 @@ static ssize_t foo_store(struct kobject *kobj, struct kobj_attribute *attr,
        return count;
 }
 
+/* Sysfs attributes cannot be world-writable. */
 static struct kobj_attribute foo_attribute =
-       __ATTR(foo, 0666, foo_show, foo_store);
+       __ATTR(foo, 0664, foo_show, foo_store);
 
 /*
  * More complex function where we determine which variable is being accessed by
@@ -73,9 +74,9 @@ static ssize_t b_store(struct kobject *kobj, struct kobj_attribute *attr,
 }
 
 static struct kobj_attribute baz_attribute =
-       __ATTR(baz, 0666, b_show, b_store);
+       __ATTR(baz, 0664, b_show, b_store);
 static struct kobj_attribute bar_attribute =
-       __ATTR(bar, 0666, b_show, b_store);
+       __ATTR(bar, 0664, b_show, b_store);
 
 
 /*
index 5dce351f131f8c154048124bc1bf3a6a32cb32c7..ab5e447ec23871b66b46049129dfaafc6f3f287d 100644 (file)
@@ -124,8 +124,9 @@ static ssize_t foo_store(struct foo_obj *foo_obj, struct foo_attribute *attr,
        return count;
 }
 
+/* Sysfs attributes cannot be world-writable. */
 static struct foo_attribute foo_attribute =
-       __ATTR(foo, 0666, foo_show, foo_store);
+       __ATTR(foo, 0664, foo_show, foo_store);
 
 /*
  * More complex function where we determine which variable is being accessed by
@@ -157,9 +158,9 @@ static ssize_t b_store(struct foo_obj *foo_obj, struct foo_attribute *attr,
 }
 
 static struct foo_attribute baz_attribute =
-       __ATTR(baz, 0666, b_show, b_store);
+       __ATTR(baz, 0664, b_show, b_store);
 static struct foo_attribute bar_attribute =
-       __ATTR(bar, 0666, b_show, b_store);
+       __ATTR(bar, 0664, b_show, b_store);
 
 /*
  * Create a group of attributes so that we can create and destroy them all
index ea7f9530afa2a3256bbc51e8bc2c4c43039300ca..026543ba8d8687b6218192d5dd4dd212c442e329 100644 (file)
@@ -2113,8 +2113,10 @@ static void read_dump(const char *fname, unsigned int kernel)
                s->preloaded = 1;
                sym_update_crc(symname, mod, crc, export_no(export));
        }
+       release_file(file, size);
        return;
 fail:
+       release_file(file, size);
        fatal("parse error in symbol dump file\n");
 }