diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/exec.c | 63 |
1 files changed, 56 insertions, 7 deletions
@@ -1787,6 +1787,50 @@ static void wait_for_dump_helpers(struct file *file) | |||
1787 | } | 1787 | } |
1788 | 1788 | ||
1789 | 1789 | ||
1790 | /* | ||
1791 | * uhm_pipe_setup | ||
1792 | * helper function to customize the process used | ||
1793 | * to collect the core in userspace. Specifically | ||
1794 | * it sets up a pipe and installs it as fd 0 (stdin) | ||
1795 | * for the process. Returns 0 on success, or | ||
1796 | * PTR_ERR on failure. | ||
1797 | * Note that it also sets the core limit to 1. This | ||
1798 | * is a special value that we use to trap recursive | ||
1799 | * core dumps | ||
1800 | */ | ||
1801 | static int umh_pipe_setup(struct subprocess_info *info) | ||
1802 | { | ||
1803 | struct file *rp, *wp; | ||
1804 | struct fdtable *fdt; | ||
1805 | struct coredump_params *cp = (struct coredump_params *)info->data; | ||
1806 | struct files_struct *cf = current->files; | ||
1807 | |||
1808 | wp = create_write_pipe(0); | ||
1809 | if (IS_ERR(wp)) | ||
1810 | return PTR_ERR(wp); | ||
1811 | |||
1812 | rp = create_read_pipe(wp, 0); | ||
1813 | if (IS_ERR(rp)) { | ||
1814 | free_write_pipe(wp); | ||
1815 | return PTR_ERR(rp); | ||
1816 | } | ||
1817 | |||
1818 | cp->file = wp; | ||
1819 | |||
1820 | sys_close(0); | ||
1821 | fd_install(0, rp); | ||
1822 | spin_lock(&cf->file_lock); | ||
1823 | fdt = files_fdtable(cf); | ||
1824 | FD_SET(0, fdt->open_fds); | ||
1825 | FD_CLR(0, fdt->close_on_exec); | ||
1826 | spin_unlock(&cf->file_lock); | ||
1827 | |||
1828 | /* and disallow core files too */ | ||
1829 | current->signal->rlim[RLIMIT_CORE] = (struct rlimit){1, 1}; | ||
1830 | |||
1831 | return 0; | ||
1832 | } | ||
1833 | |||
1790 | void do_coredump(long signr, int exit_code, struct pt_regs *regs) | 1834 | void do_coredump(long signr, int exit_code, struct pt_regs *regs) |
1791 | { | 1835 | { |
1792 | struct core_state core_state; | 1836 | struct core_state core_state; |
@@ -1874,15 +1918,15 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs) | |||
1874 | goto fail_unlock; | 1918 | goto fail_unlock; |
1875 | 1919 | ||
1876 | if (ispipe) { | 1920 | if (ispipe) { |
1877 | if (cprm.limit == 0) { | 1921 | if (cprm.limit == 1) { |
1878 | /* | 1922 | /* |
1879 | * Normally core limits are irrelevant to pipes, since | 1923 | * Normally core limits are irrelevant to pipes, since |
1880 | * we're not writing to the file system, but we use | 1924 | * we're not writing to the file system, but we use |
1881 | * cprm.limit of 0 here as a speacial value. Any | 1925 | * cprm.limit of 1 here as a speacial value. Any |
1882 | * non-zero limit gets set to RLIM_INFINITY below, but | 1926 | * non-1 limit gets set to RLIM_INFINITY below, but |
1883 | * a limit of 0 skips the dump. This is a consistent | 1927 | * a limit of 0 skips the dump. This is a consistent |
1884 | * way to catch recursive crashes. We can still crash | 1928 | * way to catch recursive crashes. We can still crash |
1885 | * if the core_pattern binary sets RLIM_CORE = !0 | 1929 | * if the core_pattern binary sets RLIM_CORE = !1 |
1886 | * but it runs as root, and can do lots of stupid things | 1930 | * but it runs as root, and can do lots of stupid things |
1887 | * Note that we use task_tgid_vnr here to grab the pid | 1931 | * Note that we use task_tgid_vnr here to grab the pid |
1888 | * of the process group leader. That way we get the | 1932 | * of the process group leader. That way we get the |
@@ -1890,7 +1934,7 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs) | |||
1890 | * core_pattern process dies. | 1934 | * core_pattern process dies. |
1891 | */ | 1935 | */ |
1892 | printk(KERN_WARNING | 1936 | printk(KERN_WARNING |
1893 | "Process %d(%s) has RLIMIT_CORE set to 0\n", | 1937 | "Process %d(%s) has RLIMIT_CORE set to 1\n", |
1894 | task_tgid_vnr(current), current->comm); | 1938 | task_tgid_vnr(current), current->comm); |
1895 | printk(KERN_WARNING "Aborting core\n"); | 1939 | printk(KERN_WARNING "Aborting core\n"); |
1896 | goto fail_unlock; | 1940 | goto fail_unlock; |
@@ -1914,8 +1958,13 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs) | |||
1914 | cprm.limit = RLIM_INFINITY; | 1958 | cprm.limit = RLIM_INFINITY; |
1915 | 1959 | ||
1916 | /* SIGPIPE can happen, but it's just never processed */ | 1960 | /* SIGPIPE can happen, but it's just never processed */ |
1917 | if (call_usermodehelper_pipe(helper_argv[0], helper_argv, NULL, | 1961 | cprm.file = NULL; |
1918 | &cprm.file)) { | 1962 | if (call_usermodehelper_fns(helper_argv[0], helper_argv, NULL, |
1963 | UMH_WAIT_EXEC, umh_pipe_setup, | ||
1964 | NULL, &cprm)) { | ||
1965 | if (cprm.file) | ||
1966 | filp_close(cprm.file, NULL); | ||
1967 | |||
1919 | printk(KERN_INFO "Core dump to %s pipe failed\n", | 1968 | printk(KERN_INFO "Core dump to %s pipe failed\n", |
1920 | corename); | 1969 | corename); |
1921 | goto fail_dropcount; | 1970 | goto fail_dropcount; |