diff options
Diffstat (limited to 'kernel/kmod.c')
| -rw-r--r-- | kernel/kmod.c | 98 | 
1 files changed, 50 insertions, 48 deletions
| diff --git a/kernel/kmod.c b/kernel/kmod.c index 56dd34976d7..1296e72e416 100644 --- a/kernel/kmod.c +++ b/kernel/kmod.c @@ -77,6 +77,7 @@ static void free_modprobe_argv(struct subprocess_info *info)  static int call_modprobe(char *module_name, int wait)  { +	struct subprocess_info *info;  	static char *envp[] = {  		"HOME=/",  		"TERM=linux", @@ -98,8 +99,15 @@ static int call_modprobe(char *module_name, int wait)  	argv[3] = module_name;	/* check free_modprobe_argv() */  	argv[4] = NULL; -	return call_usermodehelper_fns(modprobe_path, argv, envp, -		wait | UMH_KILLABLE, NULL, free_modprobe_argv, NULL); +	info = call_usermodehelper_setup(modprobe_path, argv, envp, GFP_KERNEL, +					 NULL, free_modprobe_argv, NULL); +	if (!info) +		goto free_module_name; + +	return call_usermodehelper_exec(info, wait | UMH_KILLABLE); + +free_module_name: +	kfree(module_name);  free_argv:  	kfree(argv);  out: @@ -502,14 +510,28 @@ static void helper_unlock(void)   * @argv: arg vector for process   * @envp: environment for process   * @gfp_mask: gfp mask for memory allocation + * @cleanup: a cleanup function + * @init: an init function + * @data: arbitrary context sensitive data   *   * Returns either %NULL on allocation failure, or a subprocess_info   * structure.  This should be passed to call_usermodehelper_exec to   * exec the process and free the structure. + * + * The init function is used to customize the helper process prior to + * exec.  A non-zero return code causes the process to error out, exit, + * and return the failure to the calling process + * + * The cleanup function is just before ethe subprocess_info is about to + * be freed.  This can be used for freeing the argv and envp.  The + * Function must be runnable in either a process context or the + * context in which call_usermodehelper_exec is called.   */ -static  struct subprocess_info *call_usermodehelper_setup(char *path, char **argv, -						  char **envp, gfp_t gfp_mask) +		char **envp, gfp_t gfp_mask, +		int (*init)(struct subprocess_info *info, struct cred *new), +		void (*cleanup)(struct subprocess_info *info), +		void *data)  {  	struct subprocess_info *sub_info;  	sub_info = kzalloc(sizeof(struct subprocess_info), gfp_mask); @@ -520,50 +542,27 @@ struct subprocess_info *call_usermodehelper_setup(char *path, char **argv,  	sub_info->path = path;  	sub_info->argv = argv;  	sub_info->envp = envp; + +	sub_info->cleanup = cleanup; +	sub_info->init = init; +	sub_info->data = data;    out:  	return sub_info;  } - -/** - * call_usermodehelper_setfns - set a cleanup/init function - * @info: a subprocess_info returned by call_usermodehelper_setup - * @cleanup: a cleanup function - * @init: an init function - * @data: arbitrary context sensitive data - * - * The init function is used to customize the helper process prior to - * exec.  A non-zero return code causes the process to error out, exit, - * and return the failure to the calling process - * - * The cleanup function is just before ethe subprocess_info is about to - * be freed.  This can be used for freeing the argv and envp.  The - * Function must be runnable in either a process context or the - * context in which call_usermodehelper_exec is called. - */ -static -void call_usermodehelper_setfns(struct subprocess_info *info, -		    int (*init)(struct subprocess_info *info, struct cred *new), -		    void (*cleanup)(struct subprocess_info *info), -		    void *data) -{ -	info->cleanup = cleanup; -	info->init = init; -	info->data = data; -} +EXPORT_SYMBOL(call_usermodehelper_setup);  /**   * call_usermodehelper_exec - start a usermode application   * @sub_info: information about the subprocessa   * @wait: wait for the application to finish and return status. - *        when -1 don't wait at all, but you get no useful error back when - *        the program couldn't be exec'ed. This makes it safe to call + *        when UMH_NO_WAIT don't wait at all, but you get no useful error back + *        when the program couldn't be exec'ed. This makes it safe to call   *        from interrupt context.   *   * Runs a user-space application.  The application is started   * asynchronously if wait is not set, and runs as a child of keventd.   * (ie. it runs with full root capabilities).   */ -static  int call_usermodehelper_exec(struct subprocess_info *sub_info, int wait)  {  	DECLARE_COMPLETION_ONSTACK(done); @@ -615,31 +614,34 @@ unlock:  	helper_unlock();  	return retval;  } +EXPORT_SYMBOL(call_usermodehelper_exec); -/* - * call_usermodehelper_fns() will not run the caller-provided cleanup function - * if a memory allocation failure is experienced.  So the caller might need to - * check the call_usermodehelper_fns() return value: if it is -ENOMEM, perform - * the necessaary cleanup within the caller. +/** + * call_usermodehelper() - prepare and start a usermode application + * @path: path to usermode executable + * @argv: arg vector for process + * @envp: environment for process + * @wait: wait for the application to finish and return status. + *        when UMH_NO_WAIT don't wait at all, but you get no useful error back + *        when the program couldn't be exec'ed. This makes it safe to call + *        from interrupt context. + * + * This function is the equivalent to use call_usermodehelper_setup() and + * call_usermodehelper_exec().   */ -int call_usermodehelper_fns( -	char *path, char **argv, char **envp, int wait, -	int (*init)(struct subprocess_info *info, struct cred *new), -	void (*cleanup)(struct subprocess_info *), void *data) +int call_usermodehelper(char *path, char **argv, char **envp, int wait)  {  	struct subprocess_info *info;  	gfp_t gfp_mask = (wait == UMH_NO_WAIT) ? GFP_ATOMIC : GFP_KERNEL; -	info = call_usermodehelper_setup(path, argv, envp, gfp_mask); - +	info = call_usermodehelper_setup(path, argv, envp, gfp_mask, +					 NULL, NULL, NULL);  	if (info == NULL)  		return -ENOMEM; -	call_usermodehelper_setfns(info, init, cleanup, data); -  	return call_usermodehelper_exec(info, wait);  } -EXPORT_SYMBOL(call_usermodehelper_fns); +EXPORT_SYMBOL(call_usermodehelper);  static int proc_cap_handler(struct ctl_table *table, int write,  			 void __user *buffer, size_t *lenp, loff_t *ppos) | 
