diff options
Diffstat (limited to 'fs/exec.c')
-rw-r--r-- | fs/exec.c | 188 |
1 files changed, 122 insertions, 66 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 */ |
@@ -1016,6 +1021,35 @@ out: | |||
1016 | EXPORT_SYMBOL(flush_old_exec); | 1021 | EXPORT_SYMBOL(flush_old_exec); |
1017 | 1022 | ||
1018 | /* | 1023 | /* |
1024 | * Prepare credentials and lock ->cred_guard_mutex. | ||
1025 | * install_exec_creds() commits the new creds and drops the lock. | ||
1026 | * Or, if exec fails before, free_bprm() should release ->cred and | ||
1027 | * and unlock. | ||
1028 | */ | ||
1029 | int prepare_bprm_creds(struct linux_binprm *bprm) | ||
1030 | { | ||
1031 | if (mutex_lock_interruptible(¤t->cred_guard_mutex)) | ||
1032 | return -ERESTARTNOINTR; | ||
1033 | |||
1034 | bprm->cred = prepare_exec_creds(); | ||
1035 | if (likely(bprm->cred)) | ||
1036 | return 0; | ||
1037 | |||
1038 | mutex_unlock(¤t->cred_guard_mutex); | ||
1039 | return -ENOMEM; | ||
1040 | } | ||
1041 | |||
1042 | void free_bprm(struct linux_binprm *bprm) | ||
1043 | { | ||
1044 | free_arg_pages(bprm); | ||
1045 | if (bprm->cred) { | ||
1046 | mutex_unlock(¤t->cred_guard_mutex); | ||
1047 | abort_creds(bprm->cred); | ||
1048 | } | ||
1049 | kfree(bprm); | ||
1050 | } | ||
1051 | |||
1052 | /* | ||
1019 | * install the new credentials for this executable | 1053 | * install the new credentials for this executable |
1020 | */ | 1054 | */ |
1021 | void install_exec_creds(struct linux_binprm *bprm) | 1055 | void install_exec_creds(struct linux_binprm *bprm) |
@@ -1024,12 +1058,13 @@ void install_exec_creds(struct linux_binprm *bprm) | |||
1024 | 1058 | ||
1025 | commit_creds(bprm->cred); | 1059 | commit_creds(bprm->cred); |
1026 | bprm->cred = NULL; | 1060 | bprm->cred = NULL; |
1027 | 1061 | /* | |
1028 | /* cred_guard_mutex must be held at least to this point to prevent | 1062 | * cred_guard_mutex must be held at least to this point to prevent |
1029 | * ptrace_attach() from altering our determination of the task's | 1063 | * ptrace_attach() from altering our determination of the task's |
1030 | * credentials; any time after this it may be unlocked */ | 1064 | * credentials; any time after this it may be unlocked. |
1031 | 1065 | */ | |
1032 | security_bprm_committed_creds(bprm); | 1066 | security_bprm_committed_creds(bprm); |
1067 | mutex_unlock(¤t->cred_guard_mutex); | ||
1033 | } | 1068 | } |
1034 | EXPORT_SYMBOL(install_exec_creds); | 1069 | EXPORT_SYMBOL(install_exec_creds); |
1035 | 1070 | ||
@@ -1246,14 +1281,6 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs) | |||
1246 | 1281 | ||
1247 | EXPORT_SYMBOL(search_binary_handler); | 1282 | EXPORT_SYMBOL(search_binary_handler); |
1248 | 1283 | ||
1249 | void free_bprm(struct linux_binprm *bprm) | ||
1250 | { | ||
1251 | free_arg_pages(bprm); | ||
1252 | if (bprm->cred) | ||
1253 | abort_creds(bprm->cred); | ||
1254 | kfree(bprm); | ||
1255 | } | ||
1256 | |||
1257 | /* | 1284 | /* |
1258 | * sys_execve() executes a new program. | 1285 | * sys_execve() executes a new program. |
1259 | */ | 1286 | */ |
@@ -1277,20 +1304,15 @@ int do_execve(char * filename, | |||
1277 | if (!bprm) | 1304 | if (!bprm) |
1278 | goto out_files; | 1305 | goto out_files; |
1279 | 1306 | ||
1280 | retval = -ERESTARTNOINTR; | 1307 | retval = prepare_bprm_creds(bprm); |
1281 | if (mutex_lock_interruptible(¤t->cred_guard_mutex)) | 1308 | if (retval) |
1282 | goto out_free; | 1309 | goto out_free; |
1283 | current->in_execve = 1; | ||
1284 | |||
1285 | retval = -ENOMEM; | ||
1286 | bprm->cred = prepare_exec_creds(); | ||
1287 | if (!bprm->cred) | ||
1288 | goto out_unlock; | ||
1289 | 1310 | ||
1290 | retval = check_unsafe_exec(bprm); | 1311 | retval = check_unsafe_exec(bprm); |
1291 | if (retval < 0) | 1312 | if (retval < 0) |
1292 | goto out_unlock; | 1313 | goto out_free; |
1293 | clear_in_exec = retval; | 1314 | clear_in_exec = retval; |
1315 | current->in_execve = 1; | ||
1294 | 1316 | ||
1295 | file = open_exec(filename); | 1317 | file = open_exec(filename); |
1296 | retval = PTR_ERR(file); | 1318 | retval = PTR_ERR(file); |
@@ -1337,10 +1359,11 @@ int do_execve(char * filename, | |||
1337 | if (retval < 0) | 1359 | if (retval < 0) |
1338 | goto out; | 1360 | goto out; |
1339 | 1361 | ||
1362 | current->stack_start = current->mm->start_stack; | ||
1363 | |||
1340 | /* execve succeeded */ | 1364 | /* execve succeeded */ |
1341 | current->fs->in_exec = 0; | 1365 | current->fs->in_exec = 0; |
1342 | current->in_execve = 0; | 1366 | current->in_execve = 0; |
1343 | mutex_unlock(¤t->cred_guard_mutex); | ||
1344 | acct_update_integrals(current); | 1367 | acct_update_integrals(current); |
1345 | free_bprm(bprm); | 1368 | free_bprm(bprm); |
1346 | if (displaced) | 1369 | if (displaced) |
@@ -1360,10 +1383,7 @@ out_file: | |||
1360 | out_unmark: | 1383 | out_unmark: |
1361 | if (clear_in_exec) | 1384 | if (clear_in_exec) |
1362 | current->fs->in_exec = 0; | 1385 | current->fs->in_exec = 0; |
1363 | |||
1364 | out_unlock: | ||
1365 | current->in_execve = 0; | 1386 | current->in_execve = 0; |
1366 | mutex_unlock(¤t->cred_guard_mutex); | ||
1367 | 1387 | ||
1368 | out_free: | 1388 | out_free: |
1369 | free_bprm(bprm); | 1389 | free_bprm(bprm); |
@@ -1375,18 +1395,16 @@ out_ret: | |||
1375 | return retval; | 1395 | return retval; |
1376 | } | 1396 | } |
1377 | 1397 | ||
1378 | int set_binfmt(struct linux_binfmt *new) | 1398 | void set_binfmt(struct linux_binfmt *new) |
1379 | { | 1399 | { |
1380 | struct linux_binfmt *old = current->binfmt; | 1400 | struct mm_struct *mm = current->mm; |
1381 | 1401 | ||
1382 | if (new) { | 1402 | if (mm->binfmt) |
1383 | if (!try_module_get(new->module)) | 1403 | module_put(mm->binfmt->module); |
1384 | return -1; | 1404 | |
1385 | } | 1405 | mm->binfmt = new; |
1386 | current->binfmt = new; | 1406 | if (new) |
1387 | if (old) | 1407 | __module_get(new->module); |
1388 | module_put(old->module); | ||
1389 | return 0; | ||
1390 | } | 1408 | } |
1391 | 1409 | ||
1392 | EXPORT_SYMBOL(set_binfmt); | 1410 | EXPORT_SYMBOL(set_binfmt); |
@@ -1710,6 +1728,29 @@ int get_dumpable(struct mm_struct *mm) | |||
1710 | return (ret >= 2) ? 2 : ret; | 1728 | return (ret >= 2) ? 2 : ret; |
1711 | } | 1729 | } |
1712 | 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 | |||
1713 | 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) |
1714 | { | 1755 | { |
1715 | struct core_state core_state; | 1756 | struct core_state core_state; |
@@ -1726,11 +1767,12 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs) | |||
1726 | unsigned long core_limit = current->signal->rlim[RLIMIT_CORE].rlim_cur; | 1767 | unsigned long core_limit = current->signal->rlim[RLIMIT_CORE].rlim_cur; |
1727 | char **helper_argv = NULL; | 1768 | char **helper_argv = NULL; |
1728 | int helper_argc = 0; | 1769 | int helper_argc = 0; |
1729 | char *delimit; | 1770 | int dump_count = 0; |
1771 | static atomic_t core_dump_count = ATOMIC_INIT(0); | ||
1730 | 1772 | ||
1731 | audit_core_dumps(signr); | 1773 | audit_core_dumps(signr); |
1732 | 1774 | ||
1733 | binfmt = current->binfmt; | 1775 | binfmt = mm->binfmt; |
1734 | if (!binfmt || !binfmt->core_dump) | 1776 | if (!binfmt || !binfmt->core_dump) |
1735 | goto fail; | 1777 | goto fail; |
1736 | 1778 | ||
@@ -1781,54 +1823,63 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs) | |||
1781 | lock_kernel(); | 1823 | lock_kernel(); |
1782 | ispipe = format_corename(corename, signr); | 1824 | ispipe = format_corename(corename, signr); |
1783 | unlock_kernel(); | 1825 | unlock_kernel(); |
1784 | /* | 1826 | |
1785 | * Don't bother to check the RLIMIT_CORE value if core_pattern points | ||
1786 | * to a pipe. Since we're not writing directly to the filesystem | ||
1787 | * RLIMIT_CORE doesn't really apply, as no actual core file will be | ||
1788 | * created unless the pipe reader choses to write out the core file | ||
1789 | * at which point file size limits and permissions will be imposed | ||
1790 | * as it does with any other process | ||
1791 | */ | ||
1792 | if ((!ispipe) && (core_limit < binfmt->min_coredump)) | 1827 | if ((!ispipe) && (core_limit < binfmt->min_coredump)) |
1793 | goto fail_unlock; | 1828 | goto fail_unlock; |
1794 | 1829 | ||
1795 | 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 | |||
1796 | helper_argv = argv_split(GFP_KERNEL, corename+1, &helper_argc); | 1861 | helper_argv = argv_split(GFP_KERNEL, corename+1, &helper_argc); |
1797 | if (!helper_argv) { | 1862 | if (!helper_argv) { |
1798 | printk(KERN_WARNING "%s failed to allocate memory\n", | 1863 | printk(KERN_WARNING "%s failed to allocate memory\n", |
1799 | __func__); | 1864 | __func__); |
1800 | goto fail_unlock; | 1865 | goto fail_dropcount; |
1801 | } | ||
1802 | /* Terminate the string before the first option */ | ||
1803 | delimit = strchr(corename, ' '); | ||
1804 | if (delimit) | ||
1805 | *delimit = '\0'; | ||
1806 | delimit = strrchr(helper_argv[0], '/'); | ||
1807 | if (delimit) | ||
1808 | delimit++; | ||
1809 | else | ||
1810 | delimit = helper_argv[0]; | ||
1811 | if (!strcmp(delimit, current->comm)) { | ||
1812 | printk(KERN_NOTICE "Recursive core dump detected, " | ||
1813 | "aborting\n"); | ||
1814 | goto fail_unlock; | ||
1815 | } | 1866 | } |
1816 | 1867 | ||
1817 | core_limit = RLIM_INFINITY; | 1868 | core_limit = RLIM_INFINITY; |
1818 | 1869 | ||
1819 | /* SIGPIPE can happen, but it's just never processed */ | 1870 | /* SIGPIPE can happen, but it's just never processed */ |
1820 | if (call_usermodehelper_pipe(corename+1, helper_argv, NULL, | 1871 | if (call_usermodehelper_pipe(helper_argv[0], helper_argv, NULL, |
1821 | &file)) { | 1872 | &file)) { |
1822 | printk(KERN_INFO "Core dump to %s pipe failed\n", | 1873 | printk(KERN_INFO "Core dump to %s pipe failed\n", |
1823 | corename); | 1874 | corename); |
1824 | goto fail_unlock; | 1875 | goto fail_dropcount; |
1825 | } | 1876 | } |
1826 | } else | 1877 | } else |
1827 | file = filp_open(corename, | 1878 | file = filp_open(corename, |
1828 | O_CREAT | 2 | O_NOFOLLOW | O_LARGEFILE | flag, | 1879 | O_CREAT | 2 | O_NOFOLLOW | O_LARGEFILE | flag, |
1829 | 0600); | 1880 | 0600); |
1830 | if (IS_ERR(file)) | 1881 | if (IS_ERR(file)) |
1831 | goto fail_unlock; | 1882 | goto fail_dropcount; |
1832 | inode = file->f_path.dentry->d_inode; | 1883 | inode = file->f_path.dentry->d_inode; |
1833 | if (inode->i_nlink > 1) | 1884 | if (inode->i_nlink > 1) |
1834 | goto close_fail; /* multiple links - don't dump */ | 1885 | goto close_fail; /* multiple links - don't dump */ |
@@ -1857,7 +1908,12 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs) | |||
1857 | if (retval) | 1908 | if (retval) |
1858 | current->signal->group_exit_code |= 0x80; | 1909 | current->signal->group_exit_code |= 0x80; |
1859 | close_fail: | 1910 | close_fail: |
1911 | if (ispipe && core_pipe_limit) | ||
1912 | wait_for_dump_helpers(file); | ||
1860 | filp_close(file, NULL); | 1913 | filp_close(file, NULL); |
1914 | fail_dropcount: | ||
1915 | if (dump_count) | ||
1916 | atomic_dec(&core_dump_count); | ||
1861 | fail_unlock: | 1917 | fail_unlock: |
1862 | if (helper_argv) | 1918 | if (helper_argv) |
1863 | argv_free(helper_argv); | 1919 | argv_free(helper_argv); |