Skip to content

Commit

Permalink
param: hand arguments after -- straight to init
Browse files Browse the repository at this point in the history
The kernel passes any args it doesn't need through to init, except it
assumes anything containing '.' belongs to the kernel (for a module).
This change means all users can clearly distinguish which arguments
are for init.

For example, the kernel uses debug ("dee-bug") to mean log everything to
the console, where systemd uses the debug from the Scandinavian "day-boog"
meaning "fail to boot".  If a future versions uses argv[] instead of
reading /proc/cmdline, this confusion will be avoided.

eg: test 'FOO="this is --foo"' -- 'systemd.debug="true true true"'

Gives:
argv[0] = '/debug-init'
argv[1] = 'test'
argv[2] = 'systemd.debug=true true true'
envp[0] = 'HOME=/'
envp[1] = 'TERM=linux'
envp[2] = 'FOO=this is --foo'

Signed-off-by: Rusty Russell <[email protected]>
  • Loading branch information
rustyrussell committed Apr 28, 2014
1 parent 2ee41e6 commit 51e158c
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 19 deletions.
2 changes: 1 addition & 1 deletion include/linux/moduleparam.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
33 changes: 29 additions & 4 deletions init/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,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).
Expand Down Expand Up @@ -478,7 +499,7 @@ static void __init mm_init(void)

asmlinkage void __init start_kernel(void)
{
char * command_line;
char * command_line, *after_dashes;
extern const struct kernel_param __start___param[], __stop___param[];

/*
Expand Down Expand Up @@ -519,9 +540,13 @@ asmlinkage 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();

Expand Down
12 changes: 9 additions & 3 deletions kernel/module.c
Original file line number Diff line number Diff line change
Expand Up @@ -3193,6 +3193,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)
Expand Down Expand Up @@ -3277,10 +3278,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);
Expand Down
25 changes: 14 additions & 11 deletions kernel/params.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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);
Expand All @@ -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? */
Expand Down

0 comments on commit 51e158c

Please sign in to comment.