diff options
-rw-r--r-- | include/linux/moduleparam.h | 2 | ||||
-rw-r--r-- | init/main.c | 33 | ||||
-rw-r--r-- | kernel/module.c | 12 | ||||
-rw-r--r-- | kernel/params.c | 25 |
4 files changed, 53 insertions, 19 deletions
diff --git a/include/linux/moduleparam.h b/include/linux/moduleparam.h index 204a67743804..b1990c5524e1 100644 --- a/include/linux/moduleparam.h +++ b/include/linux/moduleparam.h | |||
@@ -321,7 +321,7 @@ extern bool parameq(const char *name1, const char *name2); | |||
321 | extern bool parameqn(const char *name1, const char *name2, size_t n); | 321 | extern bool parameqn(const char *name1, const char *name2, size_t n); |
322 | 322 | ||
323 | /* Called on module insert or kernel boot */ | 323 | /* Called on module insert or kernel boot */ |
324 | extern int parse_args(const char *name, | 324 | extern char *parse_args(const char *name, |
325 | char *args, | 325 | char *args, |
326 | const struct kernel_param *params, | 326 | const struct kernel_param *params, |
327 | unsigned num, | 327 | unsigned num, |
diff --git a/init/main.c b/init/main.c index 9c7fd4c9249f..e9d458b5d77b 100644 --- a/init/main.c +++ b/init/main.c | |||
@@ -252,6 +252,27 @@ static int __init repair_env_string(char *param, char *val, const char *unused) | |||
252 | return 0; | 252 | return 0; |
253 | } | 253 | } |
254 | 254 | ||
255 | /* Anything after -- gets handed straight to init. */ | ||
256 | static int __init set_init_arg(char *param, char *val, const char *unused) | ||
257 | { | ||
258 | unsigned int i; | ||
259 | |||
260 | if (panic_later) | ||
261 | return 0; | ||
262 | |||
263 | repair_env_string(param, val, unused); | ||
264 | |||
265 | for (i = 0; argv_init[i]; i++) { | ||
266 | if (i == MAX_INIT_ARGS) { | ||
267 | panic_later = "init"; | ||
268 | panic_param = param; | ||
269 | return 0; | ||
270 | } | ||
271 | } | ||
272 | argv_init[i] = param; | ||
273 | return 0; | ||
274 | } | ||
275 | |||
255 | /* | 276 | /* |
256 | * Unknown boot options get handed to init, unless they look like | 277 | * Unknown boot options get handed to init, unless they look like |
257 | * unused parameters (modprobe will find them in /proc/cmdline). | 278 | * unused parameters (modprobe will find them in /proc/cmdline). |
@@ -478,7 +499,7 @@ static void __init mm_init(void) | |||
478 | 499 | ||
479 | asmlinkage void __init start_kernel(void) | 500 | asmlinkage void __init start_kernel(void) |
480 | { | 501 | { |
481 | char * command_line; | 502 | char * command_line, *after_dashes; |
482 | extern const struct kernel_param __start___param[], __stop___param[]; | 503 | extern const struct kernel_param __start___param[], __stop___param[]; |
483 | 504 | ||
484 | /* | 505 | /* |
@@ -519,9 +540,13 @@ asmlinkage void __init start_kernel(void) | |||
519 | 540 | ||
520 | pr_notice("Kernel command line: %s\n", boot_command_line); | 541 | pr_notice("Kernel command line: %s\n", boot_command_line); |
521 | parse_early_param(); | 542 | parse_early_param(); |
522 | parse_args("Booting kernel", static_command_line, __start___param, | 543 | after_dashes = parse_args("Booting kernel", |
523 | __stop___param - __start___param, | 544 | static_command_line, __start___param, |
524 | -1, -1, &unknown_bootoption); | 545 | __stop___param - __start___param, |
546 | -1, -1, &unknown_bootoption); | ||
547 | if (after_dashes) | ||
548 | parse_args("Setting init args", after_dashes, NULL, 0, -1, -1, | ||
549 | set_init_arg); | ||
525 | 550 | ||
526 | jump_label_init(); | 551 | jump_label_init(); |
527 | 552 | ||
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? */ |