aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeil Horman <nhorman@tuxdriver.com>2010-05-26 17:42:59 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-05-27 12:12:44 -0400
commit898b374af6f71041bd3bceebe257e564f3f1d458 (patch)
treeb1be6fd3cca69becfc75787eab906338f363d3cd
parenta06a4dc3a08201ff6a8a958f935b3cbf7744115f (diff)
exec: replace call_usermodehelper_pipe with use of umh init function and resolve limit
The first patch in this series introduced an init function to the call_usermodehelper api so that processes could be customized by caller. This patch takes advantage of that fact, by customizing the helper in do_coredump to create the pipe and set its core limit to one (for our recusrsion check). This lets us clean up the previous uglyness in the usermodehelper internals and factor call_usermodehelper out entirely. While I'm at it, we can also modify the helper setup to look for a core limit value of 1 rather than zero for our recursion check Signed-off-by: Neil Horman <nhorman@tuxdriver.com> Reviewed-by: Oleg Nesterov <oleg@redhat.com> Cc: Andi Kleen <andi@firstfloor.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-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");