diff options
-rw-r--r-- | fs/binfmt_elf.c | 14 | ||||
-rw-r--r-- | fs/binfmt_elf_fdpic.c | 14 | ||||
-rw-r--r-- | fs/exec.c | 20 | ||||
-rw-r--r-- | include/linux/binfmts.h | 1 |
4 files changed, 23 insertions, 26 deletions
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 78de530cfb02..535e763ab1a6 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c | |||
@@ -1882,7 +1882,6 @@ static int elf_core_dump(struct coredump_params *cprm) | |||
1882 | struct vm_area_struct *vma, *gate_vma; | 1882 | struct vm_area_struct *vma, *gate_vma; |
1883 | struct elfhdr *elf = NULL; | 1883 | struct elfhdr *elf = NULL; |
1884 | loff_t offset = 0, dataoff, foffset; | 1884 | loff_t offset = 0, dataoff, foffset; |
1885 | unsigned long mm_flags; | ||
1886 | struct elf_note_info info; | 1885 | struct elf_note_info info; |
1887 | struct elf_phdr *phdr4note = NULL; | 1886 | struct elf_phdr *phdr4note = NULL; |
1888 | struct elf_shdr *shdr4extnum = NULL; | 1887 | struct elf_shdr *shdr4extnum = NULL; |
@@ -1957,14 +1956,7 @@ static int elf_core_dump(struct coredump_params *cprm) | |||
1957 | 1956 | ||
1958 | dataoff = offset = roundup(offset, ELF_EXEC_PAGESIZE); | 1957 | dataoff = offset = roundup(offset, ELF_EXEC_PAGESIZE); |
1959 | 1958 | ||
1960 | /* | 1959 | offset += elf_core_vma_data_size(gate_vma, cprm->mm_flags); |
1961 | * We must use the same mm->flags while dumping core to avoid | ||
1962 | * inconsistency between the program headers and bodies, otherwise an | ||
1963 | * unusable core file can be generated. | ||
1964 | */ | ||
1965 | mm_flags = current->mm->flags; | ||
1966 | |||
1967 | offset += elf_core_vma_data_size(gate_vma, mm_flags); | ||
1968 | offset += elf_core_extra_data_size(); | 1960 | offset += elf_core_extra_data_size(); |
1969 | e_shoff = offset; | 1961 | e_shoff = offset; |
1970 | 1962 | ||
@@ -1995,7 +1987,7 @@ static int elf_core_dump(struct coredump_params *cprm) | |||
1995 | phdr.p_offset = offset; | 1987 | phdr.p_offset = offset; |
1996 | phdr.p_vaddr = vma->vm_start; | 1988 | phdr.p_vaddr = vma->vm_start; |
1997 | phdr.p_paddr = 0; | 1989 | phdr.p_paddr = 0; |
1998 | phdr.p_filesz = vma_dump_size(vma, mm_flags); | 1990 | phdr.p_filesz = vma_dump_size(vma, cprm->mm_flags); |
1999 | phdr.p_memsz = vma->vm_end - vma->vm_start; | 1991 | phdr.p_memsz = vma->vm_end - vma->vm_start; |
2000 | offset += phdr.p_filesz; | 1992 | offset += phdr.p_filesz; |
2001 | phdr.p_flags = vma->vm_flags & VM_READ ? PF_R : 0; | 1993 | phdr.p_flags = vma->vm_flags & VM_READ ? PF_R : 0; |
@@ -2030,7 +2022,7 @@ static int elf_core_dump(struct coredump_params *cprm) | |||
2030 | unsigned long addr; | 2022 | unsigned long addr; |
2031 | unsigned long end; | 2023 | unsigned long end; |
2032 | 2024 | ||
2033 | end = vma->vm_start + vma_dump_size(vma, mm_flags); | 2025 | end = vma->vm_start + vma_dump_size(vma, cprm->mm_flags); |
2034 | 2026 | ||
2035 | for (addr = vma->vm_start; addr < end; addr += PAGE_SIZE) { | 2027 | for (addr = vma->vm_start; addr < end; addr += PAGE_SIZE) { |
2036 | struct page *page; | 2028 | struct page *page; |
diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c index e49d9c06a4b6..6d6a16c5e9bb 100644 --- a/fs/binfmt_elf_fdpic.c +++ b/fs/binfmt_elf_fdpic.c | |||
@@ -1626,7 +1626,6 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm) | |||
1626 | #endif | 1626 | #endif |
1627 | int thread_status_size = 0; | 1627 | int thread_status_size = 0; |
1628 | elf_addr_t *auxv; | 1628 | elf_addr_t *auxv; |
1629 | unsigned long mm_flags; | ||
1630 | struct elf_phdr *phdr4note = NULL; | 1629 | struct elf_phdr *phdr4note = NULL; |
1631 | struct elf_shdr *shdr4extnum = NULL; | 1630 | struct elf_shdr *shdr4extnum = NULL; |
1632 | Elf_Half e_phnum; | 1631 | Elf_Half e_phnum; |
@@ -1769,14 +1768,7 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm) | |||
1769 | /* Page-align dumped data */ | 1768 | /* Page-align dumped data */ |
1770 | dataoff = offset = roundup(offset, ELF_EXEC_PAGESIZE); | 1769 | dataoff = offset = roundup(offset, ELF_EXEC_PAGESIZE); |
1771 | 1770 | ||
1772 | /* | 1771 | offset += elf_core_vma_data_size(cprm->mm_flags); |
1773 | * We must use the same mm->flags while dumping core to avoid | ||
1774 | * inconsistency between the program headers and bodies, otherwise an | ||
1775 | * unusable core file can be generated. | ||
1776 | */ | ||
1777 | mm_flags = current->mm->flags; | ||
1778 | |||
1779 | offset += elf_core_vma_data_size(mm_flags); | ||
1780 | offset += elf_core_extra_data_size(); | 1772 | offset += elf_core_extra_data_size(); |
1781 | e_shoff = offset; | 1773 | e_shoff = offset; |
1782 | 1774 | ||
@@ -1809,7 +1801,7 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm) | |||
1809 | phdr.p_offset = offset; | 1801 | phdr.p_offset = offset; |
1810 | phdr.p_vaddr = vma->vm_start; | 1802 | phdr.p_vaddr = vma->vm_start; |
1811 | phdr.p_paddr = 0; | 1803 | phdr.p_paddr = 0; |
1812 | phdr.p_filesz = maydump(vma, mm_flags) ? sz : 0; | 1804 | phdr.p_filesz = maydump(vma, cprm->mm_flags) ? sz : 0; |
1813 | phdr.p_memsz = sz; | 1805 | phdr.p_memsz = sz; |
1814 | offset += phdr.p_filesz; | 1806 | offset += phdr.p_filesz; |
1815 | phdr.p_flags = vma->vm_flags & VM_READ ? PF_R : 0; | 1807 | phdr.p_flags = vma->vm_flags & VM_READ ? PF_R : 0; |
@@ -1847,7 +1839,7 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm) | |||
1847 | goto end_coredump; | 1839 | goto end_coredump; |
1848 | 1840 | ||
1849 | if (elf_fdpic_dump_segments(cprm->file, &size, &cprm->limit, | 1841 | if (elf_fdpic_dump_segments(cprm->file, &size, &cprm->limit, |
1850 | mm_flags) < 0) | 1842 | cprm->mm_flags) < 0) |
1851 | goto end_coredump; | 1843 | goto end_coredump; |
1852 | 1844 | ||
1853 | if (!elf_core_write_extra_data(cprm->file, &size, cprm->limit)) | 1845 | if (!elf_core_write_extra_data(cprm->file, &size, cprm->limit)) |
@@ -1748,14 +1748,19 @@ void set_dumpable(struct mm_struct *mm, int value) | |||
1748 | } | 1748 | } |
1749 | } | 1749 | } |
1750 | 1750 | ||
1751 | int get_dumpable(struct mm_struct *mm) | 1751 | static int __get_dumpable(unsigned long mm_flags) |
1752 | { | 1752 | { |
1753 | int ret; | 1753 | int ret; |
1754 | 1754 | ||
1755 | ret = mm->flags & 0x3; | 1755 | ret = mm_flags & MMF_DUMPABLE_MASK; |
1756 | return (ret >= 2) ? 2 : ret; | 1756 | return (ret >= 2) ? 2 : ret; |
1757 | } | 1757 | } |
1758 | 1758 | ||
1759 | int get_dumpable(struct mm_struct *mm) | ||
1760 | { | ||
1761 | return __get_dumpable(mm->flags); | ||
1762 | } | ||
1763 | |||
1759 | static void wait_for_dump_helpers(struct file *file) | 1764 | static void wait_for_dump_helpers(struct file *file) |
1760 | { | 1765 | { |
1761 | struct pipe_inode_info *pipe; | 1766 | struct pipe_inode_info *pipe; |
@@ -1799,6 +1804,12 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs) | |||
1799 | .signr = signr, | 1804 | .signr = signr, |
1800 | .regs = regs, | 1805 | .regs = regs, |
1801 | .limit = rlimit(RLIMIT_CORE), | 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, | ||
1802 | }; | 1813 | }; |
1803 | 1814 | ||
1804 | audit_core_dumps(signr); | 1815 | audit_core_dumps(signr); |
@@ -1817,7 +1828,7 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs) | |||
1817 | /* | 1828 | /* |
1818 | * 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. |
1819 | */ | 1830 | */ |
1820 | if (mm->core_state || !get_dumpable(mm)) { | 1831 | if (mm->core_state || !__get_dumpable(cprm.mm_flags)) { |
1821 | up_write(&mm->mmap_sem); | 1832 | up_write(&mm->mmap_sem); |
1822 | put_cred(cred); | 1833 | put_cred(cred); |
1823 | goto fail; | 1834 | goto fail; |
@@ -1828,7 +1839,8 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs) | |||
1828 | * 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 |
1829 | * was tainted so we dump it as root in mode 2. | 1840 | * was tainted so we dump it as root in mode 2. |
1830 | */ | 1841 | */ |
1831 | if (get_dumpable(mm) == 2) { /* Setuid core dump mode */ | 1842 | if (__get_dumpable(cprm.mm_flags) == 2) { |
1843 | /* Setuid core dump mode */ | ||
1832 | flag = O_EXCL; /* Stop rewrite attacks */ | 1844 | flag = O_EXCL; /* Stop rewrite attacks */ |
1833 | cred->fsuid = 0; /* Dump root private */ | 1845 | cred->fsuid = 0; /* Dump root private */ |
1834 | } | 1846 | } |
diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h index 89c6249fc561..c809e286d213 100644 --- a/include/linux/binfmts.h +++ b/include/linux/binfmts.h | |||
@@ -74,6 +74,7 @@ struct coredump_params { | |||
74 | struct pt_regs *regs; | 74 | struct pt_regs *regs; |
75 | struct file *file; | 75 | struct file *file; |
76 | unsigned long limit; | 76 | unsigned long limit; |
77 | unsigned long mm_flags; | ||
77 | }; | 78 | }; |
78 | 79 | ||
79 | /* | 80 | /* |