diff options
Diffstat (limited to 'fs/exec.c')
-rw-r--r-- | fs/exec.c | 114 |
1 files changed, 76 insertions, 38 deletions
@@ -55,6 +55,7 @@ | |||
55 | #include <linux/kmod.h> | 55 | #include <linux/kmod.h> |
56 | #include <linux/fsnotify.h> | 56 | #include <linux/fsnotify.h> |
57 | #include <linux/fs_struct.h> | 57 | #include <linux/fs_struct.h> |
58 | #include <linux/pipe_fs_i.h> | ||
58 | 59 | ||
59 | #include <asm/uaccess.h> | 60 | #include <asm/uaccess.h> |
60 | #include <asm/mmu_context.h> | 61 | #include <asm/mmu_context.h> |
@@ -63,6 +64,7 @@ | |||
63 | 64 | ||
64 | int core_uses_pid; | 65 | int core_uses_pid; |
65 | char core_pattern[CORENAME_MAX_SIZE] = "core"; | 66 | char core_pattern[CORENAME_MAX_SIZE] = "core"; |
67 | unsigned int core_pipe_limit; | ||
66 | int suid_dumpable = 0; | 68 | int suid_dumpable = 0; |
67 | 69 | ||
68 | /* The maximal length of core_pattern is also specified in sysctl.c */ | 70 | /* The maximal length of core_pattern is also specified in sysctl.c */ |
@@ -1393,18 +1395,16 @@ out_ret: | |||
1393 | return retval; | 1395 | return retval; |
1394 | } | 1396 | } |
1395 | 1397 | ||
1396 | int set_binfmt(struct linux_binfmt *new) | 1398 | void set_binfmt(struct linux_binfmt *new) |
1397 | { | 1399 | { |
1398 | struct linux_binfmt *old = current->binfmt; | 1400 | struct mm_struct *mm = current->mm; |
1399 | 1401 | ||
1400 | if (new) { | 1402 | if (mm->binfmt) |
1401 | if (!try_module_get(new->module)) | 1403 | module_put(mm->binfmt->module); |
1402 | return -1; | 1404 | |
1403 | } | 1405 | mm->binfmt = new; |
1404 | current->binfmt = new; | 1406 | if (new) |
1405 | if (old) | 1407 | __module_get(new->module); |
1406 | module_put(old->module); | ||
1407 | return 0; | ||
1408 | } | 1408 | } |
1409 | 1409 | ||
1410 | EXPORT_SYMBOL(set_binfmt); | 1410 | EXPORT_SYMBOL(set_binfmt); |
@@ -1728,6 +1728,29 @@ int get_dumpable(struct mm_struct *mm) | |||
1728 | return (ret >= 2) ? 2 : ret; | 1728 | return (ret >= 2) ? 2 : ret; |
1729 | } | 1729 | } |
1730 | 1730 | ||
1731 | static void wait_for_dump_helpers(struct file *file) | ||
1732 | { | ||
1733 | struct pipe_inode_info *pipe; | ||
1734 | |||
1735 | pipe = file->f_path.dentry->d_inode->i_pipe; | ||
1736 | |||
1737 | pipe_lock(pipe); | ||
1738 | pipe->readers++; | ||
1739 | pipe->writers--; | ||
1740 | |||
1741 | while ((pipe->readers > 1) && (!signal_pending(current))) { | ||
1742 | wake_up_interruptible_sync(&pipe->wait); | ||
1743 | kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN); | ||
1744 | pipe_wait(pipe); | ||
1745 | } | ||
1746 | |||
1747 | pipe->readers--; | ||
1748 | pipe->writers++; | ||
1749 | pipe_unlock(pipe); | ||
1750 | |||
1751 | } | ||
1752 | |||
1753 | |||
1731 | void do_coredump(long signr, int exit_code, struct pt_regs *regs) | 1754 | void do_coredump(long signr, int exit_code, struct pt_regs *regs) |
1732 | { | 1755 | { |
1733 | struct core_state core_state; | 1756 | struct core_state core_state; |
@@ -1744,11 +1767,12 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs) | |||
1744 | unsigned long core_limit = current->signal->rlim[RLIMIT_CORE].rlim_cur; | 1767 | unsigned long core_limit = current->signal->rlim[RLIMIT_CORE].rlim_cur; |
1745 | char **helper_argv = NULL; | 1768 | char **helper_argv = NULL; |
1746 | int helper_argc = 0; | 1769 | int helper_argc = 0; |
1747 | char *delimit; | 1770 | int dump_count = 0; |
1771 | static atomic_t core_dump_count = ATOMIC_INIT(0); | ||
1748 | 1772 | ||
1749 | audit_core_dumps(signr); | 1773 | audit_core_dumps(signr); |
1750 | 1774 | ||
1751 | binfmt = current->binfmt; | 1775 | binfmt = mm->binfmt; |
1752 | if (!binfmt || !binfmt->core_dump) | 1776 | if (!binfmt || !binfmt->core_dump) |
1753 | goto fail; | 1777 | goto fail; |
1754 | 1778 | ||
@@ -1799,54 +1823,63 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs) | |||
1799 | lock_kernel(); | 1823 | lock_kernel(); |
1800 | ispipe = format_corename(corename, signr); | 1824 | ispipe = format_corename(corename, signr); |
1801 | unlock_kernel(); | 1825 | unlock_kernel(); |
1802 | /* | 1826 | |
1803 | * Don't bother to check the RLIMIT_CORE value if core_pattern points | ||
1804 | * to a pipe. Since we're not writing directly to the filesystem | ||
1805 | * RLIMIT_CORE doesn't really apply, as no actual core file will be | ||
1806 | * created unless the pipe reader choses to write out the core file | ||
1807 | * at which point file size limits and permissions will be imposed | ||
1808 | * as it does with any other process | ||
1809 | */ | ||
1810 | if ((!ispipe) && (core_limit < binfmt->min_coredump)) | 1827 | if ((!ispipe) && (core_limit < binfmt->min_coredump)) |
1811 | goto fail_unlock; | 1828 | goto fail_unlock; |
1812 | 1829 | ||
1813 | if (ispipe) { | 1830 | if (ispipe) { |
1831 | if (core_limit == 0) { | ||
1832 | /* | ||
1833 | * Normally core limits are irrelevant to pipes, since | ||
1834 | * we're not writing to the file system, but we use | ||
1835 | * core_limit of 0 here as a speacial value. Any | ||
1836 | * non-zero limit gets set to RLIM_INFINITY below, but | ||
1837 | * a limit of 0 skips the dump. This is a consistent | ||
1838 | * way to catch recursive crashes. We can still crash | ||
1839 | * if the core_pattern binary sets RLIM_CORE = !0 | ||
1840 | * but it runs as root, and can do lots of stupid things | ||
1841 | * Note that we use task_tgid_vnr here to grab the pid | ||
1842 | * of the process group leader. That way we get the | ||
1843 | * right pid if a thread in a multi-threaded | ||
1844 | * core_pattern process dies. | ||
1845 | */ | ||
1846 | printk(KERN_WARNING | ||
1847 | "Process %d(%s) has RLIMIT_CORE set to 0\n", | ||
1848 | task_tgid_vnr(current), current->comm); | ||
1849 | printk(KERN_WARNING "Aborting core\n"); | ||
1850 | goto fail_unlock; | ||
1851 | } | ||
1852 | |||
1853 | dump_count = atomic_inc_return(&core_dump_count); | ||
1854 | if (core_pipe_limit && (core_pipe_limit < dump_count)) { | ||
1855 | printk(KERN_WARNING "Pid %d(%s) over core_pipe_limit\n", | ||
1856 | task_tgid_vnr(current), current->comm); | ||
1857 | printk(KERN_WARNING "Skipping core dump\n"); | ||
1858 | goto fail_dropcount; | ||
1859 | } | ||
1860 | |||
1814 | helper_argv = argv_split(GFP_KERNEL, corename+1, &helper_argc); | 1861 | helper_argv = argv_split(GFP_KERNEL, corename+1, &helper_argc); |
1815 | if (!helper_argv) { | 1862 | if (!helper_argv) { |
1816 | printk(KERN_WARNING "%s failed to allocate memory\n", | 1863 | printk(KERN_WARNING "%s failed to allocate memory\n", |
1817 | __func__); | 1864 | __func__); |
1818 | goto fail_unlock; | 1865 | goto fail_dropcount; |
1819 | } | ||
1820 | /* Terminate the string before the first option */ | ||
1821 | delimit = strchr(corename, ' '); | ||
1822 | if (delimit) | ||
1823 | *delimit = '\0'; | ||
1824 | delimit = strrchr(helper_argv[0], '/'); | ||
1825 | if (delimit) | ||
1826 | delimit++; | ||
1827 | else | ||
1828 | delimit = helper_argv[0]; | ||
1829 | if (!strcmp(delimit, current->comm)) { | ||
1830 | printk(KERN_NOTICE "Recursive core dump detected, " | ||
1831 | "aborting\n"); | ||
1832 | goto fail_unlock; | ||
1833 | } | 1866 | } |
1834 | 1867 | ||
1835 | core_limit = RLIM_INFINITY; | 1868 | core_limit = RLIM_INFINITY; |
1836 | 1869 | ||
1837 | /* SIGPIPE can happen, but it's just never processed */ | 1870 | /* SIGPIPE can happen, but it's just never processed */ |
1838 | if (call_usermodehelper_pipe(corename+1, helper_argv, NULL, | 1871 | if (call_usermodehelper_pipe(helper_argv[0], helper_argv, NULL, |
1839 | &file)) { | 1872 | &file)) { |
1840 | printk(KERN_INFO "Core dump to %s pipe failed\n", | 1873 | printk(KERN_INFO "Core dump to %s pipe failed\n", |
1841 | corename); | 1874 | corename); |
1842 | goto fail_unlock; | 1875 | goto fail_dropcount; |
1843 | } | 1876 | } |
1844 | } else | 1877 | } else |
1845 | file = filp_open(corename, | 1878 | file = filp_open(corename, |
1846 | O_CREAT | 2 | O_NOFOLLOW | O_LARGEFILE | flag, | 1879 | O_CREAT | 2 | O_NOFOLLOW | O_LARGEFILE | flag, |
1847 | 0600); | 1880 | 0600); |
1848 | if (IS_ERR(file)) | 1881 | if (IS_ERR(file)) |
1849 | goto fail_unlock; | 1882 | goto fail_dropcount; |
1850 | inode = file->f_path.dentry->d_inode; | 1883 | inode = file->f_path.dentry->d_inode; |
1851 | if (inode->i_nlink > 1) | 1884 | if (inode->i_nlink > 1) |
1852 | goto close_fail; /* multiple links - don't dump */ | 1885 | goto close_fail; /* multiple links - don't dump */ |
@@ -1875,7 +1908,12 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs) | |||
1875 | if (retval) | 1908 | if (retval) |
1876 | current->signal->group_exit_code |= 0x80; | 1909 | current->signal->group_exit_code |= 0x80; |
1877 | close_fail: | 1910 | close_fail: |
1911 | if (ispipe && core_pipe_limit) | ||
1912 | wait_for_dump_helpers(file); | ||
1878 | filp_close(file, NULL); | 1913 | filp_close(file, NULL); |
1914 | fail_dropcount: | ||
1915 | if (dump_count) | ||
1916 | atomic_dec(&core_dump_count); | ||
1879 | fail_unlock: | 1917 | fail_unlock: |
1880 | if (helper_argv) | 1918 | if (helper_argv) |
1881 | argv_free(helper_argv); | 1919 | argv_free(helper_argv); |