mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	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,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										29
									
								
								init/main.c
									
									
									
									
									
								
							
							
						
						
									
										29
									
								
								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",
 | 
				
			||||||
 | 
									  static_command_line, __start___param,
 | 
				
			||||||
				  __stop___param - __start___param,
 | 
									  __stop___param - __start___param,
 | 
				
			||||||
				  -1, -1, &unknown_bootoption);
 | 
									  -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,7 +177,7 @@ 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,
 | 
				
			||||||
| 
						 | 
					@ -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…
	
		Reference in a new issue