diff options
author | Rusty Russell <rusty@rustcorp.com.au> | 2014-04-27 22:04:33 -0400 |
---|---|---|
committer | Rusty Russell <rusty@rustcorp.com.au> | 2014-04-27 22:18:34 -0400 |
commit | 51e158c12aca3c9ac63988611a97c05109b14dc9 (patch) | |
tree | 579ef4259a17200a77ec111c6a6ca082d43a368d /kernel | |
parent | 2ee41e62ba5b952e9d9fcba6f7079a0c608bb849 (diff) |
param: hand arguments after -- straight to init
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 <rusty@rustcorp.com.au>
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/module.c | 12 | ||||
-rw-r--r-- | kernel/params.c | 25 |
2 files changed, 23 insertions, 14 deletions
diff --git a/kernel/module.c b/kernel/module.c index 11869408f79b..66e4e0d260a9 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
@@ -3193,6 +3193,7 @@ static int load_module(struct load_info *info, const char __user *uargs, | |||
3193 | { | 3193 | { |
3194 | struct module *mod; | 3194 | struct module *mod; |
3195 | long err; | 3195 | long err; |
3196 | char *after_dashes; | ||
3196 | 3197 | ||
3197 | err = module_sig_check(info); | 3198 | err = module_sig_check(info); |
3198 | if (err) | 3199 | if (err) |
@@ -3277,10 +3278,15 @@ static int load_module(struct load_info *info, const char __user *uargs, | |||
3277 | goto ddebug_cleanup; | 3278 | goto ddebug_cleanup; |
3278 | 3279 | ||
3279 | /* Module is ready to execute: parsing args may do that. */ | 3280 | /* Module is ready to execute: parsing args may do that. */ |
3280 | err = parse_args(mod->name, mod->args, mod->kp, mod->num_kp, | 3281 | after_dashes = parse_args(mod->name, mod->args, mod->kp, mod->num_kp, |
3281 | -32768, 32767, unknown_module_param_cb); | 3282 | -32768, 32767, unknown_module_param_cb); |
3282 | if (err < 0) | 3283 | if (IS_ERR(after_dashes)) { |
3284 | err = PTR_ERR(after_dashes); | ||
3283 | goto bug_cleanup; | 3285 | goto bug_cleanup; |
3286 | } else if (after_dashes) { | ||
3287 | pr_warn("%s: parameters '%s' after `--' ignored\n", | ||
3288 | mod->name, after_dashes); | ||
3289 | } | ||
3284 | 3290 | ||
3285 | /* Link in to syfs. */ | 3291 | /* Link in to syfs. */ |
3286 | err = mod_sysfs_setup(mod, info, mod->kp, mod->num_kp); | 3292 | err = mod_sysfs_setup(mod, info, mod->kp, mod->num_kp); |
diff --git a/kernel/params.c b/kernel/params.c index b00142e7f3ba..1e52ca233fd9 100644 --- a/kernel/params.c +++ b/kernel/params.c | |||
@@ -177,13 +177,13 @@ static char *next_arg(char *args, char **param, char **val) | |||
177 | } | 177 | } |
178 | 178 | ||
179 | /* Args looks like "foo=bar,bar2 baz=fuz wiz". */ | 179 | /* Args looks like "foo=bar,bar2 baz=fuz wiz". */ |
180 | int parse_args(const char *doing, | 180 | char *parse_args(const char *doing, |
181 | char *args, | 181 | char *args, |
182 | const struct kernel_param *params, | 182 | const struct kernel_param *params, |
183 | unsigned num, | 183 | unsigned num, |
184 | s16 min_level, | 184 | s16 min_level, |
185 | s16 max_level, | 185 | s16 max_level, |
186 | int (*unknown)(char *param, char *val, const char *doing)) | 186 | int (*unknown)(char *param, char *val, const char *doing)) |
187 | { | 187 | { |
188 | char *param, *val; | 188 | char *param, *val; |
189 | 189 | ||
@@ -198,6 +198,9 @@ int parse_args(const char *doing, | |||
198 | int irq_was_disabled; | 198 | int irq_was_disabled; |
199 | 199 | ||
200 | args = next_arg(args, ¶m, &val); | 200 | args = next_arg(args, ¶m, &val); |
201 | /* Stop at -- */ | ||
202 | if (!val && strcmp(param, "--") == 0) | ||
203 | return args; | ||
201 | irq_was_disabled = irqs_disabled(); | 204 | irq_was_disabled = irqs_disabled(); |
202 | ret = parse_one(param, val, doing, params, num, | 205 | ret = parse_one(param, val, doing, params, num, |
203 | min_level, max_level, unknown); | 206 | min_level, max_level, unknown); |
@@ -208,22 +211,22 @@ int parse_args(const char *doing, | |||
208 | switch (ret) { | 211 | switch (ret) { |
209 | case -ENOENT: | 212 | case -ENOENT: |
210 | pr_err("%s: Unknown parameter `%s'\n", doing, param); | 213 | pr_err("%s: Unknown parameter `%s'\n", doing, param); |
211 | return ret; | 214 | return ERR_PTR(ret); |
212 | case -ENOSPC: | 215 | case -ENOSPC: |
213 | pr_err("%s: `%s' too large for parameter `%s'\n", | 216 | pr_err("%s: `%s' too large for parameter `%s'\n", |
214 | doing, val ?: "", param); | 217 | doing, val ?: "", param); |
215 | return ret; | 218 | return ERR_PTR(ret); |
216 | case 0: | 219 | case 0: |
217 | break; | 220 | break; |
218 | default: | 221 | default: |
219 | pr_err("%s: `%s' invalid for parameter `%s'\n", | 222 | pr_err("%s: `%s' invalid for parameter `%s'\n", |
220 | doing, val ?: "", param); | 223 | doing, val ?: "", param); |
221 | return ret; | 224 | return ERR_PTR(ret); |
222 | } | 225 | } |
223 | } | 226 | } |
224 | 227 | ||
225 | /* All parsed OK. */ | 228 | /* All parsed OK. */ |
226 | return 0; | 229 | return NULL; |
227 | } | 230 | } |
228 | 231 | ||
229 | /* Lazy bastard, eh? */ | 232 | /* Lazy bastard, eh? */ |