aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/exec.c63
-rw-r--r--include/linux/kmod.h7
-rw-r--r--kernel/kmod.c82
3 files changed, 56 insertions, 96 deletions
diff --git a/fs/exec.c b/fs/exec.c
index 9badbc0bfb1d..63f459cf20df 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -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 */
1801static 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
1790void do_coredump(long signr, int exit_code, struct pt_regs *regs) 1834void 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 */
76void call_usermodehelper_setkeys(struct subprocess_info *info, 75void call_usermodehelper_setkeys(struct subprocess_info *info,
77 struct key *session_keyring); 76 struct key *session_keyring);
78int call_usermodehelper_stdinpipe(struct subprocess_info *sub_info,
79 struct file **filp);
80void call_usermodehelper_setfns(struct subprocess_info *info, 77void 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
133extern void usermodehelper_init(void); 130extern void usermodehelper_init(void);
134 131
135struct file;
136extern int call_usermodehelper_pipe(char *path, char *argv[], char *envp[],
137 struct file **filp);
138
139extern int usermodehelper_disable(void); 132extern int usermodehelper_disable(void);
140extern void usermodehelper_enable(void); 133extern 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,
429EXPORT_SYMBOL(call_usermodehelper_setfns); 412EXPORT_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 */
439int 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}
458EXPORT_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}
505EXPORT_SYMBOL(call_usermodehelper_exec); 459EXPORT_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 */
518int 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}
541EXPORT_SYMBOL(call_usermodehelper_pipe);
542
543void __init usermodehelper_init(void) 461void __init usermodehelper_init(void)
544{ 462{
545 khelper_wq = create_singlethread_workqueue("khelper"); 463 khelper_wq = create_singlethread_workqueue("khelper");