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>
	
	
This commit is contained in:
		
					parent
					
						
							
								2ee41e62ba
							
						
					
				
			
			
				commit
				
					
						51e158c12a
					
				
			
		
					 4 changed files with 53 additions and 19 deletions
				
			
		|  | @ -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); | extern bool parameqn(const char *name1, const char *name2, size_t n); | ||||||
| 
 | 
 | ||||||
| /* Called on module insert or kernel boot */ | /* Called on module insert or kernel boot */ | ||||||
| extern int parse_args(const char *name, | extern char *parse_args(const char *name, | ||||||
| 		      char *args, | 		      char *args, | ||||||
| 		      const struct kernel_param *params, | 		      const struct kernel_param *params, | ||||||
| 		      unsigned num, | 		      unsigned num, | ||||||
|  |  | ||||||
							
								
								
									
										33
									
								
								init/main.c
									
										
									
									
									
								
							
							
						
						
									
										33
									
								
								init/main.c
									
										
									
									
									
								
							|  | @ -252,6 +252,27 @@ static int __init repair_env_string(char *param, char *val, const char *unused) | ||||||
| 	return 0; | 	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 |  * Unknown boot options get handed to init, unless they look like | ||||||
|  * unused parameters (modprobe will find them in /proc/cmdline). |  * unused parameters (modprobe will find them in /proc/cmdline). | ||||||
|  | @ -478,7 +499,7 @@ static void __init mm_init(void) | ||||||
| 
 | 
 | ||||||
| asmlinkage void __init start_kernel(void) | asmlinkage void __init start_kernel(void) | ||||||
| { | { | ||||||
| 	char * command_line; | 	char * command_line, *after_dashes; | ||||||
| 	extern const struct kernel_param __start___param[], __stop___param[]; | 	extern const struct kernel_param __start___param[], __stop___param[]; | ||||||
| 
 | 
 | ||||||
| 	/*
 | 	/*
 | ||||||
|  | @ -519,9 +540,13 @@ asmlinkage void __init start_kernel(void) | ||||||
| 
 | 
 | ||||||
| 	pr_notice("Kernel command line: %s\n", boot_command_line); | 	pr_notice("Kernel command line: %s\n", boot_command_line); | ||||||
| 	parse_early_param(); | 	parse_early_param(); | ||||||
| 	parse_args("Booting kernel", static_command_line, __start___param, | 	after_dashes = parse_args("Booting kernel", | ||||||
| 		   __stop___param - __start___param, | 				  static_command_line, __start___param, | ||||||
| 		   -1, -1, &unknown_bootoption); | 				  __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(); | 	jump_label_init(); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -3193,6 +3193,7 @@ static int load_module(struct load_info *info, const char __user *uargs, | ||||||
| { | { | ||||||
| 	struct module *mod; | 	struct module *mod; | ||||||
| 	long err; | 	long err; | ||||||
|  | 	char *after_dashes; | ||||||
| 
 | 
 | ||||||
| 	err = module_sig_check(info); | 	err = module_sig_check(info); | ||||||
| 	if (err) | 	if (err) | ||||||
|  | @ -3277,10 +3278,15 @@ static int load_module(struct load_info *info, const char __user *uargs, | ||||||
| 		goto ddebug_cleanup; | 		goto ddebug_cleanup; | ||||||
| 
 | 
 | ||||||
| 	/* Module is ready to execute: parsing args may do that. */ | 	/* Module is ready to execute: parsing args may do that. */ | ||||||
| 	err = parse_args(mod->name, mod->args, mod->kp, mod->num_kp, | 	after_dashes = parse_args(mod->name, mod->args, mod->kp, mod->num_kp, | ||||||
| 			 -32768, 32767, unknown_module_param_cb); | 				  -32768, 32767, unknown_module_param_cb); | ||||||
| 	if (err < 0) | 	if (IS_ERR(after_dashes)) { | ||||||
|  | 		err = PTR_ERR(after_dashes); | ||||||
| 		goto bug_cleanup; | 		goto bug_cleanup; | ||||||
|  | 	} else if (after_dashes) { | ||||||
|  | 		pr_warn("%s: parameters '%s' after `--' ignored\n", | ||||||
|  | 		       mod->name, after_dashes); | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	/* Link in to syfs. */ | 	/* Link in to syfs. */ | ||||||
| 	err = mod_sysfs_setup(mod, info, mod->kp, mod->num_kp); | 	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". */ | /* Args looks like "foo=bar,bar2 baz=fuz wiz". */ | ||||||
| int parse_args(const char *doing, | char *parse_args(const char *doing, | ||||||
| 	       char *args, | 		 char *args, | ||||||
| 	       const struct kernel_param *params, | 		 const struct kernel_param *params, | ||||||
| 	       unsigned num, | 		 unsigned num, | ||||||
| 	       s16 min_level, | 		 s16 min_level, | ||||||
| 	       s16 max_level, | 		 s16 max_level, | ||||||
| 	       int (*unknown)(char *param, char *val, const char *doing)) | 		 int (*unknown)(char *param, char *val, const char *doing)) | ||||||
| { | { | ||||||
| 	char *param, *val; | 	char *param, *val; | ||||||
| 
 | 
 | ||||||
|  | @ -198,6 +198,9 @@ int parse_args(const char *doing, | ||||||
| 		int irq_was_disabled; | 		int irq_was_disabled; | ||||||
| 
 | 
 | ||||||
| 		args = next_arg(args, ¶m, &val); | 		args = next_arg(args, ¶m, &val); | ||||||
|  | 		/* Stop at -- */ | ||||||
|  | 		if (!val && strcmp(param, "--") == 0) | ||||||
|  | 			return args; | ||||||
| 		irq_was_disabled = irqs_disabled(); | 		irq_was_disabled = irqs_disabled(); | ||||||
| 		ret = parse_one(param, val, doing, params, num, | 		ret = parse_one(param, val, doing, params, num, | ||||||
| 				min_level, max_level, unknown); | 				min_level, max_level, unknown); | ||||||
|  | @ -208,22 +211,22 @@ int parse_args(const char *doing, | ||||||
| 		switch (ret) { | 		switch (ret) { | ||||||
| 		case -ENOENT: | 		case -ENOENT: | ||||||
| 			pr_err("%s: Unknown parameter `%s'\n", doing, param); | 			pr_err("%s: Unknown parameter `%s'\n", doing, param); | ||||||
| 			return ret; | 			return ERR_PTR(ret); | ||||||
| 		case -ENOSPC: | 		case -ENOSPC: | ||||||
| 			pr_err("%s: `%s' too large for parameter `%s'\n", | 			pr_err("%s: `%s' too large for parameter `%s'\n", | ||||||
| 			       doing, val ?: "", param); | 			       doing, val ?: "", param); | ||||||
| 			return ret; | 			return ERR_PTR(ret); | ||||||
| 		case 0: | 		case 0: | ||||||
| 			break; | 			break; | ||||||
| 		default: | 		default: | ||||||
| 			pr_err("%s: `%s' invalid for parameter `%s'\n", | 			pr_err("%s: `%s' invalid for parameter `%s'\n", | ||||||
| 			       doing, val ?: "", param); | 			       doing, val ?: "", param); | ||||||
| 			return ret; | 			return ERR_PTR(ret); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/* All parsed OK. */ | 	/* All parsed OK. */ | ||||||
| 	return 0; | 	return NULL; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /* Lazy bastard, eh? */ | /* Lazy bastard, eh? */ | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Rusty Russell
				Rusty Russell