.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * umh - the kernel usermode helper |
---|
3 | 4 | */ |
---|
.. | .. |
---|
26 | 27 | #include <linux/ptrace.h> |
---|
27 | 28 | #include <linux/async.h> |
---|
28 | 29 | #include <linux/uaccess.h> |
---|
29 | | -#include <linux/shmem_fs.h> |
---|
30 | | -#include <linux/pipe_fs_i.h> |
---|
31 | 30 | |
---|
32 | 31 | #include <trace/events/module.h> |
---|
33 | 32 | |
---|
.. | .. |
---|
108 | 107 | |
---|
109 | 108 | commit_creds(new); |
---|
110 | 109 | |
---|
111 | | - sub_info->pid = task_pid_nr(current); |
---|
112 | | - if (sub_info->file) |
---|
113 | | - retval = do_execve_file(sub_info->file, |
---|
114 | | - sub_info->argv, sub_info->envp); |
---|
115 | | - else |
---|
116 | | - retval = do_execve(getname_kernel(sub_info->path), |
---|
117 | | - (const char __user *const __user *)sub_info->argv, |
---|
118 | | - (const char __user *const __user *)sub_info->envp); |
---|
| 110 | + retval = kernel_execve(sub_info->path, |
---|
| 111 | + (const char *const *)sub_info->argv, |
---|
| 112 | + (const char *const *)sub_info->envp); |
---|
119 | 113 | out: |
---|
120 | 114 | sub_info->retval = retval; |
---|
121 | 115 | /* |
---|
.. | .. |
---|
134 | 128 | { |
---|
135 | 129 | pid_t pid; |
---|
136 | 130 | |
---|
137 | | - /* If SIGCLD is ignored kernel_wait4 won't populate the status. */ |
---|
| 131 | + /* If SIGCLD is ignored do_wait won't populate the status. */ |
---|
138 | 132 | kernel_sigaction(SIGCHLD, SIG_DFL); |
---|
139 | 133 | pid = kernel_thread(call_usermodehelper_exec_async, sub_info, SIGCHLD); |
---|
140 | | - if (pid < 0) { |
---|
| 134 | + if (pid < 0) |
---|
141 | 135 | sub_info->retval = pid; |
---|
142 | | - } else { |
---|
143 | | - int ret = -ECHILD; |
---|
144 | | - /* |
---|
145 | | - * Normally it is bogus to call wait4() from in-kernel because |
---|
146 | | - * wait4() wants to write the exit code to a userspace address. |
---|
147 | | - * But call_usermodehelper_exec_sync() always runs as kernel |
---|
148 | | - * thread (workqueue) and put_user() to a kernel address works |
---|
149 | | - * OK for kernel threads, due to their having an mm_segment_t |
---|
150 | | - * which spans the entire address space. |
---|
151 | | - * |
---|
152 | | - * Thus the __user pointer cast is valid here. |
---|
153 | | - */ |
---|
154 | | - kernel_wait4(pid, (int __user *)&ret, 0, NULL); |
---|
155 | | - |
---|
156 | | - /* |
---|
157 | | - * If ret is 0, either call_usermodehelper_exec_async failed and |
---|
158 | | - * the real error code is already in sub_info->retval or |
---|
159 | | - * sub_info->retval is 0 anyway, so don't mess with it then. |
---|
160 | | - */ |
---|
161 | | - if (ret) |
---|
162 | | - sub_info->retval = ret; |
---|
163 | | - } |
---|
| 136 | + else |
---|
| 137 | + kernel_wait(pid, &sub_info->retval); |
---|
164 | 138 | |
---|
165 | 139 | /* Restore default kernel sig handler */ |
---|
166 | 140 | kernel_sigaction(SIGCHLD, SIG_IGN); |
---|
167 | | - |
---|
168 | 141 | umh_complete(sub_info); |
---|
169 | 142 | } |
---|
170 | 143 | |
---|
.. | .. |
---|
409 | 382 | } |
---|
410 | 383 | EXPORT_SYMBOL(call_usermodehelper_setup); |
---|
411 | 384 | |
---|
412 | | -struct subprocess_info *call_usermodehelper_setup_file(struct file *file, |
---|
413 | | - int (*init)(struct subprocess_info *info, struct cred *new), |
---|
414 | | - void (*cleanup)(struct subprocess_info *info), void *data) |
---|
415 | | -{ |
---|
416 | | - struct subprocess_info *sub_info; |
---|
417 | | - |
---|
418 | | - sub_info = kzalloc(sizeof(struct subprocess_info), GFP_KERNEL); |
---|
419 | | - if (!sub_info) |
---|
420 | | - return NULL; |
---|
421 | | - |
---|
422 | | - INIT_WORK(&sub_info->work, call_usermodehelper_exec_work); |
---|
423 | | - sub_info->path = "none"; |
---|
424 | | - sub_info->file = file; |
---|
425 | | - sub_info->init = init; |
---|
426 | | - sub_info->cleanup = cleanup; |
---|
427 | | - sub_info->data = data; |
---|
428 | | - return sub_info; |
---|
429 | | -} |
---|
430 | | - |
---|
431 | | -static int umh_pipe_setup(struct subprocess_info *info, struct cred *new) |
---|
432 | | -{ |
---|
433 | | - struct umh_info *umh_info = info->data; |
---|
434 | | - struct file *from_umh[2]; |
---|
435 | | - struct file *to_umh[2]; |
---|
436 | | - int err; |
---|
437 | | - |
---|
438 | | - /* create pipe to send data to umh */ |
---|
439 | | - err = create_pipe_files(to_umh, 0); |
---|
440 | | - if (err) |
---|
441 | | - return err; |
---|
442 | | - err = replace_fd(0, to_umh[0], 0); |
---|
443 | | - fput(to_umh[0]); |
---|
444 | | - if (err < 0) { |
---|
445 | | - fput(to_umh[1]); |
---|
446 | | - return err; |
---|
447 | | - } |
---|
448 | | - |
---|
449 | | - /* create pipe to receive data from umh */ |
---|
450 | | - err = create_pipe_files(from_umh, 0); |
---|
451 | | - if (err) { |
---|
452 | | - fput(to_umh[1]); |
---|
453 | | - replace_fd(0, NULL, 0); |
---|
454 | | - return err; |
---|
455 | | - } |
---|
456 | | - err = replace_fd(1, from_umh[1], 0); |
---|
457 | | - fput(from_umh[1]); |
---|
458 | | - if (err < 0) { |
---|
459 | | - fput(to_umh[1]); |
---|
460 | | - replace_fd(0, NULL, 0); |
---|
461 | | - fput(from_umh[0]); |
---|
462 | | - return err; |
---|
463 | | - } |
---|
464 | | - |
---|
465 | | - umh_info->pipe_to_umh = to_umh[1]; |
---|
466 | | - umh_info->pipe_from_umh = from_umh[0]; |
---|
467 | | - return 0; |
---|
468 | | -} |
---|
469 | | - |
---|
470 | | -static void umh_save_pid(struct subprocess_info *info) |
---|
471 | | -{ |
---|
472 | | - struct umh_info *umh_info = info->data; |
---|
473 | | - |
---|
474 | | - umh_info->pid = info->pid; |
---|
475 | | -} |
---|
476 | | - |
---|
477 | | -/** |
---|
478 | | - * fork_usermode_blob - fork a blob of bytes as a usermode process |
---|
479 | | - * @data: a blob of bytes that can be do_execv-ed as a file |
---|
480 | | - * @len: length of the blob |
---|
481 | | - * @info: information about usermode process (shouldn't be NULL) |
---|
482 | | - * |
---|
483 | | - * Returns either negative error or zero which indicates success |
---|
484 | | - * in executing a blob of bytes as a usermode process. In such |
---|
485 | | - * case 'struct umh_info *info' is populated with two pipes |
---|
486 | | - * and a pid of the process. The caller is responsible for health |
---|
487 | | - * check of the user process, killing it via pid, and closing the |
---|
488 | | - * pipes when user process is no longer needed. |
---|
489 | | - */ |
---|
490 | | -int fork_usermode_blob(void *data, size_t len, struct umh_info *info) |
---|
491 | | -{ |
---|
492 | | - struct subprocess_info *sub_info; |
---|
493 | | - struct file *file; |
---|
494 | | - ssize_t written; |
---|
495 | | - loff_t pos = 0; |
---|
496 | | - int err; |
---|
497 | | - |
---|
498 | | - file = shmem_kernel_file_setup("", len, 0); |
---|
499 | | - if (IS_ERR(file)) |
---|
500 | | - return PTR_ERR(file); |
---|
501 | | - |
---|
502 | | - written = kernel_write(file, data, len, &pos); |
---|
503 | | - if (written != len) { |
---|
504 | | - err = written; |
---|
505 | | - if (err >= 0) |
---|
506 | | - err = -ENOMEM; |
---|
507 | | - goto out; |
---|
508 | | - } |
---|
509 | | - |
---|
510 | | - err = -ENOMEM; |
---|
511 | | - sub_info = call_usermodehelper_setup_file(file, umh_pipe_setup, |
---|
512 | | - umh_save_pid, info); |
---|
513 | | - if (!sub_info) |
---|
514 | | - goto out; |
---|
515 | | - |
---|
516 | | - err = call_usermodehelper_exec(sub_info, UMH_WAIT_EXEC); |
---|
517 | | -out: |
---|
518 | | - fput(file); |
---|
519 | | - return err; |
---|
520 | | -} |
---|
521 | | -EXPORT_SYMBOL_GPL(fork_usermode_blob); |
---|
522 | | - |
---|
523 | 385 | /** |
---|
524 | 386 | * call_usermodehelper_exec - start a usermode application |
---|
525 | 387 | * @sub_info: information about the subprocessa |
---|
.. | .. |
---|
622 | 484 | EXPORT_SYMBOL(call_usermodehelper); |
---|
623 | 485 | |
---|
624 | 486 | static int proc_cap_handler(struct ctl_table *table, int write, |
---|
625 | | - void __user *buffer, size_t *lenp, loff_t *ppos) |
---|
| 487 | + void *buffer, size_t *lenp, loff_t *ppos) |
---|
626 | 488 | { |
---|
627 | 489 | struct ctl_table t; |
---|
628 | 490 | unsigned long cap_array[_KERNEL_CAPABILITY_U32S]; |
---|