diff options
Diffstat (limited to 'kernel/kmod.c')
-rw-r--r-- | kernel/kmod.c | 203 |
1 files changed, 49 insertions, 154 deletions
diff --git a/kernel/kmod.c b/kernel/kmod.c index 7e95bedb2bfc..9cd0591c96a2 100644 --- a/kernel/kmod.c +++ b/kernel/kmod.c | |||
@@ -24,7 +24,6 @@ | |||
24 | #include <linux/unistd.h> | 24 | #include <linux/unistd.h> |
25 | #include <linux/kmod.h> | 25 | #include <linux/kmod.h> |
26 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
27 | #include <linux/mnt_namespace.h> | ||
28 | #include <linux/completion.h> | 27 | #include <linux/completion.h> |
29 | #include <linux/file.h> | 28 | #include <linux/file.h> |
30 | #include <linux/fdtable.h> | 29 | #include <linux/fdtable.h> |
@@ -38,6 +37,8 @@ | |||
38 | #include <linux/suspend.h> | 37 | #include <linux/suspend.h> |
39 | #include <asm/uaccess.h> | 38 | #include <asm/uaccess.h> |
40 | 39 | ||
40 | #include <trace/events/module.h> | ||
41 | |||
41 | extern int max_threads; | 42 | extern int max_threads; |
42 | 43 | ||
43 | static struct workqueue_struct *khelper_wq; | 44 | static struct workqueue_struct *khelper_wq; |
@@ -85,6 +86,10 @@ int __request_module(bool wait, const char *fmt, ...) | |||
85 | if (ret >= MODULE_NAME_LEN) | 86 | if (ret >= MODULE_NAME_LEN) |
86 | return -ENAMETOOLONG; | 87 | return -ENAMETOOLONG; |
87 | 88 | ||
89 | ret = security_kernel_module_request(module_name); | ||
90 | if (ret) | ||
91 | return ret; | ||
92 | |||
88 | /* If modprobe needs a service that is in a module, we get a recursive | 93 | /* If modprobe needs a service that is in a module, we get a recursive |
89 | * loop. Limit the number of running kmod threads to max_threads/2 or | 94 | * loop. Limit the number of running kmod threads to max_threads/2 or |
90 | * MAX_KMOD_CONCURRENT, whichever is the smaller. A cleaner method | 95 | * MAX_KMOD_CONCURRENT, whichever is the smaller. A cleaner method |
@@ -109,27 +114,18 @@ int __request_module(bool wait, const char *fmt, ...) | |||
109 | return -ENOMEM; | 114 | return -ENOMEM; |
110 | } | 115 | } |
111 | 116 | ||
112 | ret = call_usermodehelper(modprobe_path, argv, envp, | 117 | trace_module_request(module_name, wait, _RET_IP_); |
113 | wait ? UMH_WAIT_PROC : UMH_WAIT_EXEC); | 118 | |
119 | ret = call_usermodehelper_fns(modprobe_path, argv, envp, | ||
120 | wait ? UMH_WAIT_PROC : UMH_WAIT_EXEC, | ||
121 | NULL, NULL, NULL); | ||
122 | |||
114 | atomic_dec(&kmod_concurrent); | 123 | atomic_dec(&kmod_concurrent); |
115 | return ret; | 124 | return ret; |
116 | } | 125 | } |
117 | EXPORT_SYMBOL(__request_module); | 126 | EXPORT_SYMBOL(__request_module); |
118 | #endif /* CONFIG_MODULES */ | 127 | #endif /* CONFIG_MODULES */ |
119 | 128 | ||
120 | struct subprocess_info { | ||
121 | struct work_struct work; | ||
122 | struct completion *complete; | ||
123 | struct cred *cred; | ||
124 | char *path; | ||
125 | char **argv; | ||
126 | char **envp; | ||
127 | enum umh_wait wait; | ||
128 | int retval; | ||
129 | struct file *stdin; | ||
130 | void (*cleanup)(char **argv, char **envp); | ||
131 | }; | ||
132 | |||
133 | /* | 129 | /* |
134 | * This is the task which runs the usermode application | 130 | * This is the task which runs the usermode application |
135 | */ | 131 | */ |
@@ -138,36 +134,10 @@ static int ____call_usermodehelper(void *data) | |||
138 | struct subprocess_info *sub_info = data; | 134 | struct subprocess_info *sub_info = data; |
139 | int retval; | 135 | int retval; |
140 | 136 | ||
141 | BUG_ON(atomic_read(&sub_info->cred->usage) != 1); | ||
142 | |||
143 | /* Unblock all signals */ | ||
144 | spin_lock_irq(¤t->sighand->siglock); | 137 | spin_lock_irq(¤t->sighand->siglock); |
145 | flush_signal_handlers(current, 1); | 138 | flush_signal_handlers(current, 1); |
146 | sigemptyset(¤t->blocked); | ||
147 | recalc_sigpending(); | ||
148 | spin_unlock_irq(¤t->sighand->siglock); | 139 | spin_unlock_irq(¤t->sighand->siglock); |
149 | 140 | ||
150 | /* Install the credentials */ | ||
151 | commit_creds(sub_info->cred); | ||
152 | sub_info->cred = NULL; | ||
153 | |||
154 | /* Install input pipe when needed */ | ||
155 | if (sub_info->stdin) { | ||
156 | struct files_struct *f = current->files; | ||
157 | struct fdtable *fdt; | ||
158 | /* no races because files should be private here */ | ||
159 | sys_close(0); | ||
160 | fd_install(0, sub_info->stdin); | ||
161 | spin_lock(&f->file_lock); | ||
162 | fdt = files_fdtable(f); | ||
163 | FD_SET(0, fdt->open_fds); | ||
164 | FD_CLR(0, fdt->close_on_exec); | ||
165 | spin_unlock(&f->file_lock); | ||
166 | |||
167 | /* and disallow core files too */ | ||
168 | current->signal->rlim[RLIMIT_CORE] = (struct rlimit){0, 0}; | ||
169 | } | ||
170 | |||
171 | /* We can run anywhere, unlike our parent keventd(). */ | 141 | /* We can run anywhere, unlike our parent keventd(). */ |
172 | set_cpus_allowed_ptr(current, cpu_all_mask); | 142 | set_cpus_allowed_ptr(current, cpu_all_mask); |
173 | 143 | ||
@@ -177,9 +147,18 @@ static int ____call_usermodehelper(void *data) | |||
177 | */ | 147 | */ |
178 | set_user_nice(current, 0); | 148 | set_user_nice(current, 0); |
179 | 149 | ||
180 | retval = kernel_execve(sub_info->path, sub_info->argv, sub_info->envp); | 150 | if (sub_info->init) { |
151 | retval = sub_info->init(sub_info); | ||
152 | if (retval) | ||
153 | goto fail; | ||
154 | } | ||
155 | |||
156 | retval = kernel_execve(sub_info->path, | ||
157 | (const char *const *)sub_info->argv, | ||
158 | (const char *const *)sub_info->envp); | ||
181 | 159 | ||
182 | /* Exec failed? */ | 160 | /* Exec failed? */ |
161 | fail: | ||
183 | sub_info->retval = retval; | 162 | sub_info->retval = retval; |
184 | do_exit(0); | 163 | do_exit(0); |
185 | } | 164 | } |
@@ -187,9 +166,7 @@ static int ____call_usermodehelper(void *data) | |||
187 | void call_usermodehelper_freeinfo(struct subprocess_info *info) | 166 | void call_usermodehelper_freeinfo(struct subprocess_info *info) |
188 | { | 167 | { |
189 | if (info->cleanup) | 168 | if (info->cleanup) |
190 | (*info->cleanup)(info->argv, info->envp); | 169 | (*info->cleanup)(info); |
191 | if (info->cred) | ||
192 | put_cred(info->cred); | ||
193 | kfree(info); | 170 | kfree(info); |
194 | } | 171 | } |
195 | EXPORT_SYMBOL(call_usermodehelper_freeinfo); | 172 | EXPORT_SYMBOL(call_usermodehelper_freeinfo); |
@@ -200,16 +177,16 @@ static int wait_for_helper(void *data) | |||
200 | struct subprocess_info *sub_info = data; | 177 | struct subprocess_info *sub_info = data; |
201 | pid_t pid; | 178 | pid_t pid; |
202 | 179 | ||
203 | /* Install a handler: if SIGCLD isn't handled sys_wait4 won't | 180 | /* If SIGCLD is ignored sys_wait4 won't populate the status. */ |
204 | * populate the status, but will return -ECHILD. */ | 181 | spin_lock_irq(¤t->sighand->siglock); |
205 | allow_signal(SIGCHLD); | 182 | current->sighand->action[SIGCHLD-1].sa.sa_handler = SIG_DFL; |
183 | spin_unlock_irq(¤t->sighand->siglock); | ||
206 | 184 | ||
207 | pid = kernel_thread(____call_usermodehelper, sub_info, SIGCHLD); | 185 | pid = kernel_thread(____call_usermodehelper, sub_info, SIGCHLD); |
208 | if (pid < 0) { | 186 | if (pid < 0) { |
209 | sub_info->retval = pid; | 187 | sub_info->retval = pid; |
210 | } else { | 188 | } else { |
211 | int ret; | 189 | int ret = -ECHILD; |
212 | |||
213 | /* | 190 | /* |
214 | * Normally it is bogus to call wait4() from in-kernel because | 191 | * Normally it is bogus to call wait4() from in-kernel because |
215 | * wait4() wants to write the exit code to a userspace address. | 192 | * wait4() wants to write the exit code to a userspace address. |
@@ -230,10 +207,7 @@ static int wait_for_helper(void *data) | |||
230 | sub_info->retval = ret; | 207 | sub_info->retval = ret; |
231 | } | 208 | } |
232 | 209 | ||
233 | if (sub_info->wait == UMH_NO_WAIT) | 210 | complete(sub_info->complete); |
234 | call_usermodehelper_freeinfo(sub_info); | ||
235 | else | ||
236 | complete(sub_info->complete); | ||
237 | return 0; | 211 | return 0; |
238 | } | 212 | } |
239 | 213 | ||
@@ -242,15 +216,13 @@ static void __call_usermodehelper(struct work_struct *work) | |||
242 | { | 216 | { |
243 | struct subprocess_info *sub_info = | 217 | struct subprocess_info *sub_info = |
244 | container_of(work, struct subprocess_info, work); | 218 | container_of(work, struct subprocess_info, work); |
245 | pid_t pid; | ||
246 | enum umh_wait wait = sub_info->wait; | 219 | enum umh_wait wait = sub_info->wait; |
247 | 220 | pid_t pid; | |
248 | BUG_ON(atomic_read(&sub_info->cred->usage) != 1); | ||
249 | 221 | ||
250 | /* CLONE_VFORK: wait until the usermode helper has execve'd | 222 | /* CLONE_VFORK: wait until the usermode helper has execve'd |
251 | * successfully We need the data structures to stay around | 223 | * successfully We need the data structures to stay around |
252 | * until that is done. */ | 224 | * until that is done. */ |
253 | if (wait == UMH_WAIT_PROC || wait == UMH_NO_WAIT) | 225 | if (wait == UMH_WAIT_PROC) |
254 | pid = kernel_thread(wait_for_helper, sub_info, | 226 | pid = kernel_thread(wait_for_helper, sub_info, |
255 | CLONE_FS | CLONE_FILES | SIGCHLD); | 227 | CLONE_FS | CLONE_FILES | SIGCHLD); |
256 | else | 228 | else |
@@ -259,15 +231,16 @@ static void __call_usermodehelper(struct work_struct *work) | |||
259 | 231 | ||
260 | switch (wait) { | 232 | switch (wait) { |
261 | case UMH_NO_WAIT: | 233 | case UMH_NO_WAIT: |
234 | call_usermodehelper_freeinfo(sub_info); | ||
262 | break; | 235 | break; |
263 | 236 | ||
264 | case UMH_WAIT_PROC: | 237 | case UMH_WAIT_PROC: |
265 | if (pid > 0) | 238 | if (pid > 0) |
266 | break; | 239 | break; |
267 | sub_info->retval = pid; | ||
268 | /* FALLTHROUGH */ | 240 | /* FALLTHROUGH */ |
269 | |||
270 | case UMH_WAIT_EXEC: | 241 | case UMH_WAIT_EXEC: |
242 | if (pid < 0) | ||
243 | sub_info->retval = pid; | ||
271 | complete(sub_info->complete); | 244 | complete(sub_info->complete); |
272 | } | 245 | } |
273 | } | 246 | } |
@@ -369,80 +342,37 @@ struct subprocess_info *call_usermodehelper_setup(char *path, char **argv, | |||
369 | sub_info->path = path; | 342 | sub_info->path = path; |
370 | sub_info->argv = argv; | 343 | sub_info->argv = argv; |
371 | sub_info->envp = envp; | 344 | sub_info->envp = envp; |
372 | sub_info->cred = prepare_usermodehelper_creds(); | ||
373 | if (!sub_info->cred) { | ||
374 | kfree(sub_info); | ||
375 | return NULL; | ||
376 | } | ||
377 | |||
378 | out: | 345 | out: |
379 | return sub_info; | 346 | return sub_info; |
380 | } | 347 | } |
381 | EXPORT_SYMBOL(call_usermodehelper_setup); | 348 | EXPORT_SYMBOL(call_usermodehelper_setup); |
382 | 349 | ||
383 | /** | 350 | /** |
384 | * call_usermodehelper_setkeys - set the session keys for usermode helper | 351 | * call_usermodehelper_setfns - set a cleanup/init function |
385 | * @info: a subprocess_info returned by call_usermodehelper_setup | ||
386 | * @session_keyring: the session keyring for the process | ||
387 | */ | ||
388 | void call_usermodehelper_setkeys(struct subprocess_info *info, | ||
389 | struct key *session_keyring) | ||
390 | { | ||
391 | #ifdef CONFIG_KEYS | ||
392 | struct thread_group_cred *tgcred = info->cred->tgcred; | ||
393 | key_put(tgcred->session_keyring); | ||
394 | tgcred->session_keyring = key_get(session_keyring); | ||
395 | #else | ||
396 | BUG(); | ||
397 | #endif | ||
398 | } | ||
399 | EXPORT_SYMBOL(call_usermodehelper_setkeys); | ||
400 | |||
401 | /** | ||
402 | * call_usermodehelper_setcleanup - set a cleanup function | ||
403 | * @info: a subprocess_info returned by call_usermodehelper_setup | 352 | * @info: a subprocess_info returned by call_usermodehelper_setup |
404 | * @cleanup: a cleanup function | 353 | * @cleanup: a cleanup function |
354 | * @init: an init function | ||
355 | * @data: arbitrary context sensitive data | ||
356 | * | ||
357 | * The init function is used to customize the helper process prior to | ||
358 | * exec. A non-zero return code causes the process to error out, exit, | ||
359 | * and return the failure to the calling process | ||
405 | * | 360 | * |
406 | * The cleanup function is just befor ethe subprocess_info is about to | 361 | * The cleanup function is just before ethe subprocess_info is about to |
407 | * be freed. This can be used for freeing the argv and envp. The | 362 | * be freed. This can be used for freeing the argv and envp. The |
408 | * Function must be runnable in either a process context or the | 363 | * Function must be runnable in either a process context or the |
409 | * context in which call_usermodehelper_exec is called. | 364 | * context in which call_usermodehelper_exec is called. |
410 | */ | 365 | */ |
411 | void call_usermodehelper_setcleanup(struct subprocess_info *info, | 366 | void call_usermodehelper_setfns(struct subprocess_info *info, |
412 | void (*cleanup)(char **argv, char **envp)) | 367 | int (*init)(struct subprocess_info *info), |
368 | void (*cleanup)(struct subprocess_info *info), | ||
369 | void *data) | ||
413 | { | 370 | { |
414 | info->cleanup = cleanup; | 371 | info->cleanup = cleanup; |
372 | info->init = init; | ||
373 | info->data = data; | ||
415 | } | 374 | } |
416 | EXPORT_SYMBOL(call_usermodehelper_setcleanup); | 375 | EXPORT_SYMBOL(call_usermodehelper_setfns); |
417 | |||
418 | /** | ||
419 | * call_usermodehelper_stdinpipe - set up a pipe to be used for stdin | ||
420 | * @sub_info: a subprocess_info returned by call_usermodehelper_setup | ||
421 | * @filp: set to the write-end of a pipe | ||
422 | * | ||
423 | * This constructs a pipe, and sets the read end to be the stdin of the | ||
424 | * subprocess, and returns the write-end in *@filp. | ||
425 | */ | ||
426 | int call_usermodehelper_stdinpipe(struct subprocess_info *sub_info, | ||
427 | struct file **filp) | ||
428 | { | ||
429 | struct file *f; | ||
430 | |||
431 | f = create_write_pipe(0); | ||
432 | if (IS_ERR(f)) | ||
433 | return PTR_ERR(f); | ||
434 | *filp = f; | ||
435 | |||
436 | f = create_read_pipe(f, 0); | ||
437 | if (IS_ERR(f)) { | ||
438 | free_write_pipe(*filp); | ||
439 | return PTR_ERR(f); | ||
440 | } | ||
441 | sub_info->stdin = f; | ||
442 | |||
443 | return 0; | ||
444 | } | ||
445 | EXPORT_SYMBOL(call_usermodehelper_stdinpipe); | ||
446 | 376 | ||
447 | /** | 377 | /** |
448 | * call_usermodehelper_exec - start a usermode application | 378 | * call_usermodehelper_exec - start a usermode application |
@@ -462,8 +392,6 @@ int call_usermodehelper_exec(struct subprocess_info *sub_info, | |||
462 | DECLARE_COMPLETION_ONSTACK(done); | 392 | DECLARE_COMPLETION_ONSTACK(done); |
463 | int retval = 0; | 393 | int retval = 0; |
464 | 394 | ||
465 | BUG_ON(atomic_read(&sub_info->cred->usage) != 1); | ||
466 | |||
467 | helper_lock(); | 395 | helper_lock(); |
468 | if (sub_info->path[0] == '\0') | 396 | if (sub_info->path[0] == '\0') |
469 | goto out; | 397 | goto out; |
@@ -490,39 +418,6 @@ unlock: | |||
490 | } | 418 | } |
491 | EXPORT_SYMBOL(call_usermodehelper_exec); | 419 | EXPORT_SYMBOL(call_usermodehelper_exec); |
492 | 420 | ||
493 | /** | ||
494 | * call_usermodehelper_pipe - call a usermode helper process with a pipe stdin | ||
495 | * @path: path to usermode executable | ||
496 | * @argv: arg vector for process | ||
497 | * @envp: environment for process | ||
498 | * @filp: set to the write-end of a pipe | ||
499 | * | ||
500 | * This is a simple wrapper which executes a usermode-helper function | ||
501 | * with a pipe as stdin. It is implemented entirely in terms of | ||
502 | * lower-level call_usermodehelper_* functions. | ||
503 | */ | ||
504 | int call_usermodehelper_pipe(char *path, char **argv, char **envp, | ||
505 | struct file **filp) | ||
506 | { | ||
507 | struct subprocess_info *sub_info; | ||
508 | int ret; | ||
509 | |||
510 | sub_info = call_usermodehelper_setup(path, argv, envp, GFP_KERNEL); | ||
511 | if (sub_info == NULL) | ||
512 | return -ENOMEM; | ||
513 | |||
514 | ret = call_usermodehelper_stdinpipe(sub_info, filp); | ||
515 | if (ret < 0) | ||
516 | goto out; | ||
517 | |||
518 | return call_usermodehelper_exec(sub_info, UMH_WAIT_EXEC); | ||
519 | |||
520 | out: | ||
521 | call_usermodehelper_freeinfo(sub_info); | ||
522 | return ret; | ||
523 | } | ||
524 | EXPORT_SYMBOL(call_usermodehelper_pipe); | ||
525 | |||
526 | void __init usermodehelper_init(void) | 421 | void __init usermodehelper_init(void) |
527 | { | 422 | { |
528 | khelper_wq = create_singlethread_workqueue("khelper"); | 423 | khelper_wq = create_singlethread_workqueue("khelper"); |