|
@@ -116,27 +116,16 @@ int __request_module(bool wait, const char *fmt, ...)
|
|
|
|
|
|
trace_module_request(module_name, wait, _RET_IP_);
|
|
|
|
|
|
- ret = call_usermodehelper(modprobe_path, argv, envp,
|
|
|
- wait ? UMH_WAIT_PROC : UMH_WAIT_EXEC);
|
|
|
+ ret = call_usermodehelper_fns(modprobe_path, argv, envp,
|
|
|
+ wait ? UMH_WAIT_PROC : UMH_WAIT_EXEC,
|
|
|
+ NULL, NULL, NULL);
|
|
|
+
|
|
|
atomic_dec(&kmod_concurrent);
|
|
|
return ret;
|
|
|
}
|
|
|
EXPORT_SYMBOL(__request_module);
|
|
|
#endif /* CONFIG_MODULES */
|
|
|
|
|
|
-struct subprocess_info {
|
|
|
- struct work_struct work;
|
|
|
- struct completion *complete;
|
|
|
- struct cred *cred;
|
|
|
- char *path;
|
|
|
- char **argv;
|
|
|
- char **envp;
|
|
|
- enum umh_wait wait;
|
|
|
- int retval;
|
|
|
- struct file *stdin;
|
|
|
- void (*cleanup)(char **argv, char **envp);
|
|
|
-};
|
|
|
-
|
|
|
/*
|
|
|
* This is the task which runs the usermode application
|
|
|
*/
|
|
@@ -184,9 +173,16 @@ static int ____call_usermodehelper(void *data)
|
|
|
*/
|
|
|
set_user_nice(current, 0);
|
|
|
|
|
|
+ if (sub_info->init) {
|
|
|
+ retval = sub_info->init(sub_info);
|
|
|
+ if (retval)
|
|
|
+ goto fail;
|
|
|
+ }
|
|
|
+
|
|
|
retval = kernel_execve(sub_info->path, sub_info->argv, sub_info->envp);
|
|
|
|
|
|
/* Exec failed? */
|
|
|
+fail:
|
|
|
sub_info->retval = retval;
|
|
|
do_exit(0);
|
|
|
}
|
|
@@ -194,7 +190,7 @@ static int ____call_usermodehelper(void *data)
|
|
|
void call_usermodehelper_freeinfo(struct subprocess_info *info)
|
|
|
{
|
|
|
if (info->cleanup)
|
|
|
- (*info->cleanup)(info->argv, info->envp);
|
|
|
+ (*info->cleanup)(info);
|
|
|
if (info->cred)
|
|
|
put_cred(info->cred);
|
|
|
kfree(info);
|
|
@@ -406,21 +402,31 @@ void call_usermodehelper_setkeys(struct subprocess_info *info,
|
|
|
EXPORT_SYMBOL(call_usermodehelper_setkeys);
|
|
|
|
|
|
/**
|
|
|
- * call_usermodehelper_setcleanup - set a cleanup function
|
|
|
+ * 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 befor ethe subprocess_info is about to
|
|
|
+ * 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.
|
|
|
*/
|
|
|
-void call_usermodehelper_setcleanup(struct subprocess_info *info,
|
|
|
- void (*cleanup)(char **argv, char **envp))
|
|
|
+void call_usermodehelper_setfns(struct subprocess_info *info,
|
|
|
+ int (*init)(struct subprocess_info *info),
|
|
|
+ void (*cleanup)(struct subprocess_info *info),
|
|
|
+ void *data)
|
|
|
{
|
|
|
info->cleanup = cleanup;
|
|
|
+ info->init = init;
|
|
|
+ info->data = data;
|
|
|
}
|
|
|
-EXPORT_SYMBOL(call_usermodehelper_setcleanup);
|
|
|
+EXPORT_SYMBOL(call_usermodehelper_setfns);
|
|
|
|
|
|
/**
|
|
|
* call_usermodehelper_stdinpipe - set up a pipe to be used for stdin
|
|
@@ -515,7 +521,8 @@ int call_usermodehelper_pipe(char *path, char **argv, char **envp,
|
|
|
struct subprocess_info *sub_info;
|
|
|
int ret;
|
|
|
|
|
|
- sub_info = call_usermodehelper_setup(path, argv, envp, GFP_KERNEL);
|
|
|
+ sub_info = call_usermodehelper_setup(path, argv, envp,
|
|
|
+ GFP_KERNEL);
|
|
|
if (sub_info == NULL)
|
|
|
return -ENOMEM;
|
|
|
|