diff options
-rw-r--r-- | fs/exec.c | 63 | ||||
-rw-r--r-- | include/linux/kmod.h | 7 | ||||
-rw-r--r-- | kernel/kmod.c | 82 |
3 files changed, 56 insertions, 96 deletions
@@ -1787,6 +1787,50 @@ static void wait_for_dump_helpers(struct file *file) | |||
1787 | } | 1787 | } |
1788 | 1788 | ||
1789 | 1789 | ||
1790 | /* | ||
1791 | * uhm_pipe_setup | ||
1792 | * helper function to customize the process used | ||
1793 | * to collect the core in userspace. Specifically | ||
1794 | * it sets up a pipe and installs it as fd 0 (stdin) | ||
1795 | * for the process. Returns 0 on success, or | ||
1796 | * PTR_ERR on failure. | ||
1797 | * Note that it also sets the core limit to 1. This | ||
1798 | * is a special value that we use to trap recursive | ||
1799 | * core dumps | ||
1800 | */ | ||
1801 | static int umh_pipe_setup(struct subprocess_info *info) | ||
1802 | { | ||
1803 | struct file *rp, *wp; | ||
1804 | struct fdtable *fdt; | ||
1805 | struct coredump_params *cp = (struct coredump_params *)info->data; | ||
1806 | struct files_struct *cf = current->files; | ||
1807 | |||
1808 | wp = create_write_pipe(0); | ||
1809 | if (IS_ERR(wp)) | ||
1810 | return PTR_ERR(wp); | ||
1811 | |||
1812 | rp = create_read_pipe(wp, 0); | ||
1813 | if (IS_ERR(rp)) { | ||
1814 | free_write_pipe(wp); | ||
1815 | return PTR_ERR(rp); | ||
1816 | } | ||
1817 | |||
1818 | cp->file = wp; | ||
1819 | |||
1820 | sys_close(0); | ||
1821 | fd_install(0, rp); | ||
1822 | spin_lock(&cf->file_lock); | ||
1823 | fdt = files_fdtable(cf); | ||
1824 | FD_SET(0, fdt->open_fds); | ||
1825 | FD_CLR(0, fdt->close_on_exec); | ||
1826 | spin_unlock(&cf->file_lock); | ||
1827 | |||
1828 | /* and disallow core files too */ | ||
1829 | current->signal->rlim[RLIMIT_CORE] = (struct rlimit){1, 1}; | ||
1830 | |||
1831 | return 0; | ||
1832 | } | ||
1833 | |||
1790 | void do_coredump(long signr, int exit_code, struct pt_regs *regs) | 1834 | void do_coredump(long signr, int exit_code, struct pt_regs *regs) |
1791 | { | 1835 | { |
1792 | struct core_state core_state; | 1836 | struct core_state core_state; |
@@ -1874,15 +1918,15 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs) | |||
1874 | goto fail_unlock; | 1918 | goto fail_unlock; |
1875 | 1919 | ||
1876 | if (ispipe) { | 1920 | if (ispipe) { |
1877 | if (cprm.limit == 0) { | 1921 | if (cprm.limit == 1) { |
1878 | /* | 1922 | /* |
1879 | * Normally core limits are irrelevant to pipes, since | 1923 | * Normally core limits are irrelevant to pipes, since |
1880 | * we're not writing to the file system, but we use | 1924 | * we're not writing to the file system, but we use |
1881 | * cprm.limit of 0 here as a speacial value. Any | 1925 | * cprm.limit of 1 here as a speacial value. Any |
1882 | * non-zero limit gets set to RLIM_INFINITY below, but | 1926 | * non-1 limit gets set to RLIM_INFINITY below, but |
1883 | * a limit of 0 skips the dump. This is a consistent | 1927 | * a limit of 0 skips the dump. This is a consistent |
1884 | * way to catch recursive crashes. We can still crash | 1928 | * way to catch recursive crashes. We can still crash |
1885 | * if the core_pattern binary sets RLIM_CORE = !0 | 1929 | * if the core_pattern binary sets RLIM_CORE = !1 |
1886 | * but it runs as root, and can do lots of stupid things | 1930 | * but it runs as root, and can do lots of stupid things |
1887 | * Note that we use task_tgid_vnr here to grab the pid | 1931 | * Note that we use task_tgid_vnr here to grab the pid |
1888 | * of the process group leader. That way we get the | 1932 | * of the process group leader. That way we get the |
@@ -1890,7 +1934,7 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs) | |||
1890 | * core_pattern process dies. | 1934 | * core_pattern process dies. |
1891 | */ | 1935 | */ |
1892 | printk(KERN_WARNING | 1936 | printk(KERN_WARNING |
1893 | "Process %d(%s) has RLIMIT_CORE set to 0\n", | 1937 | "Process %d(%s) has RLIMIT_CORE set to 1\n", |
1894 | task_tgid_vnr(current), current->comm); | 1938 | task_tgid_vnr(current), current->comm); |
1895 | printk(KERN_WARNING "Aborting core\n"); | 1939 | printk(KERN_WARNING "Aborting core\n"); |
1896 | goto fail_unlock; | 1940 | goto fail_unlock; |
@@ -1914,8 +1958,13 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs) | |||
1914 | cprm.limit = RLIM_INFINITY; | 1958 | cprm.limit = RLIM_INFINITY; |
1915 | 1959 | ||
1916 | /* SIGPIPE can happen, but it's just never processed */ | 1960 | /* SIGPIPE can happen, but it's just never processed */ |
1917 | if (call_usermodehelper_pipe(helper_argv[0], helper_argv, NULL, | 1961 | cprm.file = NULL; |
1918 | &cprm.file)) { | 1962 | if (call_usermodehelper_fns(helper_argv[0], helper_argv, NULL, |
1963 | UMH_WAIT_EXEC, umh_pipe_setup, | ||
1964 | NULL, &cprm)) { | ||
1965 | if (cprm.file) | ||
1966 | filp_close(cprm.file, NULL); | ||
1967 | |||
1919 | printk(KERN_INFO "Core dump to %s pipe failed\n", | 1968 | printk(KERN_INFO "Core dump to %s pipe failed\n", |
1920 | corename); | 1969 | corename); |
1921 | goto fail_dropcount; | 1970 | goto fail_dropcount; |
diff --git a/include/linux/kmod.h b/include/linux/kmod.h index f9edf63e90ea..5c058778ad35 100644 --- a/include/linux/kmod.h +++ b/include/linux/kmod.h | |||
@@ -62,7 +62,6 @@ struct subprocess_info { | |||
62 | char **envp; | 62 | char **envp; |
63 | enum umh_wait wait; | 63 | enum umh_wait wait; |
64 | int retval; | 64 | int retval; |
65 | struct file *stdin; | ||
66 | int (*init)(struct subprocess_info *info); | 65 | int (*init)(struct subprocess_info *info); |
67 | void (*cleanup)(struct subprocess_info *info); | 66 | void (*cleanup)(struct subprocess_info *info); |
68 | void *data; | 67 | void *data; |
@@ -75,8 +74,6 @@ struct subprocess_info *call_usermodehelper_setup(char *path, char **argv, | |||
75 | /* Set various pieces of state into the subprocess_info structure */ | 74 | /* Set various pieces of state into the subprocess_info structure */ |
76 | void call_usermodehelper_setkeys(struct subprocess_info *info, | 75 | void call_usermodehelper_setkeys(struct subprocess_info *info, |
77 | struct key *session_keyring); | 76 | struct key *session_keyring); |
78 | int call_usermodehelper_stdinpipe(struct subprocess_info *sub_info, | ||
79 | struct file **filp); | ||
80 | void call_usermodehelper_setfns(struct subprocess_info *info, | 77 | void call_usermodehelper_setfns(struct subprocess_info *info, |
81 | int (*init)(struct subprocess_info *info), | 78 | int (*init)(struct subprocess_info *info), |
82 | void (*cleanup)(struct subprocess_info *info), | 79 | void (*cleanup)(struct subprocess_info *info), |
@@ -132,10 +129,6 @@ call_usermodehelper_keys(char *path, char **argv, char **envp, | |||
132 | 129 | ||
133 | extern void usermodehelper_init(void); | 130 | extern void usermodehelper_init(void); |
134 | 131 | ||
135 | struct file; | ||
136 | extern int call_usermodehelper_pipe(char *path, char *argv[], char *envp[], | ||
137 | struct file **filp); | ||
138 | |||
139 | extern int usermodehelper_disable(void); | 132 | extern int usermodehelper_disable(void); |
140 | extern void usermodehelper_enable(void); | 133 | extern void usermodehelper_enable(void); |
141 | 134 | ||
diff --git a/kernel/kmod.c b/kernel/kmod.c index 531ef62cf536..d1544547fea6 100644 --- a/kernel/kmod.c +++ b/kernel/kmod.c | |||
@@ -147,23 +147,6 @@ static int ____call_usermodehelper(void *data) | |||
147 | commit_creds(sub_info->cred); | 147 | commit_creds(sub_info->cred); |
148 | sub_info->cred = NULL; | 148 | sub_info->cred = NULL; |
149 | 149 | ||
150 | /* Install input pipe when needed */ | ||
151 | if (sub_info->stdin) { | ||
152 | struct files_struct *f = current->files; | ||
153 | struct fdtable *fdt; | ||
154 | /* no races because files should be private here */ | ||
155 | sys_close(0); | ||
156 | fd_install(0, sub_info->stdin); | ||
157 | spin_lock(&f->file_lock); | ||
158 | fdt = files_fdtable(f); | ||
159 | FD_SET(0, fdt->open_fds); | ||
160 | FD_CLR(0, fdt->close_on_exec); | ||
161 | spin_unlock(&f->file_lock); | ||
162 | |||
163 | /* and disallow core files too */ | ||
164 | current->signal->rlim[RLIMIT_CORE] = (struct rlimit){0, 0}; | ||
165 | } | ||
166 | |||
167 | /* We can run anywhere, unlike our parent keventd(). */ | 150 | /* We can run anywhere, unlike our parent keventd(). */ |
168 | set_cpus_allowed_ptr(current, cpu_all_mask); | 151 | set_cpus_allowed_ptr(current, cpu_all_mask); |
169 | 152 | ||
@@ -429,35 +412,6 @@ void call_usermodehelper_setfns(struct subprocess_info *info, | |||
429 | EXPORT_SYMBOL(call_usermodehelper_setfns); | 412 | EXPORT_SYMBOL(call_usermodehelper_setfns); |
430 | 413 | ||
431 | /** | 414 | /** |
432 | * call_usermodehelper_stdinpipe - set up a pipe to be used for stdin | ||
433 | * @sub_info: a subprocess_info returned by call_usermodehelper_setup | ||
434 | * @filp: set to the write-end of a pipe | ||
435 | * | ||
436 | * This constructs a pipe, and sets the read end to be the stdin of the | ||
437 | * subprocess, and returns the write-end in *@filp. | ||
438 | */ | ||
439 | int call_usermodehelper_stdinpipe(struct subprocess_info *sub_info, | ||
440 | struct file **filp) | ||
441 | { | ||
442 | struct file *f; | ||
443 | |||
444 | f = create_write_pipe(0); | ||
445 | if (IS_ERR(f)) | ||
446 | return PTR_ERR(f); | ||
447 | *filp = f; | ||
448 | |||
449 | f = create_read_pipe(f, 0); | ||
450 | if (IS_ERR(f)) { | ||
451 | free_write_pipe(*filp); | ||
452 | return PTR_ERR(f); | ||
453 | } | ||
454 | sub_info->stdin = f; | ||
455 | |||
456 | return 0; | ||
457 | } | ||
458 | EXPORT_SYMBOL(call_usermodehelper_stdinpipe); | ||
459 | |||
460 | /** | ||
461 | * call_usermodehelper_exec - start a usermode application | 415 | * call_usermodehelper_exec - start a usermode application |
462 | * @sub_info: information about the subprocessa | 416 | * @sub_info: information about the subprocessa |
463 | * @wait: wait for the application to finish and return status. | 417 | * @wait: wait for the application to finish and return status. |
@@ -504,42 +458,6 @@ unlock: | |||
504 | } | 458 | } |
505 | EXPORT_SYMBOL(call_usermodehelper_exec); | 459 | EXPORT_SYMBOL(call_usermodehelper_exec); |
506 | 460 | ||
507 | /** | ||
508 | * call_usermodehelper_pipe - call a usermode helper process with a pipe stdin | ||
509 | * @path: path to usermode executable | ||
510 | * @argv: arg vector for process | ||
511 | * @envp: environment for process | ||
512 | * @filp: set to the write-end of a pipe | ||
513 | * | ||
514 | * This is a simple wrapper which executes a usermode-helper function | ||
515 | * with a pipe as stdin. It is implemented entirely in terms of | ||
516 | * lower-level call_usermodehelper_* functions. | ||
517 | */ | ||
518 | int call_usermodehelper_pipe(char *path, char **argv, char **envp, | ||
519 | struct file **filp) | ||
520 | { | ||
521 | struct subprocess_info *sub_info; | ||
522 | int ret; | ||
523 | |||
524 | sub_info = call_usermodehelper_setup(path, argv, envp, | ||
525 | GFP_KERNEL); | ||
526 | if (sub_info == NULL) | ||
527 | return -ENOMEM; | ||
528 | |||
529 | ret = call_usermodehelper_stdinpipe(sub_info, filp); | ||
530 | if (ret < 0) { | ||
531 | call_usermodehelper_freeinfo(sub_info); | ||
532 | return ret; | ||
533 | } | ||
534 | |||
535 | ret = call_usermodehelper_exec(sub_info, UMH_WAIT_EXEC); | ||
536 | if (ret < 0) /* Failed to execute helper, close pipe */ | ||
537 | filp_close(*filp, NULL); | ||
538 | |||
539 | return ret; | ||
540 | } | ||
541 | EXPORT_SYMBOL(call_usermodehelper_pipe); | ||
542 | |||
543 | void __init usermodehelper_init(void) | 461 | void __init usermodehelper_init(void) |
544 | { | 462 | { |
545 | khelper_wq = create_singlethread_workqueue("khelper"); | 463 | khelper_wq = create_singlethread_workqueue("khelper"); |