diff options
Diffstat (limited to 'fs/exec.c')
| -rw-r--r-- | fs/exec.c | 133 |
1 files changed, 87 insertions, 46 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 */ |
| @@ -622,10 +624,8 @@ int setup_arg_pages(struct linux_binprm *bprm, | |||
| 622 | /* Move stack pages down in memory. */ | 624 | /* Move stack pages down in memory. */ |
| 623 | if (stack_shift) { | 625 | if (stack_shift) { |
| 624 | ret = shift_arg_pages(vma, stack_shift); | 626 | ret = shift_arg_pages(vma, stack_shift); |
| 625 | if (ret) { | 627 | if (ret) |
| 626 | up_write(&mm->mmap_sem); | 628 | goto out_unlock; |
| 627 | return ret; | ||
| 628 | } | ||
| 629 | } | 629 | } |
| 630 | 630 | ||
| 631 | #ifdef CONFIG_STACK_GROWSUP | 631 | #ifdef CONFIG_STACK_GROWSUP |
| @@ -639,7 +639,7 @@ int setup_arg_pages(struct linux_binprm *bprm, | |||
| 639 | 639 | ||
| 640 | out_unlock: | 640 | out_unlock: |
| 641 | up_write(&mm->mmap_sem); | 641 | up_write(&mm->mmap_sem); |
| 642 | return 0; | 642 | return ret; |
| 643 | } | 643 | } |
| 644 | EXPORT_SYMBOL(setup_arg_pages); | 644 | EXPORT_SYMBOL(setup_arg_pages); |
| 645 | 645 | ||
| @@ -845,6 +845,9 @@ static int de_thread(struct task_struct *tsk) | |||
| 845 | sig->notify_count = 0; | 845 | sig->notify_count = 0; |
| 846 | 846 | ||
| 847 | no_thread_group: | 847 | no_thread_group: |
| 848 | if (current->mm) | ||
| 849 | setmax_mm_hiwater_rss(&sig->maxrss, current->mm); | ||
| 850 | |||
| 848 | exit_itimers(sig); | 851 | exit_itimers(sig); |
| 849 | flush_itimer_signals(); | 852 | flush_itimer_signals(); |
| 850 | 853 | ||
| @@ -923,7 +926,7 @@ void set_task_comm(struct task_struct *tsk, char *buf) | |||
| 923 | task_lock(tsk); | 926 | task_lock(tsk); |
| 924 | strlcpy(tsk->comm, buf, sizeof(tsk->comm)); | 927 | strlcpy(tsk->comm, buf, sizeof(tsk->comm)); |
| 925 | task_unlock(tsk); | 928 | task_unlock(tsk); |
| 926 | perf_counter_comm(tsk); | 929 | perf_event_comm(tsk); |
| 927 | } | 930 | } |
| 928 | 931 | ||
| 929 | int flush_old_exec(struct linux_binprm * bprm) | 932 | int flush_old_exec(struct linux_binprm * bprm) |
| @@ -997,7 +1000,7 @@ int flush_old_exec(struct linux_binprm * bprm) | |||
| 997 | * security domain: | 1000 | * security domain: |
| 998 | */ | 1001 | */ |
| 999 | if (!get_dumpable(current->mm)) | 1002 | if (!get_dumpable(current->mm)) |
| 1000 | perf_counter_exit_task(current); | 1003 | perf_event_exit_task(current); |
| 1001 | 1004 | ||
| 1002 | /* An exec changes our domain. We are no longer part of the thread | 1005 | /* An exec changes our domain. We are no longer part of the thread |
| 1003 | group */ | 1006 | group */ |
| @@ -1354,6 +1357,8 @@ int do_execve(char * filename, | |||
| 1354 | if (retval < 0) | 1357 | if (retval < 0) |
| 1355 | goto out; | 1358 | goto out; |
| 1356 | 1359 | ||
| 1360 | current->stack_start = current->mm->start_stack; | ||
| 1361 | |||
| 1357 | /* execve succeeded */ | 1362 | /* execve succeeded */ |
| 1358 | current->fs->in_exec = 0; | 1363 | current->fs->in_exec = 0; |
| 1359 | current->in_execve = 0; | 1364 | current->in_execve = 0; |
| @@ -1388,18 +1393,16 @@ out_ret: | |||
| 1388 | return retval; | 1393 | return retval; |
| 1389 | } | 1394 | } |
| 1390 | 1395 | ||
| 1391 | int set_binfmt(struct linux_binfmt *new) | 1396 | void set_binfmt(struct linux_binfmt *new) |
| 1392 | { | 1397 | { |
| 1393 | struct linux_binfmt *old = current->binfmt; | 1398 | struct mm_struct *mm = current->mm; |
| 1394 | 1399 | ||
| 1395 | if (new) { | 1400 | if (mm->binfmt) |
| 1396 | if (!try_module_get(new->module)) | 1401 | module_put(mm->binfmt->module); |
| 1397 | return -1; | 1402 | |
| 1398 | } | 1403 | mm->binfmt = new; |
| 1399 | current->binfmt = new; | 1404 | if (new) |
| 1400 | if (old) | 1405 | __module_get(new->module); |
| 1401 | module_put(old->module); | ||
| 1402 | return 0; | ||
| 1403 | } | 1406 | } |
| 1404 | 1407 | ||
| 1405 | EXPORT_SYMBOL(set_binfmt); | 1408 | EXPORT_SYMBOL(set_binfmt); |
| @@ -1723,6 +1726,29 @@ int get_dumpable(struct mm_struct *mm) | |||
| 1723 | return (ret >= 2) ? 2 : ret; | 1726 | return (ret >= 2) ? 2 : ret; |
| 1724 | } | 1727 | } |
| 1725 | 1728 | ||
| 1729 | static void wait_for_dump_helpers(struct file *file) | ||
| 1730 | { | ||
| 1731 | struct pipe_inode_info *pipe; | ||
| 1732 | |||
| 1733 | pipe = file->f_path.dentry->d_inode->i_pipe; | ||
| 1734 | |||
| 1735 | pipe_lock(pipe); | ||
| 1736 | pipe->readers++; | ||
| 1737 | pipe->writers--; | ||
| 1738 | |||
| 1739 | while ((pipe->readers > 1) && (!signal_pending(current))) { | ||
| 1740 | wake_up_interruptible_sync(&pipe->wait); | ||
| 1741 | kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN); | ||
| 1742 | pipe_wait(pipe); | ||
| 1743 | } | ||
| 1744 | |||
| 1745 | pipe->readers--; | ||
| 1746 | pipe->writers++; | ||
| 1747 | pipe_unlock(pipe); | ||
| 1748 | |||
| 1749 | } | ||
| 1750 | |||
| 1751 | |||
| 1726 | void do_coredump(long signr, int exit_code, struct pt_regs *regs) | 1752 | void do_coredump(long signr, int exit_code, struct pt_regs *regs) |
| 1727 | { | 1753 | { |
| 1728 | struct core_state core_state; | 1754 | struct core_state core_state; |
| @@ -1739,11 +1765,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; | 1765 | unsigned long core_limit = current->signal->rlim[RLIMIT_CORE].rlim_cur; |
| 1740 | char **helper_argv = NULL; | 1766 | char **helper_argv = NULL; |
| 1741 | int helper_argc = 0; | 1767 | int helper_argc = 0; |
| 1742 | char *delimit; | 1768 | int dump_count = 0; |
| 1769 | static atomic_t core_dump_count = ATOMIC_INIT(0); | ||
| 1743 | 1770 | ||
| 1744 | audit_core_dumps(signr); | 1771 | audit_core_dumps(signr); |
| 1745 | 1772 | ||
| 1746 | binfmt = current->binfmt; | 1773 | binfmt = mm->binfmt; |
| 1747 | if (!binfmt || !binfmt->core_dump) | 1774 | if (!binfmt || !binfmt->core_dump) |
| 1748 | goto fail; | 1775 | goto fail; |
| 1749 | 1776 | ||
| @@ -1794,54 +1821,63 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs) | |||
| 1794 | lock_kernel(); | 1821 | lock_kernel(); |
| 1795 | ispipe = format_corename(corename, signr); | 1822 | ispipe = format_corename(corename, signr); |
| 1796 | unlock_kernel(); | 1823 | unlock_kernel(); |
| 1797 | /* | 1824 | |
| 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)) | 1825 | if ((!ispipe) && (core_limit < binfmt->min_coredump)) |
| 1806 | goto fail_unlock; | 1826 | goto fail_unlock; |
| 1807 | 1827 | ||
| 1808 | if (ispipe) { | 1828 | if (ispipe) { |
| 1829 | if (core_limit == 0) { | ||
| 1830 | /* | ||
| 1831 | * Normally core limits are irrelevant to pipes, since | ||
| 1832 | * we're not writing to the file system, but we use | ||
| 1833 | * core_limit of 0 here as a speacial value. Any | ||
| 1834 | * non-zero limit gets set to RLIM_INFINITY below, but | ||
| 1835 | * a limit of 0 skips the dump. This is a consistent | ||
| 1836 | * way to catch recursive crashes. We can still crash | ||
| 1837 | * if the core_pattern binary sets RLIM_CORE = !0 | ||
| 1838 | * but it runs as root, and can do lots of stupid things | ||
| 1839 | * Note that we use task_tgid_vnr here to grab the pid | ||
| 1840 | * of the process group leader. That way we get the | ||
| 1841 | * right pid if a thread in a multi-threaded | ||
| 1842 | * core_pattern process dies. | ||
| 1843 | */ | ||
| 1844 | printk(KERN_WARNING | ||
| 1845 | "Process %d(%s) has RLIMIT_CORE set to 0\n", | ||
| 1846 | task_tgid_vnr(current), current->comm); | ||
| 1847 | printk(KERN_WARNING "Aborting core\n"); | ||
| 1848 | goto fail_unlock; | ||
| 1849 | } | ||
| 1850 | |||
| 1851 | dump_count = atomic_inc_return(&core_dump_count); | ||
| 1852 | if (core_pipe_limit && (core_pipe_limit < dump_count)) { | ||
| 1853 | printk(KERN_WARNING "Pid %d(%s) over core_pipe_limit\n", | ||
| 1854 | task_tgid_vnr(current), current->comm); | ||
| 1855 | printk(KERN_WARNING "Skipping core dump\n"); | ||
| 1856 | goto fail_dropcount; | ||
| 1857 | } | ||
| 1858 | |||
| 1809 | helper_argv = argv_split(GFP_KERNEL, corename+1, &helper_argc); | 1859 | helper_argv = argv_split(GFP_KERNEL, corename+1, &helper_argc); |
| 1810 | if (!helper_argv) { | 1860 | if (!helper_argv) { |
| 1811 | printk(KERN_WARNING "%s failed to allocate memory\n", | 1861 | printk(KERN_WARNING "%s failed to allocate memory\n", |
| 1812 | __func__); | 1862 | __func__); |
| 1813 | goto fail_unlock; | 1863 | 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 | } | 1864 | } |
| 1829 | 1865 | ||
| 1830 | core_limit = RLIM_INFINITY; | 1866 | core_limit = RLIM_INFINITY; |
| 1831 | 1867 | ||
| 1832 | /* SIGPIPE can happen, but it's just never processed */ | 1868 | /* SIGPIPE can happen, but it's just never processed */ |
| 1833 | if (call_usermodehelper_pipe(corename+1, helper_argv, NULL, | 1869 | if (call_usermodehelper_pipe(helper_argv[0], helper_argv, NULL, |
| 1834 | &file)) { | 1870 | &file)) { |
| 1835 | printk(KERN_INFO "Core dump to %s pipe failed\n", | 1871 | printk(KERN_INFO "Core dump to %s pipe failed\n", |
| 1836 | corename); | 1872 | corename); |
| 1837 | goto fail_unlock; | 1873 | goto fail_dropcount; |
| 1838 | } | 1874 | } |
| 1839 | } else | 1875 | } else |
| 1840 | file = filp_open(corename, | 1876 | file = filp_open(corename, |
| 1841 | O_CREAT | 2 | O_NOFOLLOW | O_LARGEFILE | flag, | 1877 | O_CREAT | 2 | O_NOFOLLOW | O_LARGEFILE | flag, |
| 1842 | 0600); | 1878 | 0600); |
| 1843 | if (IS_ERR(file)) | 1879 | if (IS_ERR(file)) |
| 1844 | goto fail_unlock; | 1880 | goto fail_dropcount; |
| 1845 | inode = file->f_path.dentry->d_inode; | 1881 | inode = file->f_path.dentry->d_inode; |
| 1846 | if (inode->i_nlink > 1) | 1882 | if (inode->i_nlink > 1) |
| 1847 | goto close_fail; /* multiple links - don't dump */ | 1883 | goto close_fail; /* multiple links - don't dump */ |
| @@ -1870,7 +1906,12 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs) | |||
| 1870 | if (retval) | 1906 | if (retval) |
| 1871 | current->signal->group_exit_code |= 0x80; | 1907 | current->signal->group_exit_code |= 0x80; |
| 1872 | close_fail: | 1908 | close_fail: |
| 1909 | if (ispipe && core_pipe_limit) | ||
| 1910 | wait_for_dump_helpers(file); | ||
| 1873 | filp_close(file, NULL); | 1911 | filp_close(file, NULL); |
| 1912 | fail_dropcount: | ||
| 1913 | if (dump_count) | ||
| 1914 | atomic_dec(&core_dump_count); | ||
| 1874 | fail_unlock: | 1915 | fail_unlock: |
| 1875 | if (helper_argv) | 1916 | if (helper_argv) |
| 1876 | argv_free(helper_argv); | 1917 | argv_free(helper_argv); |
