diff options
Diffstat (limited to 'fs/exec.c')
-rw-r--r-- | fs/exec.c | 50 |
1 files changed, 32 insertions, 18 deletions
@@ -195,7 +195,7 @@ static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos, | |||
195 | * to work from. | 195 | * to work from. |
196 | */ | 196 | */ |
197 | rlim = current->signal->rlim; | 197 | rlim = current->signal->rlim; |
198 | if (size > rlim[RLIMIT_STACK].rlim_cur / 4) { | 198 | if (size > ACCESS_ONCE(rlim[RLIMIT_STACK].rlim_cur) / 4) { |
199 | put_page(page); | 199 | put_page(page); |
200 | return NULL; | 200 | return NULL; |
201 | } | 201 | } |
@@ -246,6 +246,7 @@ static int __bprm_mm_init(struct linux_binprm *bprm) | |||
246 | vma->vm_start = vma->vm_end - PAGE_SIZE; | 246 | vma->vm_start = vma->vm_end - PAGE_SIZE; |
247 | vma->vm_flags = VM_STACK_FLAGS; | 247 | vma->vm_flags = VM_STACK_FLAGS; |
248 | vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); | 248 | vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); |
249 | INIT_LIST_HEAD(&vma->anon_vma_chain); | ||
249 | err = insert_vm_struct(mm, vma); | 250 | err = insert_vm_struct(mm, vma); |
250 | if (err) | 251 | if (err) |
251 | goto err; | 252 | goto err; |
@@ -516,7 +517,8 @@ static int shift_arg_pages(struct vm_area_struct *vma, unsigned long shift) | |||
516 | /* | 517 | /* |
517 | * cover the whole range: [new_start, old_end) | 518 | * cover the whole range: [new_start, old_end) |
518 | */ | 519 | */ |
519 | vma_adjust(vma, new_start, old_end, vma->vm_pgoff, NULL); | 520 | if (vma_adjust(vma, new_start, old_end, vma->vm_pgoff, NULL)) |
521 | return -ENOMEM; | ||
520 | 522 | ||
521 | /* | 523 | /* |
522 | * move the page tables downwards, on failure we rely on | 524 | * move the page tables downwards, on failure we rely on |
@@ -547,15 +549,13 @@ static int shift_arg_pages(struct vm_area_struct *vma, unsigned long shift) | |||
547 | tlb_finish_mmu(tlb, new_end, old_end); | 549 | tlb_finish_mmu(tlb, new_end, old_end); |
548 | 550 | ||
549 | /* | 551 | /* |
550 | * shrink the vma to just the new range. | 552 | * Shrink the vma to just the new range. Always succeeds. |
551 | */ | 553 | */ |
552 | vma_adjust(vma, new_start, new_end, vma->vm_pgoff, NULL); | 554 | vma_adjust(vma, new_start, new_end, vma->vm_pgoff, NULL); |
553 | 555 | ||
554 | return 0; | 556 | return 0; |
555 | } | 557 | } |
556 | 558 | ||
557 | #define EXTRA_STACK_VM_PAGES 20 /* random */ | ||
558 | |||
559 | /* | 559 | /* |
560 | * Finalizes the stack vm_area_struct. The flags and permissions are updated, | 560 | * Finalizes the stack vm_area_struct. The flags and permissions are updated, |
561 | * the stack is optionally relocated, and some extra space is added. | 561 | * the stack is optionally relocated, and some extra space is added. |
@@ -577,7 +577,7 @@ int setup_arg_pages(struct linux_binprm *bprm, | |||
577 | 577 | ||
578 | #ifdef CONFIG_STACK_GROWSUP | 578 | #ifdef CONFIG_STACK_GROWSUP |
579 | /* Limit stack size to 1GB */ | 579 | /* Limit stack size to 1GB */ |
580 | stack_base = current->signal->rlim[RLIMIT_STACK].rlim_max; | 580 | stack_base = rlimit_max(RLIMIT_STACK); |
581 | if (stack_base > (1 << 30)) | 581 | if (stack_base > (1 << 30)) |
582 | stack_base = 1 << 30; | 582 | stack_base = 1 << 30; |
583 | 583 | ||
@@ -630,7 +630,7 @@ int setup_arg_pages(struct linux_binprm *bprm, | |||
630 | goto out_unlock; | 630 | goto out_unlock; |
631 | } | 631 | } |
632 | 632 | ||
633 | stack_expand = EXTRA_STACK_VM_PAGES * PAGE_SIZE; | 633 | stack_expand = 131072UL; /* randomly 32*4k (or 2*64k) pages */ |
634 | stack_size = vma->vm_end - vma->vm_start; | 634 | stack_size = vma->vm_end - vma->vm_start; |
635 | /* | 635 | /* |
636 | * Align this down to a page boundary as expand_stack | 636 | * Align this down to a page boundary as expand_stack |
@@ -718,6 +718,7 @@ static int exec_mmap(struct mm_struct *mm) | |||
718 | /* Notify parent that we're no longer interested in the old VM */ | 718 | /* Notify parent that we're no longer interested in the old VM */ |
719 | tsk = current; | 719 | tsk = current; |
720 | old_mm = current->mm; | 720 | old_mm = current->mm; |
721 | sync_mm_rss(tsk, old_mm); | ||
721 | mm_release(tsk, old_mm); | 722 | mm_release(tsk, old_mm); |
722 | 723 | ||
723 | if (old_mm) { | 724 | if (old_mm) { |
@@ -1532,7 +1533,7 @@ static int format_corename(char *corename, long signr) | |||
1532 | /* core limit size */ | 1533 | /* core limit size */ |
1533 | case 'c': | 1534 | case 'c': |
1534 | rc = snprintf(out_ptr, out_end - out_ptr, | 1535 | rc = snprintf(out_ptr, out_end - out_ptr, |
1535 | "%lu", current->signal->rlim[RLIMIT_CORE].rlim_cur); | 1536 | "%lu", rlimit(RLIMIT_CORE)); |
1536 | if (rc > out_end - out_ptr) | 1537 | if (rc > out_end - out_ptr) |
1537 | goto out; | 1538 | goto out; |
1538 | out_ptr += rc; | 1539 | out_ptr += rc; |
@@ -1560,12 +1561,13 @@ out: | |||
1560 | return ispipe; | 1561 | return ispipe; |
1561 | } | 1562 | } |
1562 | 1563 | ||
1563 | static int zap_process(struct task_struct *start) | 1564 | static int zap_process(struct task_struct *start, int exit_code) |
1564 | { | 1565 | { |
1565 | struct task_struct *t; | 1566 | struct task_struct *t; |
1566 | int nr = 0; | 1567 | int nr = 0; |
1567 | 1568 | ||
1568 | start->signal->flags = SIGNAL_GROUP_EXIT; | 1569 | start->signal->flags = SIGNAL_GROUP_EXIT; |
1570 | start->signal->group_exit_code = exit_code; | ||
1569 | start->signal->group_stop_count = 0; | 1571 | start->signal->group_stop_count = 0; |
1570 | 1572 | ||
1571 | t = start; | 1573 | t = start; |
@@ -1590,8 +1592,7 @@ static inline int zap_threads(struct task_struct *tsk, struct mm_struct *mm, | |||
1590 | spin_lock_irq(&tsk->sighand->siglock); | 1592 | spin_lock_irq(&tsk->sighand->siglock); |
1591 | if (!signal_group_exit(tsk->signal)) { | 1593 | if (!signal_group_exit(tsk->signal)) { |
1592 | mm->core_state = core_state; | 1594 | mm->core_state = core_state; |
1593 | tsk->signal->group_exit_code = exit_code; | 1595 | nr = zap_process(tsk, exit_code); |
1594 | nr = zap_process(tsk); | ||
1595 | } | 1596 | } |
1596 | spin_unlock_irq(&tsk->sighand->siglock); | 1597 | spin_unlock_irq(&tsk->sighand->siglock); |
1597 | if (unlikely(nr < 0)) | 1598 | if (unlikely(nr < 0)) |
@@ -1640,7 +1641,7 @@ static inline int zap_threads(struct task_struct *tsk, struct mm_struct *mm, | |||
1640 | if (p->mm) { | 1641 | if (p->mm) { |
1641 | if (unlikely(p->mm == mm)) { | 1642 | if (unlikely(p->mm == mm)) { |
1642 | lock_task_sighand(p, &flags); | 1643 | lock_task_sighand(p, &flags); |
1643 | nr += zap_process(p); | 1644 | nr += zap_process(p, exit_code); |
1644 | unlock_task_sighand(p, &flags); | 1645 | unlock_task_sighand(p, &flags); |
1645 | } | 1646 | } |
1646 | break; | 1647 | break; |
@@ -1747,14 +1748,19 @@ void set_dumpable(struct mm_struct *mm, int value) | |||
1747 | } | 1748 | } |
1748 | } | 1749 | } |
1749 | 1750 | ||
1750 | int get_dumpable(struct mm_struct *mm) | 1751 | static int __get_dumpable(unsigned long mm_flags) |
1751 | { | 1752 | { |
1752 | int ret; | 1753 | int ret; |
1753 | 1754 | ||
1754 | ret = mm->flags & 0x3; | 1755 | ret = mm_flags & MMF_DUMPABLE_MASK; |
1755 | return (ret >= 2) ? 2 : ret; | 1756 | return (ret >= 2) ? 2 : ret; |
1756 | } | 1757 | } |
1757 | 1758 | ||
1759 | int get_dumpable(struct mm_struct *mm) | ||
1760 | { | ||
1761 | return __get_dumpable(mm->flags); | ||
1762 | } | ||
1763 | |||
1758 | static void wait_for_dump_helpers(struct file *file) | 1764 | static void wait_for_dump_helpers(struct file *file) |
1759 | { | 1765 | { |
1760 | struct pipe_inode_info *pipe; | 1766 | struct pipe_inode_info *pipe; |
@@ -1797,7 +1803,13 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs) | |||
1797 | struct coredump_params cprm = { | 1803 | struct coredump_params cprm = { |
1798 | .signr = signr, | 1804 | .signr = signr, |
1799 | .regs = regs, | 1805 | .regs = regs, |
1800 | .limit = current->signal->rlim[RLIMIT_CORE].rlim_cur, | 1806 | .limit = rlimit(RLIMIT_CORE), |
1807 | /* | ||
1808 | * We must use the same mm->flags while dumping core to avoid | ||
1809 | * inconsistency of bit flags, since this flag is not protected | ||
1810 | * by any locks. | ||
1811 | */ | ||
1812 | .mm_flags = mm->flags, | ||
1801 | }; | 1813 | }; |
1802 | 1814 | ||
1803 | audit_core_dumps(signr); | 1815 | audit_core_dumps(signr); |
@@ -1816,7 +1828,7 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs) | |||
1816 | /* | 1828 | /* |
1817 | * If another thread got here first, or we are not dumpable, bail out. | 1829 | * If another thread got here first, or we are not dumpable, bail out. |
1818 | */ | 1830 | */ |
1819 | if (mm->core_state || !get_dumpable(mm)) { | 1831 | if (mm->core_state || !__get_dumpable(cprm.mm_flags)) { |
1820 | up_write(&mm->mmap_sem); | 1832 | up_write(&mm->mmap_sem); |
1821 | put_cred(cred); | 1833 | put_cred(cred); |
1822 | goto fail; | 1834 | goto fail; |
@@ -1827,7 +1839,8 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs) | |||
1827 | * process nor do we know its entire history. We only know it | 1839 | * process nor do we know its entire history. We only know it |
1828 | * was tainted so we dump it as root in mode 2. | 1840 | * was tainted so we dump it as root in mode 2. |
1829 | */ | 1841 | */ |
1830 | if (get_dumpable(mm) == 2) { /* Setuid core dump mode */ | 1842 | if (__get_dumpable(cprm.mm_flags) == 2) { |
1843 | /* Setuid core dump mode */ | ||
1831 | flag = O_EXCL; /* Stop rewrite attacks */ | 1844 | flag = O_EXCL; /* Stop rewrite attacks */ |
1832 | cred->fsuid = 0; /* Dump root private */ | 1845 | cred->fsuid = 0; /* Dump root private */ |
1833 | } | 1846 | } |
@@ -1923,8 +1936,9 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs) | |||
1923 | /* | 1936 | /* |
1924 | * Dont allow local users get cute and trick others to coredump | 1937 | * Dont allow local users get cute and trick others to coredump |
1925 | * into their pre-created files: | 1938 | * into their pre-created files: |
1939 | * Note, this is not relevant for pipes | ||
1926 | */ | 1940 | */ |
1927 | if (inode->i_uid != current_fsuid()) | 1941 | if (!ispipe && (inode->i_uid != current_fsuid())) |
1928 | goto close_fail; | 1942 | goto close_fail; |
1929 | if (!cprm.file->f_op) | 1943 | if (!cprm.file->f_op) |
1930 | goto close_fail; | 1944 | goto close_fail; |