diff options
Diffstat (limited to 'fs/exec.c')
-rw-r--r-- | fs/exec.c | 125 |
1 files changed, 84 insertions, 41 deletions
@@ -33,7 +33,7 @@ | |||
33 | #include <linux/string.h> | 33 | #include <linux/string.h> |
34 | #include <linux/init.h> | 34 | #include <linux/init.h> |
35 | #include <linux/pagemap.h> | 35 | #include <linux/pagemap.h> |
36 | #include <linux/perf_counter.h> | 36 | #include <linux/perf_event.h> |
37 | #include <linux/highmem.h> | 37 | #include <linux/highmem.h> |
38 | #include <linux/spinlock.h> | 38 | #include <linux/spinlock.h> |
39 | #include <linux/key.h> | 39 | #include <linux/key.h> |
@@ -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 */ |
@@ -845,6 +847,9 @@ static int de_thread(struct task_struct *tsk) | |||
845 | sig->notify_count = 0; | 847 | sig->notify_count = 0; |
846 | 848 | ||
847 | no_thread_group: | 849 | no_thread_group: |
850 | if (current->mm) | ||
851 | setmax_mm_hiwater_rss(&sig->maxrss, current->mm); | ||
852 | |||
848 | exit_itimers(sig); | 853 | exit_itimers(sig); |
849 | flush_itimer_signals(); | 854 | flush_itimer_signals(); |
850 | 855 | ||
@@ -923,7 +928,7 @@ void set_task_comm(struct task_struct *tsk, char *buf) | |||
923 | task_lock(tsk); | 928 | task_lock(tsk); |
924 | strlcpy(tsk->comm, buf, sizeof(tsk->comm)); | 929 | strlcpy(tsk->comm, buf, sizeof(tsk->comm)); |
925 | task_unlock(tsk); | 930 | task_unlock(tsk); |
926 | perf_counter_comm(tsk); | 931 | perf_event_comm(tsk); |
927 | } | 932 | } |
928 | 933 | ||
929 | int flush_old_exec(struct linux_binprm * bprm) | 934 | int flush_old_exec(struct linux_binprm * bprm) |
@@ -997,7 +1002,7 @@ int flush_old_exec(struct linux_binprm * bprm) | |||
997 | * security domain: | 1002 | * security domain: |
998 | */ | 1003 | */ |
999 | if (!get_dumpable(current->mm)) | 1004 | if (!get_dumpable(current->mm)) |
1000 | perf_counter_exit_task(current); | 1005 | perf_event_exit_task(current); |
1001 | 1006 | ||
1002 | /* An exec changes our domain. We are no longer part of the thread | 1007 | /* An exec changes our domain. We are no longer part of the thread |
1003 | group */ | 1008 | group */ |
@@ -1354,6 +1359,8 @@ int do_execve(char * filename, | |||
1354 | if (retval < 0) | 1359 | if (retval < 0) |
1355 | goto out; | 1360 | goto out; |
1356 | 1361 | ||
1362 | current->stack_start = current->mm->start_stack; | ||
1363 | |||
1357 | /* execve succeeded */ | 1364 | /* execve succeeded */ |
1358 | current->fs->in_exec = 0; | 1365 | current->fs->in_exec = 0; |
1359 | current->in_execve = 0; | 1366 | current->in_execve = 0; |
@@ -1388,18 +1395,16 @@ out_ret: | |||
1388 | return retval; | 1395 | return retval; |
1389 | } | 1396 | } |
1390 | 1397 | ||
1391 | int set_binfmt(struct linux_binfmt *new) | 1398 | void set_binfmt(struct linux_binfmt *new) |
1392 | { | 1399 | { |
1393 | struct linux_binfmt *old = current->binfmt; | 1400 | struct mm_struct *mm = current->mm; |
1394 | 1401 | ||
1395 | if (new) { | 1402 | if (mm->binfmt) |
1396 | if (!try_module_get(new->module)) | 1403 | module_put(mm->binfmt->module); |
1397 | return -1; | 1404 | |
1398 | } | 1405 | mm->binfmt = new; |
1399 | current->binfmt = new; | 1406 | if (new) |
1400 | if (old) | 1407 | __module_get(new->module); |
1401 | module_put(old->module); | ||
1402 | return 0; | ||
1403 | } | 1408 | } |
1404 | 1409 | ||
1405 | EXPORT_SYMBOL(set_binfmt); | 1410 | EXPORT_SYMBOL(set_binfmt); |
@@ -1723,6 +1728,29 @@ int get_dumpable(struct mm_struct *mm) | |||
1723 | return (ret >= 2) ? 2 : ret; | 1728 | return (ret >= 2) ? 2 : ret; |
1724 | } | 1729 | } |
1725 | 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 | |||
1726 | 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) |
1727 | { | 1755 | { |
1728 | struct core_state core_state; | 1756 | struct core_state core_state; |
@@ -1739,11 +1767,12 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs) | |||
1739 | unsigned long core_limit = current->signal->rlim[RLIMIT_CORE].rlim_cur; | 1767 | unsigned long core_limit = current->signal->rlim[RLIMIT_CORE].rlim_cur; |
1740 | char **helper_argv = NULL; | 1768 | char **helper_argv = NULL; |
1741 | int helper_argc = 0; | 1769 | int helper_argc = 0; |
1742 | char *delimit; | 1770 | int dump_count = 0; |
1771 | static atomic_t core_dump_count = ATOMIC_INIT(0); | ||
1743 | 1772 | ||
1744 | audit_core_dumps(signr); | 1773 | audit_core_dumps(signr); |
1745 | 1774 | ||
1746 | binfmt = current->binfmt; | 1775 | binfmt = mm->binfmt; |
1747 | if (!binfmt || !binfmt->core_dump) | 1776 | if (!binfmt || !binfmt->core_dump) |
1748 | goto fail; | 1777 | goto fail; |
1749 | 1778 | ||
@@ -1794,54 +1823,63 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs) | |||
1794 | lock_kernel(); | 1823 | lock_kernel(); |
1795 | ispipe = format_corename(corename, signr); | 1824 | ispipe = format_corename(corename, signr); |
1796 | unlock_kernel(); | 1825 | unlock_kernel(); |
1797 | /* | 1826 | |
1798 | * Don't bother to check the RLIMIT_CORE value if core_pattern points | ||
1799 | * to a pipe. Since we're not writing directly to the filesystem | ||
1800 | * RLIMIT_CORE doesn't really apply, as no actual core file will be | ||
1801 | * created unless the pipe reader choses to write out the core file | ||
1802 | * at which point file size limits and permissions will be imposed | ||
1803 | * as it does with any other process | ||
1804 | */ | ||
1805 | if ((!ispipe) && (core_limit < binfmt->min_coredump)) | 1827 | if ((!ispipe) && (core_limit < binfmt->min_coredump)) |
1806 | goto fail_unlock; | 1828 | goto fail_unlock; |
1807 | 1829 | ||
1808 | 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 | |||
1809 | helper_argv = argv_split(GFP_KERNEL, corename+1, &helper_argc); | 1861 | helper_argv = argv_split(GFP_KERNEL, corename+1, &helper_argc); |
1810 | if (!helper_argv) { | 1862 | if (!helper_argv) { |
1811 | printk(KERN_WARNING "%s failed to allocate memory\n", | 1863 | printk(KERN_WARNING "%s failed to allocate memory\n", |
1812 | __func__); | 1864 | __func__); |
1813 | goto fail_unlock; | 1865 | goto fail_dropcount; |
1814 | } | ||
1815 | /* Terminate the string before the first option */ | ||
1816 | delimit = strchr(corename, ' '); | ||
1817 | if (delimit) | ||
1818 | *delimit = '\0'; | ||
1819 | delimit = strrchr(helper_argv[0], '/'); | ||
1820 | if (delimit) | ||
1821 | delimit++; | ||
1822 | else | ||
1823 | delimit = helper_argv[0]; | ||
1824 | if (!strcmp(delimit, current->comm)) { | ||
1825 | printk(KERN_NOTICE "Recursive core dump detected, " | ||
1826 | "aborting\n"); | ||
1827 | goto fail_unlock; | ||
1828 | } | 1866 | } |
1829 | 1867 | ||
1830 | core_limit = RLIM_INFINITY; | 1868 | core_limit = RLIM_INFINITY; |
1831 | 1869 | ||
1832 | /* SIGPIPE can happen, but it's just never processed */ | 1870 | /* SIGPIPE can happen, but it's just never processed */ |
1833 | if (call_usermodehelper_pipe(corename+1, helper_argv, NULL, | 1871 | if (call_usermodehelper_pipe(helper_argv[0], helper_argv, NULL, |
1834 | &file)) { | 1872 | &file)) { |
1835 | printk(KERN_INFO "Core dump to %s pipe failed\n", | 1873 | printk(KERN_INFO "Core dump to %s pipe failed\n", |
1836 | corename); | 1874 | corename); |
1837 | goto fail_unlock; | 1875 | goto fail_dropcount; |
1838 | } | 1876 | } |
1839 | } else | 1877 | } else |
1840 | file = filp_open(corename, | 1878 | file = filp_open(corename, |
1841 | O_CREAT | 2 | O_NOFOLLOW | O_LARGEFILE | flag, | 1879 | O_CREAT | 2 | O_NOFOLLOW | O_LARGEFILE | flag, |
1842 | 0600); | 1880 | 0600); |
1843 | if (IS_ERR(file)) | 1881 | if (IS_ERR(file)) |
1844 | goto fail_unlock; | 1882 | goto fail_dropcount; |
1845 | inode = file->f_path.dentry->d_inode; | 1883 | inode = file->f_path.dentry->d_inode; |
1846 | if (inode->i_nlink > 1) | 1884 | if (inode->i_nlink > 1) |
1847 | goto close_fail; /* multiple links - don't dump */ | 1885 | goto close_fail; /* multiple links - don't dump */ |
@@ -1870,7 +1908,12 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs) | |||
1870 | if (retval) | 1908 | if (retval) |
1871 | current->signal->group_exit_code |= 0x80; | 1909 | current->signal->group_exit_code |= 0x80; |
1872 | close_fail: | 1910 | close_fail: |
1911 | if (ispipe && core_pipe_limit) | ||
1912 | wait_for_dump_helpers(file); | ||
1873 | filp_close(file, NULL); | 1913 | filp_close(file, NULL); |
1914 | fail_dropcount: | ||
1915 | if (dump_count) | ||
1916 | atomic_dec(&core_dump_count); | ||
1874 | fail_unlock: | 1917 | fail_unlock: |
1875 | if (helper_argv) | 1918 | if (helper_argv) |
1876 | argv_free(helper_argv); | 1919 | argv_free(helper_argv); |