BugLink: http://bugs.launchpad.net/bugs/586386
Some init packages such as upstart find having all of the kernel parameters
passed in useful. Currently they have to open up /proc/cmdline and
reparse that to obtain this information. Add a kernel configuration
option to enable passing of all options.
Note, enabling this option will reduce the chances that a fallback from
/sbin/init to /bin/bash or /bin/sh will succeed. Though it should be
noted that there are commonly unknown options present which would already
break this fallback. init=/bin/foo provides explicit control over options
which is unaffected by this change.
Signed-off-by: Andy Whitcroft <apw@canonical.com>
Signed-off-by: Leann Ogasawara <leann.ogasawara@canonical.com>
char *args,
const struct kernel_param *params,
unsigned num,
char *args,
const struct kernel_param *params,
unsigned num,
- int (*unknown)(char *param, char *val));
+ int (*handle)(char *param, char *val, int known));
/* Called by module remove. */
#ifdef CONFIG_SYSFS
/* Called by module remove. */
#ifdef CONFIG_SYSFS
Maximum of each of the number of arguments and environment
variables passed to init from the kernel command line.
Maximum of each of the number of arguments and environment
variables passed to init from the kernel command line.
+config INIT_PASS_ALL_PARAMS
+ bool "Pass all (known and unknown) kernel parameters to init"
+ default n
+ help
+ Pass all kernel command line parameters to init, this includes
+ those consumed by kernel modules. This is useful for upstart
+ based systems. If in doubt say N.
config CROSS_COMPILE
string "Cross-compiler tool prefix"
config CROSS_COMPILE
string "Cross-compiler tool prefix"
*/
#define MAX_INIT_ARGS CONFIG_INIT_ENV_ARG_LIMIT
#define MAX_INIT_ENVS CONFIG_INIT_ENV_ARG_LIMIT
*/
#define MAX_INIT_ARGS CONFIG_INIT_ENV_ARG_LIMIT
#define MAX_INIT_ENVS CONFIG_INIT_ENV_ARG_LIMIT
+#ifdef CONFIG_INIT_PASS_ALL_PARAMS
+#define INIT_PASS_FUNCTION pass_all_bootoptions
+#else
+#define INIT_PASS_FUNCTION pass_unknown_bootoptions
+#endif
extern void time_init(void);
/* Default late time init is NULL. archs can override this later. */
extern void time_init(void);
/* Default late time init is NULL. archs can override this later. */
early_param("loglevel", loglevel);
/*
early_param("loglevel", loglevel);
/*
- * Unknown boot options get handed to init, unless they look like
- * unused parameters (modprobe will find them in /proc/cmdline).
+ * Select boot options to hand to init. If all is set hand off them all
+ * otherwise only hand off unused ones which do not apply to modules
+ * (modprobe will find them in /proc/cmdline).
-static int __init unknown_bootoption(char *param, char *val)
+static int __init pass_bootoption(char *param, char *val, int all)
{
/* Change NUL term back to "=", to make "param" the whole string. */
if (val) {
{
/* Change NUL term back to "=", to make "param" the whole string. */
if (val) {
}
/* Handle obsolete-style parameters */
}
/* Handle obsolete-style parameters */
- if (obsolete_checksetup(param))
+ if (obsolete_checksetup(param) && !all)
return 0;
/* Unused module parameter. */
return 0;
/* Unused module parameter. */
- if (strchr(param, '.') && (!val || strchr(param, '.') < val))
+ if (!all && strchr(param, '.') && (!val || strchr(param, '.') < val))
return 0;
if (panic_later)
return 0;
if (panic_later)
+static int __init pass_unknown_bootoptions(char *param, char *val, int known)
+{
+ if (known)
+ return 0;
+ return pass_bootoption(param, val, 0);
+}
+static int __init pass_all_bootoptions(char *param, char *val, int known)
+{
+ return pass_bootoption(param, val, 1);
+}
#ifdef CONFIG_DEBUG_PAGEALLOC
int __read_mostly debug_pagealloc_enabled = 0;
#ifdef CONFIG_DEBUG_PAGEALLOC
int __read_mostly debug_pagealloc_enabled = 0;
}
/* Check for early params. */
}
/* Check for early params. */
-static int __init do_early_param(char *param, char *val)
+static int __init do_early_param(char *param, char *val, int known)
{
const struct obs_kernel_param *p;
{
const struct obs_kernel_param *p;
+ if (known)
+ return 0;
+
for (p = __setup_start; p < __setup_end; p++) {
if ((p->early && strcmp(param, p->str) == 0) ||
(strcmp(param, "console") == 0 &&
for (p = __setup_start; p < __setup_end; p++) {
if ((p->early && strcmp(param, p->str) == 0) ||
(strcmp(param, "console") == 0 &&
parse_early_param();
parse_args("Booting kernel", static_command_line, __start___param,
__stop___param - __start___param,
parse_early_param();
parse_args("Booting kernel", static_command_line, __start___param,
__stop___param - __start___param,
/*
* These use large bootmem allocations and must precede
* kmem_cache_init()
/*
* These use large bootmem allocations and must precede
* kmem_cache_init()
char *val,
const struct kernel_param *params,
unsigned num_params,
char *val,
const struct kernel_param *params,
unsigned num_params,
- int (*handle_unknown)(char *param, char *val))
+ int (*handle_arg)(char *param, char *val, int known))
{
unsigned int i;
int err;
{
unsigned int i;
int err;
/* Noone handled NULL, so do it here. */
if (!val && params[i].ops->set != param_set_bool)
return -EINVAL;
/* Noone handled NULL, so do it here. */
if (!val && params[i].ops->set != param_set_bool)
return -EINVAL;
+ if (handle_arg) {
+ int ret;
+ DEBUGP("Valid argument: calling %p\n",
+ handle_arg);
+ ret = handle_arg(param, val, 1);
+ if (ret)
+ return ret;
+ }
DEBUGP("They are equal! Calling %p\n",
params[i].ops->set);
mutex_lock(¶m_lock);
DEBUGP("They are equal! Calling %p\n",
params[i].ops->set);
mutex_lock(¶m_lock);
- if (handle_unknown) {
- DEBUGP("Unknown argument: calling %p\n", handle_unknown);
- return handle_unknown(param, val);
+ if (handle_arg) {
+ DEBUGP("Unknown argument: calling %p\n", handle_arg);
+ return handle_arg(param, val, 0);
}
DEBUGP("Unknown argument `%s'\n", param);
}
DEBUGP("Unknown argument `%s'\n", param);
char *args,
const struct kernel_param *params,
unsigned num,
char *args,
const struct kernel_param *params,
unsigned num,
- int (*unknown)(char *param, char *val))
+ int (*handle_arg)(char *param, char *val, int arg))
args = next_arg(args, ¶m, &val);
irq_was_disabled = irqs_disabled();
args = next_arg(args, ¶m, &val);
irq_was_disabled = irqs_disabled();
- ret = parse_one(param, val, params, num, unknown);
+ ret = parse_one(param, val, params, num, handle_arg);
if (irq_was_disabled && !irqs_disabled()) {
printk(KERN_WARNING "parse_args(): option '%s' enabled "
"irq's!\n", param);
if (irq_was_disabled && !irqs_disabled()) {
printk(KERN_WARNING "parse_args(): option '%s' enabled "
"irq's!\n", param);