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(). Cheers, Rusty. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJTl+oJAAoJENkgDmzRrbjxtUEP/jIXml01jE2HquOJ/DfrCJOt ry5L5Iy8wVBRotTszrXqlD6+W8fLYsEdhM65Wof1H7X1qjaulqYZmrL7bQn4rIGN YPUmO5rOzECeAPNW5+e2JLnR4bmS99gVcWzJFCHUBd7Z8ceKaoIk7/XvUg6Mdjg7 v0kJ5X+U9da2sVYYcZ71euth4ADLFDRNRexA1mPI6mKzJLOBgfvCBWZnkFVdBcjd VmL6ceFo/yP9Ed4pgG/4uXq1dZ4ZttpjPusDmNcjq+snOzsQb4tW+KB2Pr6iTwQy TDt7lQm5+xfUXgUG/S5L6PYn10P44Voo7AEJa+QK5YPSOY/eRVA0h4/ayP0vqDaJ LpZjqXbW77G4yOgEV9KRFLLXiFXykTh2TyCPYL5G2XVXQp1OmViu2f21JWJLFLgL mqOXYWdowOGVOOoTgwxIdxczCFCATJUaU5Ig6ay8C02E2mCwIV+IaGSdpsCiyjz/ dNNumMxWg0NMo/c0YG4K3Ake6ZaGrwbnuJYijaEj6mgpifhh7k4yhFciXGLpkLnS Yuo4ORO0GX34z1+bX0iwrgMGPdy7+BnbXsDdWJsbsnwnKKes/Sp44fNl4lPwdM3n siaPsxmfAtl9EGqbkU1Fk+x5+X/Lv2I/7/nX5n53520RLkJJpbeMDfHUqpbrqeUN JNUTOZ9o72EqDVKnn175 =IxSN -----END PGP SIGNATURE----- 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()
This commit is contained in:
Коммит
4251c2a670
|
@ -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.
|
||||
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.
|
||||
|
||||
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
|
||||
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.
|
||||
|
||||
modprobe usbcore blinkenlights=1
|
||||
Module parameters can be specified in two ways: via the kernel command
|
||||
line with a module name prefix, or via modprobe, e.g.:
|
||||
|
||||
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:
|
||||
(kernel command line) usbcore.blinkenlights=1
|
||||
(modprobe command line) modprobe usbcore blinkenlights=1
|
||||
|
||||
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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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] = {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
*
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
33
init/main.c
33
init/main.c
|
@ -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();
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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, ¶m, &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? */
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
||||
/*
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче