aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorNeil Horman <nhorman@tuxdriver.com>2009-09-23 18:56:56 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-09-24 10:21:00 -0400
commita293980c2e261bd5b0d2a77340dd04f684caff58 (patch)
tree69f2b2747548deafb146c18953ebce21ae1f02d4 /fs
parent725eae32df7754044809973034429a47e6035158 (diff)
exec: let do_coredump() limit the number of concurrent dumps to pipes
Introduce core pipe limiting sysctl. Since we can dump cores to pipe, rather than directly to the filesystem, we create a condition in which a user can create a very high load on the system simply by running bad applications. If the pipe reader specified in core_pattern is poorly written, we can have lots of ourstandig resources and processes in the system. This sysctl introduces an ability to limit that resource consumption. core_pipe_limit defines how many in-flight dumps may be run in parallel, dumps beyond this value are skipped and a note is made in the kernel log. A special value of 0 in core_pipe_limit denotes unlimited core dumps may be handled (this is the default value). [akpm@linux-foundation.org: coding-style fixes] Signed-off-by: Neil Horman <nhorman@tuxdriver.com> Reported-by: Earl Chew <earl_chew@agilent.com> Cc: Oleg Nesterov <oleg@tv-sign.ru> Cc: Andi Kleen <andi@firstfloor.org> Cc: Alan Cox <alan@lxorguk.ukuu.org.uk> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs')
-rw-r--r--fs/exec.c23
1 files changed, 18 insertions, 5 deletions
diff --git a/fs/exec.c b/fs/exec.c
index 735d9c18ec71..dc022dd15d51 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -63,6 +63,7 @@
63 63
64int core_uses_pid; 64int core_uses_pid;
65char core_pattern[CORENAME_MAX_SIZE] = "core"; 65char core_pattern[CORENAME_MAX_SIZE] = "core";
66unsigned int core_pipe_limit;
66int suid_dumpable = 0; 67int suid_dumpable = 0;
67 68
68/* The maximal length of core_pattern is also specified in sysctl.c */ 69/* The maximal length of core_pattern is also specified in sysctl.c */
@@ -1744,7 +1745,8 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs)
1744 unsigned long core_limit = current->signal->rlim[RLIMIT_CORE].rlim_cur; 1745 unsigned long core_limit = current->signal->rlim[RLIMIT_CORE].rlim_cur;
1745 char **helper_argv = NULL; 1746 char **helper_argv = NULL;
1746 int helper_argc = 0; 1747 int helper_argc = 0;
1747 char *delimit; 1748 int dump_count = 0;
1749 static atomic_t core_dump_count = ATOMIC_INIT(0);
1748 1750
1749 audit_core_dumps(signr); 1751 audit_core_dumps(signr);
1750 1752
@@ -1826,28 +1828,36 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs)
1826 goto fail_unlock; 1828 goto fail_unlock;
1827 } 1829 }
1828 1830
1831 dump_count = atomic_inc_return(&core_dump_count);
1832 if (core_pipe_limit && (core_pipe_limit < dump_count)) {
1833 printk(KERN_WARNING "Pid %d(%s) over core_pipe_limit\n",
1834 task_tgid_vnr(current), current->comm);
1835 printk(KERN_WARNING "Skipping core dump\n");
1836 goto fail_dropcount;
1837 }
1838
1829 helper_argv = argv_split(GFP_KERNEL, corename+1, &helper_argc); 1839 helper_argv = argv_split(GFP_KERNEL, corename+1, &helper_argc);
1830 if (!helper_argv) { 1840 if (!helper_argv) {
1831 printk(KERN_WARNING "%s failed to allocate memory\n", 1841 printk(KERN_WARNING "%s failed to allocate memory\n",
1832 __func__); 1842 __func__);
1833 goto fail_unlock; 1843 goto fail_dropcount;
1834 } 1844 }
1835 1845
1836 core_limit = RLIM_INFINITY; 1846 core_limit = RLIM_INFINITY;
1837 1847
1838 /* SIGPIPE can happen, but it's just never processed */ 1848 /* SIGPIPE can happen, but it's just never processed */
1839 if (call_usermodehelper_pipe(corename+1, helper_argv, NULL, 1849 if (call_usermodehelper_pipe(helper_argv[0], helper_argv, NULL,
1840 &file)) { 1850 &file)) {
1841 printk(KERN_INFO "Core dump to %s pipe failed\n", 1851 printk(KERN_INFO "Core dump to %s pipe failed\n",
1842 corename); 1852 corename);
1843 goto fail_unlock; 1853 goto fail_dropcount;
1844 } 1854 }
1845 } else 1855 } else
1846 file = filp_open(corename, 1856 file = filp_open(corename,
1847 O_CREAT | 2 | O_NOFOLLOW | O_LARGEFILE | flag, 1857 O_CREAT | 2 | O_NOFOLLOW | O_LARGEFILE | flag,
1848 0600); 1858 0600);
1849 if (IS_ERR(file)) 1859 if (IS_ERR(file))
1850 goto fail_unlock; 1860 goto fail_dropcount;
1851 inode = file->f_path.dentry->d_inode; 1861 inode = file->f_path.dentry->d_inode;
1852 if (inode->i_nlink > 1) 1862 if (inode->i_nlink > 1)
1853 goto close_fail; /* multiple links - don't dump */ 1863 goto close_fail; /* multiple links - don't dump */
@@ -1877,6 +1887,9 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs)
1877 current->signal->group_exit_code |= 0x80; 1887 current->signal->group_exit_code |= 0x80;
1878close_fail: 1888close_fail:
1879 filp_close(file, NULL); 1889 filp_close(file, NULL);
1890fail_dropcount:
1891 if (dump_count)
1892 atomic_dec(&core_dump_count);
1880fail_unlock: 1893fail_unlock:
1881 if (helper_argv) 1894 if (helper_argv)
1882 argv_free(helper_argv); 1895 argv_free(helper_argv);