aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/kmod.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/kmod.c')
-rw-r--r--kernel/kmod.c51
1 files changed, 29 insertions, 22 deletions
diff --git a/kernel/kmod.c b/kernel/kmod.c
index bf0e231d9702..531ef62cf536 100644
--- a/kernel/kmod.c
+++ b/kernel/kmod.c
@@ -116,27 +116,16 @@ int __request_module(bool wait, const char *fmt, ...)
116 116
117 trace_module_request(module_name, wait, _RET_IP_); 117 trace_module_request(module_name, wait, _RET_IP_);
118 118
119 ret = call_usermodehelper(modprobe_path, argv, envp, 119 ret = call_usermodehelper_fns(modprobe_path, argv, envp,
120 wait ? UMH_WAIT_PROC : UMH_WAIT_EXEC); 120 wait ? UMH_WAIT_PROC : UMH_WAIT_EXEC,
121 NULL, NULL, NULL);
122
121 atomic_dec(&kmod_concurrent); 123 atomic_dec(&kmod_concurrent);
122 return ret; 124 return ret;
123} 125}
124EXPORT_SYMBOL(__request_module); 126EXPORT_SYMBOL(__request_module);
125#endif /* CONFIG_MODULES */ 127#endif /* CONFIG_MODULES */
126 128
127struct subprocess_info {
128 struct work_struct work;
129 struct completion *complete;
130 struct cred *cred;
131 char *path;
132 char **argv;
133 char **envp;
134 enum umh_wait wait;
135 int retval;
136 struct file *stdin;
137 void (*cleanup)(char **argv, char **envp);
138};
139
140/* 129/*
141 * This is the task which runs the usermode application 130 * This is the task which runs the usermode application
142 */ 131 */
@@ -184,9 +173,16 @@ static int ____call_usermodehelper(void *data)
184 */ 173 */
185 set_user_nice(current, 0); 174 set_user_nice(current, 0);
186 175
176 if (sub_info->init) {
177 retval = sub_info->init(sub_info);
178 if (retval)
179 goto fail;
180 }
181
187 retval = kernel_execve(sub_info->path, sub_info->argv, sub_info->envp); 182 retval = kernel_execve(sub_info->path, sub_info->argv, sub_info->envp);
188 183
189 /* Exec failed? */ 184 /* Exec failed? */
185fail:
190 sub_info->retval = retval; 186 sub_info->retval = retval;
191 do_exit(0); 187 do_exit(0);
192} 188}
@@ -194,7 +190,7 @@ static int ____call_usermodehelper(void *data)
194void call_usermodehelper_freeinfo(struct subprocess_info *info) 190void call_usermodehelper_freeinfo(struct subprocess_info *info)
195{ 191{
196 if (info->cleanup) 192 if (info->cleanup)
197 (*info->cleanup)(info->argv, info->envp); 193 (*info->cleanup)(info);
198 if (info->cred) 194 if (info->cred)
199 put_cred(info->cred); 195 put_cred(info->cred);
200 kfree(info); 196 kfree(info);
@@ -406,21 +402,31 @@ void call_usermodehelper_setkeys(struct subprocess_info *info,
406EXPORT_SYMBOL(call_usermodehelper_setkeys); 402EXPORT_SYMBOL(call_usermodehelper_setkeys);
407 403
408/** 404/**
409 * call_usermodehelper_setcleanup - set a cleanup function 405 * call_usermodehelper_setfns - set a cleanup/init function
410 * @info: a subprocess_info returned by call_usermodehelper_setup 406 * @info: a subprocess_info returned by call_usermodehelper_setup
411 * @cleanup: a cleanup function 407 * @cleanup: a cleanup function
408 * @init: an init function
409 * @data: arbitrary context sensitive data
410 *
411 * The init function is used to customize the helper process prior to
412 * exec. A non-zero return code causes the process to error out, exit,
413 * and return the failure to the calling process
412 * 414 *
413 * The cleanup function is just befor ethe subprocess_info is about to 415 * The cleanup function is just before ethe subprocess_info is about to
414 * be freed. This can be used for freeing the argv and envp. The 416 * be freed. This can be used for freeing the argv and envp. The
415 * Function must be runnable in either a process context or the 417 * Function must be runnable in either a process context or the
416 * context in which call_usermodehelper_exec is called. 418 * context in which call_usermodehelper_exec is called.
417 */ 419 */
418void call_usermodehelper_setcleanup(struct subprocess_info *info, 420void call_usermodehelper_setfns(struct subprocess_info *info,
419 void (*cleanup)(char **argv, char **envp)) 421 int (*init)(struct subprocess_info *info),
422 void (*cleanup)(struct subprocess_info *info),
423 void *data)
420{ 424{
421 info->cleanup = cleanup; 425 info->cleanup = cleanup;
426 info->init = init;
427 info->data = data;
422} 428}
423EXPORT_SYMBOL(call_usermodehelper_setcleanup); 429EXPORT_SYMBOL(call_usermodehelper_setfns);
424 430
425/** 431/**
426 * call_usermodehelper_stdinpipe - set up a pipe to be used for stdin 432 * 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,
515 struct subprocess_info *sub_info; 521 struct subprocess_info *sub_info;
516 int ret; 522 int ret;
517 523
518 sub_info = call_usermodehelper_setup(path, argv, envp, GFP_KERNEL); 524 sub_info = call_usermodehelper_setup(path, argv, envp,
525 GFP_KERNEL);
519 if (sub_info == NULL) 526 if (sub_info == NULL)
520 return -ENOMEM; 527 return -ENOMEM;
521 528