aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/binfmt_elf.c14
-rw-r--r--fs/binfmt_elf_fdpic.c14
-rw-r--r--fs/exec.c20
-rw-r--r--include/linux/binfmts.h1
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))
diff --git a/fs/exec.c b/fs/exec.c
index da2b31dc4e1c..89d4080c1435 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1748,14 +1748,19 @@ void set_dumpable(struct mm_struct *mm, int value)
1748 } 1748 }
1749} 1749}
1750 1750
1751int get_dumpable(struct mm_struct *mm) 1751static 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
1759int get_dumpable(struct mm_struct *mm)
1760{
1761 return __get_dumpable(mm->flags);
1762}
1763
1759static void wait_for_dump_helpers(struct file *file) 1764static 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/*