diff options
author | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2010-05-31 06:07:15 -0400 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2010-05-31 06:07:15 -0400 |
commit | e37c83c06c2690157a989df40dc99a6b61c9ea15 (patch) | |
tree | 024dfb8b2c9abeec9ca7cb0c0136c276d9aacc91 /fs/exec.c | |
parent | ce1f7d30766f6549db6fa0b9e595e0d26a5b7d9a (diff) | |
parent | 67a3e12b05e055c0415c556a315a3d3eb637e29e (diff) |
Merge commit 'v2.6.35-rc1' into for-2.6.36
Diffstat (limited to 'fs/exec.c')
-rw-r--r-- | fs/exec.c | 204 |
1 files changed, 120 insertions, 84 deletions
@@ -242,9 +242,10 @@ static int __bprm_mm_init(struct linux_binprm *bprm) | |||
242 | * use STACK_TOP because that can depend on attributes which aren't | 242 | * use STACK_TOP because that can depend on attributes which aren't |
243 | * configured yet. | 243 | * configured yet. |
244 | */ | 244 | */ |
245 | BUG_ON(VM_STACK_FLAGS & VM_STACK_INCOMPLETE_SETUP); | ||
245 | vma->vm_end = STACK_TOP_MAX; | 246 | vma->vm_end = STACK_TOP_MAX; |
246 | vma->vm_start = vma->vm_end - PAGE_SIZE; | 247 | vma->vm_start = vma->vm_end - PAGE_SIZE; |
247 | vma->vm_flags = VM_STACK_FLAGS; | 248 | vma->vm_flags = VM_STACK_FLAGS | VM_STACK_INCOMPLETE_SETUP; |
248 | vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); | 249 | vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); |
249 | INIT_LIST_HEAD(&vma->anon_vma_chain); | 250 | INIT_LIST_HEAD(&vma->anon_vma_chain); |
250 | err = insert_vm_struct(mm, vma); | 251 | err = insert_vm_struct(mm, vma); |
@@ -616,6 +617,7 @@ int setup_arg_pages(struct linux_binprm *bprm, | |||
616 | else if (executable_stack == EXSTACK_DISABLE_X) | 617 | else if (executable_stack == EXSTACK_DISABLE_X) |
617 | vm_flags &= ~VM_EXEC; | 618 | vm_flags &= ~VM_EXEC; |
618 | vm_flags |= mm->def_flags; | 619 | vm_flags |= mm->def_flags; |
620 | vm_flags |= VM_STACK_INCOMPLETE_SETUP; | ||
619 | 621 | ||
620 | ret = mprotect_fixup(vma, &prev, vma->vm_start, vma->vm_end, | 622 | ret = mprotect_fixup(vma, &prev, vma->vm_start, vma->vm_end, |
621 | vm_flags); | 623 | vm_flags); |
@@ -630,6 +632,9 @@ int setup_arg_pages(struct linux_binprm *bprm, | |||
630 | goto out_unlock; | 632 | goto out_unlock; |
631 | } | 633 | } |
632 | 634 | ||
635 | /* mprotect_fixup is overkill to remove the temporary stack flags */ | ||
636 | vma->vm_flags &= ~VM_STACK_INCOMPLETE_SETUP; | ||
637 | |||
633 | stack_expand = 131072UL; /* randomly 32*4k (or 2*64k) pages */ | 638 | stack_expand = 131072UL; /* randomly 32*4k (or 2*64k) pages */ |
634 | stack_size = vma->vm_end - vma->vm_start; | 639 | stack_size = vma->vm_end - vma->vm_start; |
635 | /* | 640 | /* |
@@ -763,7 +768,6 @@ static int de_thread(struct task_struct *tsk) | |||
763 | struct signal_struct *sig = tsk->signal; | 768 | struct signal_struct *sig = tsk->signal; |
764 | struct sighand_struct *oldsighand = tsk->sighand; | 769 | struct sighand_struct *oldsighand = tsk->sighand; |
765 | spinlock_t *lock = &oldsighand->siglock; | 770 | spinlock_t *lock = &oldsighand->siglock; |
766 | int count; | ||
767 | 771 | ||
768 | if (thread_group_empty(tsk)) | 772 | if (thread_group_empty(tsk)) |
769 | goto no_thread_group; | 773 | goto no_thread_group; |
@@ -780,13 +784,13 @@ static int de_thread(struct task_struct *tsk) | |||
780 | spin_unlock_irq(lock); | 784 | spin_unlock_irq(lock); |
781 | return -EAGAIN; | 785 | return -EAGAIN; |
782 | } | 786 | } |
787 | |||
783 | sig->group_exit_task = tsk; | 788 | sig->group_exit_task = tsk; |
784 | zap_other_threads(tsk); | 789 | sig->notify_count = zap_other_threads(tsk); |
790 | if (!thread_group_leader(tsk)) | ||
791 | sig->notify_count--; | ||
785 | 792 | ||
786 | /* Account for the thread group leader hanging around: */ | 793 | while (sig->notify_count) { |
787 | count = thread_group_leader(tsk) ? 1 : 2; | ||
788 | sig->notify_count = count; | ||
789 | while (atomic_read(&sig->count) > count) { | ||
790 | __set_current_state(TASK_UNINTERRUPTIBLE); | 794 | __set_current_state(TASK_UNINTERRUPTIBLE); |
791 | spin_unlock_irq(lock); | 795 | spin_unlock_irq(lock); |
792 | schedule(); | 796 | schedule(); |
@@ -1387,8 +1391,6 @@ int do_execve(char * filename, | |||
1387 | if (retval < 0) | 1391 | if (retval < 0) |
1388 | goto out; | 1392 | goto out; |
1389 | 1393 | ||
1390 | current->stack_start = current->mm->start_stack; | ||
1391 | |||
1392 | /* execve succeeded */ | 1394 | /* execve succeeded */ |
1393 | current->fs->in_exec = 0; | 1395 | current->fs->in_exec = 0; |
1394 | current->in_execve = 0; | 1396 | current->in_execve = 0; |
@@ -1659,12 +1661,15 @@ static int coredump_wait(int exit_code, struct core_state *core_state) | |||
1659 | struct task_struct *tsk = current; | 1661 | struct task_struct *tsk = current; |
1660 | struct mm_struct *mm = tsk->mm; | 1662 | struct mm_struct *mm = tsk->mm; |
1661 | struct completion *vfork_done; | 1663 | struct completion *vfork_done; |
1662 | int core_waiters; | 1664 | int core_waiters = -EBUSY; |
1663 | 1665 | ||
1664 | init_completion(&core_state->startup); | 1666 | init_completion(&core_state->startup); |
1665 | core_state->dumper.task = tsk; | 1667 | core_state->dumper.task = tsk; |
1666 | core_state->dumper.next = NULL; | 1668 | core_state->dumper.next = NULL; |
1667 | core_waiters = zap_threads(tsk, mm, core_state, exit_code); | 1669 | |
1670 | down_write(&mm->mmap_sem); | ||
1671 | if (!mm->core_state) | ||
1672 | core_waiters = zap_threads(tsk, mm, core_state, exit_code); | ||
1668 | up_write(&mm->mmap_sem); | 1673 | up_write(&mm->mmap_sem); |
1669 | 1674 | ||
1670 | if (unlikely(core_waiters < 0)) | 1675 | if (unlikely(core_waiters < 0)) |
@@ -1784,21 +1789,61 @@ static void wait_for_dump_helpers(struct file *file) | |||
1784 | } | 1789 | } |
1785 | 1790 | ||
1786 | 1791 | ||
1792 | /* | ||
1793 | * uhm_pipe_setup | ||
1794 | * helper function to customize the process used | ||
1795 | * to collect the core in userspace. Specifically | ||
1796 | * it sets up a pipe and installs it as fd 0 (stdin) | ||
1797 | * for the process. Returns 0 on success, or | ||
1798 | * PTR_ERR on failure. | ||
1799 | * Note that it also sets the core limit to 1. This | ||
1800 | * is a special value that we use to trap recursive | ||
1801 | * core dumps | ||
1802 | */ | ||
1803 | static int umh_pipe_setup(struct subprocess_info *info) | ||
1804 | { | ||
1805 | struct file *rp, *wp; | ||
1806 | struct fdtable *fdt; | ||
1807 | struct coredump_params *cp = (struct coredump_params *)info->data; | ||
1808 | struct files_struct *cf = current->files; | ||
1809 | |||
1810 | wp = create_write_pipe(0); | ||
1811 | if (IS_ERR(wp)) | ||
1812 | return PTR_ERR(wp); | ||
1813 | |||
1814 | rp = create_read_pipe(wp, 0); | ||
1815 | if (IS_ERR(rp)) { | ||
1816 | free_write_pipe(wp); | ||
1817 | return PTR_ERR(rp); | ||
1818 | } | ||
1819 | |||
1820 | cp->file = wp; | ||
1821 | |||
1822 | sys_close(0); | ||
1823 | fd_install(0, rp); | ||
1824 | spin_lock(&cf->file_lock); | ||
1825 | fdt = files_fdtable(cf); | ||
1826 | FD_SET(0, fdt->open_fds); | ||
1827 | FD_CLR(0, fdt->close_on_exec); | ||
1828 | spin_unlock(&cf->file_lock); | ||
1829 | |||
1830 | /* and disallow core files too */ | ||
1831 | current->signal->rlim[RLIMIT_CORE] = (struct rlimit){1, 1}; | ||
1832 | |||
1833 | return 0; | ||
1834 | } | ||
1835 | |||
1787 | void do_coredump(long signr, int exit_code, struct pt_regs *regs) | 1836 | void do_coredump(long signr, int exit_code, struct pt_regs *regs) |
1788 | { | 1837 | { |
1789 | struct core_state core_state; | 1838 | struct core_state core_state; |
1790 | char corename[CORENAME_MAX_SIZE + 1]; | 1839 | char corename[CORENAME_MAX_SIZE + 1]; |
1791 | struct mm_struct *mm = current->mm; | 1840 | struct mm_struct *mm = current->mm; |
1792 | struct linux_binfmt * binfmt; | 1841 | struct linux_binfmt * binfmt; |
1793 | struct inode * inode; | ||
1794 | const struct cred *old_cred; | 1842 | const struct cred *old_cred; |
1795 | struct cred *cred; | 1843 | struct cred *cred; |
1796 | int retval = 0; | 1844 | int retval = 0; |
1797 | int flag = 0; | 1845 | int flag = 0; |
1798 | int ispipe = 0; | 1846 | int ispipe; |
1799 | char **helper_argv = NULL; | ||
1800 | int helper_argc = 0; | ||
1801 | int dump_count = 0; | ||
1802 | static atomic_t core_dump_count = ATOMIC_INIT(0); | 1847 | static atomic_t core_dump_count = ATOMIC_INIT(0); |
1803 | struct coredump_params cprm = { | 1848 | struct coredump_params cprm = { |
1804 | .signr = signr, | 1849 | .signr = signr, |
@@ -1817,23 +1862,12 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs) | |||
1817 | binfmt = mm->binfmt; | 1862 | binfmt = mm->binfmt; |
1818 | if (!binfmt || !binfmt->core_dump) | 1863 | if (!binfmt || !binfmt->core_dump) |
1819 | goto fail; | 1864 | goto fail; |
1820 | 1865 | if (!__get_dumpable(cprm.mm_flags)) | |
1821 | cred = prepare_creds(); | ||
1822 | if (!cred) { | ||
1823 | retval = -ENOMEM; | ||
1824 | goto fail; | 1866 | goto fail; |
1825 | } | ||
1826 | 1867 | ||
1827 | down_write(&mm->mmap_sem); | 1868 | cred = prepare_creds(); |
1828 | /* | 1869 | if (!cred) |
1829 | * If another thread got here first, or we are not dumpable, bail out. | ||
1830 | */ | ||
1831 | if (mm->core_state || !__get_dumpable(cprm.mm_flags)) { | ||
1832 | up_write(&mm->mmap_sem); | ||
1833 | put_cred(cred); | ||
1834 | goto fail; | 1870 | goto fail; |
1835 | } | ||
1836 | |||
1837 | /* | 1871 | /* |
1838 | * We cannot trust fsuid as being the "true" uid of the | 1872 | * We cannot trust fsuid as being the "true" uid of the |
1839 | * process nor do we know its entire history. We only know it | 1873 | * process nor do we know its entire history. We only know it |
@@ -1846,10 +1880,8 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs) | |||
1846 | } | 1880 | } |
1847 | 1881 | ||
1848 | retval = coredump_wait(exit_code, &core_state); | 1882 | retval = coredump_wait(exit_code, &core_state); |
1849 | if (retval < 0) { | 1883 | if (retval < 0) |
1850 | put_cred(cred); | 1884 | goto fail_creds; |
1851 | goto fail; | ||
1852 | } | ||
1853 | 1885 | ||
1854 | old_cred = override_creds(cred); | 1886 | old_cred = override_creds(cred); |
1855 | 1887 | ||
@@ -1867,19 +1899,19 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs) | |||
1867 | ispipe = format_corename(corename, signr); | 1899 | ispipe = format_corename(corename, signr); |
1868 | unlock_kernel(); | 1900 | unlock_kernel(); |
1869 | 1901 | ||
1870 | if ((!ispipe) && (cprm.limit < binfmt->min_coredump)) | ||
1871 | goto fail_unlock; | ||
1872 | |||
1873 | if (ispipe) { | 1902 | if (ispipe) { |
1874 | if (cprm.limit == 0) { | 1903 | int dump_count; |
1904 | char **helper_argv; | ||
1905 | |||
1906 | if (cprm.limit == 1) { | ||
1875 | /* | 1907 | /* |
1876 | * Normally core limits are irrelevant to pipes, since | 1908 | * Normally core limits are irrelevant to pipes, since |
1877 | * we're not writing to the file system, but we use | 1909 | * we're not writing to the file system, but we use |
1878 | * cprm.limit of 0 here as a speacial value. Any | 1910 | * cprm.limit of 1 here as a speacial value. Any |
1879 | * non-zero limit gets set to RLIM_INFINITY below, but | 1911 | * non-1 limit gets set to RLIM_INFINITY below, but |
1880 | * a limit of 0 skips the dump. This is a consistent | 1912 | * a limit of 0 skips the dump. This is a consistent |
1881 | * way to catch recursive crashes. We can still crash | 1913 | * way to catch recursive crashes. We can still crash |
1882 | * if the core_pattern binary sets RLIM_CORE = !0 | 1914 | * if the core_pattern binary sets RLIM_CORE = !1 |
1883 | * but it runs as root, and can do lots of stupid things | 1915 | * but it runs as root, and can do lots of stupid things |
1884 | * Note that we use task_tgid_vnr here to grab the pid | 1916 | * Note that we use task_tgid_vnr here to grab the pid |
1885 | * of the process group leader. That way we get the | 1917 | * of the process group leader. That way we get the |
@@ -1887,11 +1919,12 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs) | |||
1887 | * core_pattern process dies. | 1919 | * core_pattern process dies. |
1888 | */ | 1920 | */ |
1889 | printk(KERN_WARNING | 1921 | printk(KERN_WARNING |
1890 | "Process %d(%s) has RLIMIT_CORE set to 0\n", | 1922 | "Process %d(%s) has RLIMIT_CORE set to 1\n", |
1891 | task_tgid_vnr(current), current->comm); | 1923 | task_tgid_vnr(current), current->comm); |
1892 | printk(KERN_WARNING "Aborting core\n"); | 1924 | printk(KERN_WARNING "Aborting core\n"); |
1893 | goto fail_unlock; | 1925 | goto fail_unlock; |
1894 | } | 1926 | } |
1927 | cprm.limit = RLIM_INFINITY; | ||
1895 | 1928 | ||
1896 | dump_count = atomic_inc_return(&core_dump_count); | 1929 | dump_count = atomic_inc_return(&core_dump_count); |
1897 | if (core_pipe_limit && (core_pipe_limit < dump_count)) { | 1930 | if (core_pipe_limit && (core_pipe_limit < dump_count)) { |
@@ -1901,71 +1934,74 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs) | |||
1901 | goto fail_dropcount; | 1934 | goto fail_dropcount; |
1902 | } | 1935 | } |
1903 | 1936 | ||
1904 | helper_argv = argv_split(GFP_KERNEL, corename+1, &helper_argc); | 1937 | helper_argv = argv_split(GFP_KERNEL, corename+1, NULL); |
1905 | if (!helper_argv) { | 1938 | if (!helper_argv) { |
1906 | printk(KERN_WARNING "%s failed to allocate memory\n", | 1939 | printk(KERN_WARNING "%s failed to allocate memory\n", |
1907 | __func__); | 1940 | __func__); |
1908 | goto fail_dropcount; | 1941 | goto fail_dropcount; |
1909 | } | 1942 | } |
1910 | 1943 | ||
1911 | cprm.limit = RLIM_INFINITY; | 1944 | retval = call_usermodehelper_fns(helper_argv[0], helper_argv, |
1912 | 1945 | NULL, UMH_WAIT_EXEC, umh_pipe_setup, | |
1913 | /* SIGPIPE can happen, but it's just never processed */ | 1946 | NULL, &cprm); |
1914 | if (call_usermodehelper_pipe(helper_argv[0], helper_argv, NULL, | 1947 | argv_free(helper_argv); |
1915 | &cprm.file)) { | 1948 | if (retval) { |
1916 | printk(KERN_INFO "Core dump to %s pipe failed\n", | 1949 | printk(KERN_INFO "Core dump to %s pipe failed\n", |
1917 | corename); | 1950 | corename); |
1918 | goto fail_dropcount; | 1951 | goto close_fail; |
1919 | } | 1952 | } |
1920 | } else | 1953 | } else { |
1954 | struct inode *inode; | ||
1955 | |||
1956 | if (cprm.limit < binfmt->min_coredump) | ||
1957 | goto fail_unlock; | ||
1958 | |||
1921 | cprm.file = filp_open(corename, | 1959 | cprm.file = filp_open(corename, |
1922 | O_CREAT | 2 | O_NOFOLLOW | O_LARGEFILE | flag, | 1960 | O_CREAT | 2 | O_NOFOLLOW | O_LARGEFILE | flag, |
1923 | 0600); | 1961 | 0600); |
1924 | if (IS_ERR(cprm.file)) | 1962 | if (IS_ERR(cprm.file)) |
1925 | goto fail_dropcount; | 1963 | goto fail_unlock; |
1926 | inode = cprm.file->f_path.dentry->d_inode; | ||
1927 | if (inode->i_nlink > 1) | ||
1928 | goto close_fail; /* multiple links - don't dump */ | ||
1929 | if (!ispipe && d_unhashed(cprm.file->f_path.dentry)) | ||
1930 | goto close_fail; | ||
1931 | |||
1932 | /* AK: actually i see no reason to not allow this for named pipes etc., | ||
1933 | but keep the previous behaviour for now. */ | ||
1934 | if (!ispipe && !S_ISREG(inode->i_mode)) | ||
1935 | goto close_fail; | ||
1936 | /* | ||
1937 | * Dont allow local users get cute and trick others to coredump | ||
1938 | * into their pre-created files: | ||
1939 | * Note, this is not relevant for pipes | ||
1940 | */ | ||
1941 | if (!ispipe && (inode->i_uid != current_fsuid())) | ||
1942 | goto close_fail; | ||
1943 | if (!cprm.file->f_op) | ||
1944 | goto close_fail; | ||
1945 | if (!cprm.file->f_op->write) | ||
1946 | goto close_fail; | ||
1947 | if (!ispipe && | ||
1948 | do_truncate(cprm.file->f_path.dentry, 0, 0, cprm.file) != 0) | ||
1949 | goto close_fail; | ||
1950 | 1964 | ||
1951 | retval = binfmt->core_dump(&cprm); | 1965 | inode = cprm.file->f_path.dentry->d_inode; |
1966 | if (inode->i_nlink > 1) | ||
1967 | goto close_fail; | ||
1968 | if (d_unhashed(cprm.file->f_path.dentry)) | ||
1969 | goto close_fail; | ||
1970 | /* | ||
1971 | * AK: actually i see no reason to not allow this for named | ||
1972 | * pipes etc, but keep the previous behaviour for now. | ||
1973 | */ | ||
1974 | if (!S_ISREG(inode->i_mode)) | ||
1975 | goto close_fail; | ||
1976 | /* | ||
1977 | * Dont allow local users get cute and trick others to coredump | ||
1978 | * into their pre-created files. | ||
1979 | */ | ||
1980 | if (inode->i_uid != current_fsuid()) | ||
1981 | goto close_fail; | ||
1982 | if (!cprm.file->f_op || !cprm.file->f_op->write) | ||
1983 | goto close_fail; | ||
1984 | if (do_truncate(cprm.file->f_path.dentry, 0, 0, cprm.file)) | ||
1985 | goto close_fail; | ||
1986 | } | ||
1952 | 1987 | ||
1988 | retval = binfmt->core_dump(&cprm); | ||
1953 | if (retval) | 1989 | if (retval) |
1954 | current->signal->group_exit_code |= 0x80; | 1990 | current->signal->group_exit_code |= 0x80; |
1955 | close_fail: | 1991 | |
1956 | if (ispipe && core_pipe_limit) | 1992 | if (ispipe && core_pipe_limit) |
1957 | wait_for_dump_helpers(cprm.file); | 1993 | wait_for_dump_helpers(cprm.file); |
1958 | filp_close(cprm.file, NULL); | 1994 | close_fail: |
1995 | if (cprm.file) | ||
1996 | filp_close(cprm.file, NULL); | ||
1959 | fail_dropcount: | 1997 | fail_dropcount: |
1960 | if (dump_count) | 1998 | if (ispipe) |
1961 | atomic_dec(&core_dump_count); | 1999 | atomic_dec(&core_dump_count); |
1962 | fail_unlock: | 2000 | fail_unlock: |
1963 | if (helper_argv) | 2001 | coredump_finish(mm); |
1964 | argv_free(helper_argv); | ||
1965 | |||
1966 | revert_creds(old_cred); | 2002 | revert_creds(old_cred); |
2003 | fail_creds: | ||
1967 | put_cred(cred); | 2004 | put_cred(cred); |
1968 | coredump_finish(mm); | ||
1969 | fail: | 2005 | fail: |
1970 | return; | 2006 | return; |
1971 | } | 2007 | } |