Commit 4251c2a6 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'modules-next-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux

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()
parents c31c24b8 4982223e
Kernel Parameters Kernel Parameters
~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~
The following is a consolidated list of the kernel parameters as implemented The following is a consolidated list of the kernel parameters as
(mostly) by the __setup() macro and sorted into English Dictionary order implemented by the __setup(), core_param() and module_param() macros
(defined as ignoring all punctuation and sorting digits before letters in a and sorted into English Dictionary order (defined as ignoring all
case insensitive manner), and with descriptions where known. 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: 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
modprobe usbcore blinkenlights=1 parameter gets passed to init: parameters with '=' go into init's
environment, others are passed as command line arguments to init.
Module parameters for modules that are built into the kernel image Everything after "--" is passed as an argument to init.
are specified on the kernel command line with the module name plus
'.' plus parameter name, with '=' and value if appropriate, such as: Module parameters can be specified in two ways: via the kernel command
line with a module name prefix, or via modprobe, e.g.:
usbcore.blinkenlights=1
(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 Hyphens (dashes) and underscores are equivalent in parameter names, so
log_buf_len=1M print-fatal-signals=1 log_buf_len=1M print-fatal-signals=1
can also be entered as can also be entered as
log-buf-len=1M print_fatal_signals=1 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 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 "modinfo -p ${modulename}" shows a current list of all parameters of a loadable
......
...@@ -52,7 +52,7 @@ static void hid_lg4ff_set_range_g25(struct hid_device *hid, u16 range); ...@@ -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_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 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 { struct lg4ff_device_entry {
__u32 product_id; __u32 product_id;
......
...@@ -501,7 +501,7 @@ static ssize_t picolcd_fb_update_rate_store(struct device *dev, ...@@ -501,7 +501,7 @@ static ssize_t picolcd_fb_update_rate_store(struct device *dev,
return count; 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); picolcd_fb_update_rate_store);
/* initialize Framebuffer device */ /* initialize Framebuffer device */
......
...@@ -1608,8 +1608,8 @@ static ssize_t dps1_insert_key(struct device *dev, ...@@ -1608,8 +1608,8 @@ static ssize_t dps1_insert_key(struct device *dev,
#define FLOOR_SYSFS(id) { \ #define FLOOR_SYSFS(id) { \
__ATTR(f##id##_dps0_is_keylocked, S_IRUGO, dps0_is_key_locked, NULL), \ __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##_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##_dps0_protection_key, S_IWUSR|S_IWGRP, NULL, dps0_insert_key), \
__ATTR(f##id##_dps1_protection_key, S_IWUGO, NULL, dps1_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] = { static struct device_attribute doc_sys_attrs[DOC_MAX_NBFLOORS][4] = {
......
...@@ -266,11 +266,11 @@ static ssize_t set_mode(struct device *dev, struct device_attribute *attr, ...@@ -266,11 +266,11 @@ static ssize_t set_mode(struct device *dev, struct device_attribute *attr,
return count; return count;
} }
static DEVICE_ATTR(min_microvolts, 0666, show_min_uV, set_min_uV); static DEVICE_ATTR(min_microvolts, 0664, show_min_uV, set_min_uV);
static DEVICE_ATTR(max_microvolts, 0666, show_max_uV, set_max_uV); static DEVICE_ATTR(max_microvolts, 0664, show_max_uV, set_max_uV);
static DEVICE_ATTR(min_microamps, 0666, show_min_uA, set_min_uA); static DEVICE_ATTR(min_microamps, 0664, show_min_uA, set_min_uA);
static DEVICE_ATTR(max_microamps, 0666, show_max_uA, set_max_uA); static DEVICE_ATTR(max_microamps, 0664, show_max_uA, set_max_uA);
static DEVICE_ATTR(mode, 0666, show_mode, set_mode); static DEVICE_ATTR(mode, 0664, show_mode, set_mode);
static struct attribute *regulator_virtual_attributes[] = { static struct attribute *regulator_virtual_attributes[] = {
&dev_attr_min_microvolts.attr, &dev_attr_min_microvolts.attr,
......
...@@ -732,7 +732,7 @@ static ssize_t pm8001_show_update_fw(struct device *cdev, ...@@ -732,7 +732,7 @@ static ssize_t pm8001_show_update_fw(struct device *cdev,
flash_error_table[i].reason); 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); pm8001_show_update_fw, pm8001_store_update_fw);
struct device_attribute *pm8001_host_attrs[] = { struct device_attribute *pm8001_host_attrs[] = {
&dev_attr_interface_rev, &dev_attr_interface_rev,
......
...@@ -1215,7 +1215,7 @@ static ssize_t sm501fb_crtsrc_store(struct device *dev, ...@@ -1215,7 +1215,7 @@ static ssize_t sm501fb_crtsrc_store(struct device *dev,
} }
/* Prepare the device_attr for registration with sysfs later */ /* 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 /* sm501fb_show_regs
* *
......
...@@ -600,7 +600,7 @@ static inline int cpulist_scnprintf(char *buf, int len, ...@@ -600,7 +600,7 @@ static inline int cpulist_scnprintf(char *buf, int len,
static inline int cpumask_parse(const char *buf, struct cpumask *dstp) static inline int cpumask_parse(const char *buf, struct cpumask *dstp)
{ {
char *nl = strchr(buf, '\n'); 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); return bitmap_parse(buf, len, cpumask_bits(dstp), nr_cpumask_bits);
} }
......
...@@ -321,7 +321,7 @@ extern bool parameq(const char *name1, const char *name2); ...@@ -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); extern bool parameqn(const char *name1, const char *name2, size_t n);
/* Called on module insert or kernel boot */ /* Called on module insert or kernel boot */
extern int parse_args(const char *name, extern char *parse_args(const char *name,
char *args, char *args,
const struct kernel_param *params, const struct kernel_param *params,
unsigned num, unsigned num,
......
...@@ -253,6 +253,27 @@ static int __init repair_env_string(char *param, char *val, const char *unused) ...@@ -253,6 +253,27 @@ static int __init repair_env_string(char *param, char *val, const char *unused)
return 0; 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 * Unknown boot options get handed to init, unless they look like
* unused parameters (modprobe will find them in /proc/cmdline). * unused parameters (modprobe will find them in /proc/cmdline).
...@@ -479,7 +500,7 @@ static void __init mm_init(void) ...@@ -479,7 +500,7 @@ static void __init mm_init(void)
asmlinkage __visible void __init start_kernel(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[]; extern const struct kernel_param __start___param[], __stop___param[];
/* /*
...@@ -519,9 +540,13 @@ asmlinkage __visible void __init start_kernel(void) ...@@ -519,9 +540,13 @@ asmlinkage __visible void __init start_kernel(void)
pr_notice("Kernel command line: %s\n", boot_command_line); pr_notice("Kernel command line: %s\n", boot_command_line);
parse_early_param(); parse_early_param();
parse_args("Booting kernel", static_command_line, __start___param, after_dashes = parse_args("Booting kernel",
__stop___param - __start___param, static_command_line, __start___param,
-1, -1, &unknown_bootoption); __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(); jump_label_init();
......
...@@ -3020,21 +3020,6 @@ static int do_init_module(struct module *mod) ...@@ -3020,21 +3020,6 @@ static int do_init_module(struct module *mod)
*/ */
current->flags &= ~PF_USED_ASYNC; 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); do_mod_ctors(mod);
/* Start the module */ /* Start the module */
if (mod->init != NULL) if (mod->init != NULL)
...@@ -3165,9 +3150,26 @@ static int complete_formation(struct module *mod, struct load_info *info) ...@@ -3165,9 +3150,26 @@ static int complete_formation(struct module *mod, struct load_info *info)
/* This relies on module_mutex for list integrity. */ /* This relies on module_mutex for list integrity. */
module_bug_finalize(info->hdr, info->sechdrs, mod); 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, /* Mark state as coming so strong_try_module_get() ignores us,
* but kallsyms etc. can see us. */ * but kallsyms etc. can see us. */
mod->state = MODULE_STATE_COMING; mod->state = MODULE_STATE_COMING;
mutex_unlock(&module_mutex);
blocking_notifier_call_chain(&module_notify_list,
MODULE_STATE_COMING, mod);
return 0;
out: out:
mutex_unlock(&module_mutex); mutex_unlock(&module_mutex);
...@@ -3190,6 +3192,7 @@ static int load_module(struct load_info *info, const char __user *uargs, ...@@ -3190,6 +3192,7 @@ static int load_module(struct load_info *info, const char __user *uargs,
{ {
struct module *mod; struct module *mod;
long err; long err;
char *after_dashes;
err = module_sig_check(info); err = module_sig_check(info);
if (err) if (err)
...@@ -3277,10 +3280,15 @@ static int load_module(struct load_info *info, const char __user *uargs, ...@@ -3277,10 +3280,15 @@ static int load_module(struct load_info *info, const char __user *uargs,
goto ddebug_cleanup; goto ddebug_cleanup;
/* Module is ready to execute: parsing args may do that. */ /* Module is ready to execute: parsing args may do that. */
err = parse_args(mod->name, mod->args, mod->kp, mod->num_kp, after_dashes = parse_args(mod->name, mod->args, mod->kp, mod->num_kp,
-32768, 32767, unknown_module_param_cb); -32768, 32767, unknown_module_param_cb);
if (err < 0) if (IS_ERR(after_dashes)) {
err = PTR_ERR(after_dashes);
goto bug_cleanup; goto bug_cleanup;
} else if (after_dashes) {
pr_warn("%s: parameters '%s' after `--' ignored\n",
mod->name, after_dashes);
}
/* Link in to syfs. */ /* Link in to syfs. */
err = mod_sysfs_setup(mod, info, mod->kp, mod->num_kp); err = mod_sysfs_setup(mod, info, mod->kp, mod->num_kp);
......
...@@ -177,13 +177,13 @@ static char *next_arg(char *args, char **param, char **val) ...@@ -177,13 +177,13 @@ static char *next_arg(char *args, char **param, char **val)
} }
/* Args looks like "foo=bar,bar2 baz=fuz wiz". */ /* Args looks like "foo=bar,bar2 baz=fuz wiz". */
int parse_args(const char *doing, char *parse_args(const char *doing,
char *args, char *args,
const struct kernel_param *params, const struct kernel_param *params,
unsigned num, unsigned num,
s16 min_level, s16 min_level,
s16 max_level, s16 max_level,
int (*unknown)(char *param, char *val, const char *doing)) int (*unknown)(char *param, char *val, const char *doing))
{ {
char *param, *val; char *param, *val;
...@@ -198,6 +198,9 @@ int parse_args(const char *doing, ...@@ -198,6 +198,9 @@ int parse_args(const char *doing,
int irq_was_disabled; int irq_was_disabled;
args = next_arg(args, &param, &val); args = next_arg(args, &param, &val);
/* Stop at -- */
if (!val && strcmp(param, "--") == 0)
return args;
irq_was_disabled = irqs_disabled(); irq_was_disabled = irqs_disabled();
ret = parse_one(param, val, doing, params, num, ret = parse_one(param, val, doing, params, num,
min_level, max_level, unknown); min_level, max_level, unknown);
...@@ -208,22 +211,22 @@ int parse_args(const char *doing, ...@@ -208,22 +211,22 @@ int parse_args(const char *doing,
switch (ret) { switch (ret) {
case -ENOENT: case -ENOENT:
pr_err("%s: Unknown parameter `%s'\n", doing, param); pr_err("%s: Unknown parameter `%s'\n", doing, param);
return ret; return ERR_PTR(ret);
case -ENOSPC: case -ENOSPC:
pr_err("%s: `%s' too large for parameter `%s'\n", pr_err("%s: `%s' too large for parameter `%s'\n",
doing, val ?: "", param); doing, val ?: "", param);
return ret; return ERR_PTR(ret);
case 0: case 0:
break; break;
default: default:
pr_err("%s: `%s' invalid for parameter `%s'\n", pr_err("%s: `%s' invalid for parameter `%s'\n",
doing, val ?: "", param); doing, val ?: "", param);
return ret; return ERR_PTR(ret);
} }
} }
/* All parsed OK. */ /* All parsed OK. */
return 0; return NULL;
} }
/* Lazy bastard, eh? */ /* Lazy bastard, eh? */
......
...@@ -40,8 +40,9 @@ static ssize_t foo_store(struct kobject *kobj, struct kobj_attribute *attr, ...@@ -40,8 +40,9 @@ static ssize_t foo_store(struct kobject *kobj, struct kobj_attribute *attr,
return count; return count;
} }
/* Sysfs attributes cannot be world-writable. */
static struct kobj_attribute foo_attribute = 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 * 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, ...@@ -73,9 +74,9 @@ static ssize_t b_store(struct kobject *kobj, struct kobj_attribute *attr,
} }
static struct kobj_attribute baz_attribute = 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 = static struct kobj_attribute bar_attribute =
__ATTR(bar, 0666, b_show, b_store); __ATTR(bar, 0664, b_show, b_store);
/* /*
......
...@@ -124,8 +124,9 @@ static ssize_t foo_store(struct foo_obj *foo_obj, struct foo_attribute *attr, ...@@ -124,8 +124,9 @@ static ssize_t foo_store(struct foo_obj *foo_obj, struct foo_attribute *attr,
return count; return count;
} }
/* Sysfs attributes cannot be world-writable. */
static struct foo_attribute foo_attribute = 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 * 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, ...@@ -157,9 +158,9 @@ static ssize_t b_store(struct foo_obj *foo_obj, struct foo_attribute *attr,
} }
static struct foo_attribute baz_attribute = 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 = 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 * Create a group of attributes so that we can create and destroy them all
......
...@@ -2113,8 +2113,10 @@ static void read_dump(const char *fname, unsigned int kernel) ...@@ -2113,8 +2113,10 @@ static void read_dump(const char *fname, unsigned int kernel)
s->preloaded = 1; s->preloaded = 1;
sym_update_crc(symname, mod, crc, export_no(export)); sym_update_crc(symname, mod, crc, export_no(export));
} }
release_file(file, size);
return; return;
fail: fail:
release_file(file, size);
fatal("parse error in symbol dump file\n"); fatal("parse error in symbol dump file\n");
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment