Commit 30736a4d authored by Masami Hiramatsu's avatar Masami Hiramatsu Committed by Linus Torvalds

coredump: pass mm->flags as a coredump parameter for consistency

Pass mm->flags as a coredump parameter for consistency.

 ---
1787         if (mm->core_state || !get_dumpable(mm)) {  <- (1)
1788                 up_write(&mm->mmap_sem);
1789                 put_cred(cred);
1790                 goto fail;
1791         }
1792
[...]
1798         if (get_dumpable(mm) == 2) {    /* Setuid core dump mode */ <-(2)
1799                 flag = O_EXCL;          /* Stop rewrite attacks */
1800                 cred->fsuid = 0;        /* Dump root private */
1801         }
 ---

Since dumpable bits are not protected by lock, there is a chance to change
these bits between (1) and (2).

To solve this issue, this patch copies mm->flags to
coredump_params.mm_flags at the beginning of do_coredump() and uses it
instead of get_dumpable() while dumping core.

This copy is also passed to binfmt->core_dump, since elf*_core_dump() uses
dump_filter bits in mm->flags.

[akpm@linux-foundation.org: fix merge]
Signed-off-by: default avatarMasami Hiramatsu <mhiramat@redhat.com>
Acked-by: default avatarRoland McGrath <roland@redhat.com>
Cc: Hidehiro Kawai <hidehiro.kawai.ez@hitachi.com>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Ingo Molnar <mingo@elte.hu>
Reviewed-by: default avatarKOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 8d9032bb
...@@ -1882,7 +1882,6 @@ static int elf_core_dump(struct coredump_params *cprm) ...@@ -1882,7 +1882,6 @@ static int elf_core_dump(struct coredump_params *cprm)
struct vm_area_struct *vma, *gate_vma; struct vm_area_struct *vma, *gate_vma;
struct elfhdr *elf = NULL; struct elfhdr *elf = NULL;
loff_t offset = 0, dataoff, foffset; loff_t offset = 0, dataoff, foffset;
unsigned long mm_flags;
struct elf_note_info info; struct elf_note_info info;
struct elf_phdr *phdr4note = NULL; struct elf_phdr *phdr4note = NULL;
struct elf_shdr *shdr4extnum = NULL; struct elf_shdr *shdr4extnum = NULL;
...@@ -1957,14 +1956,7 @@ static int elf_core_dump(struct coredump_params *cprm) ...@@ -1957,14 +1956,7 @@ static int elf_core_dump(struct coredump_params *cprm)
dataoff = offset = roundup(offset, ELF_EXEC_PAGESIZE); dataoff = offset = roundup(offset, ELF_EXEC_PAGESIZE);
/* offset += elf_core_vma_data_size(gate_vma, cprm->mm_flags);
* We must use the same mm->flags while dumping core to avoid
* inconsistency between the program headers and bodies, otherwise an
* unusable core file can be generated.
*/
mm_flags = current->mm->flags;
offset += elf_core_vma_data_size(gate_vma, mm_flags);
offset += elf_core_extra_data_size(); offset += elf_core_extra_data_size();
e_shoff = offset; e_shoff = offset;
...@@ -1995,7 +1987,7 @@ static int elf_core_dump(struct coredump_params *cprm) ...@@ -1995,7 +1987,7 @@ static int elf_core_dump(struct coredump_params *cprm)
phdr.p_offset = offset; phdr.p_offset = offset;
phdr.p_vaddr = vma->vm_start; phdr.p_vaddr = vma->vm_start;
phdr.p_paddr = 0; phdr.p_paddr = 0;
phdr.p_filesz = vma_dump_size(vma, mm_flags); phdr.p_filesz = vma_dump_size(vma, cprm->mm_flags);
phdr.p_memsz = vma->vm_end - vma->vm_start; phdr.p_memsz = vma->vm_end - vma->vm_start;
offset += phdr.p_filesz; offset += phdr.p_filesz;
phdr.p_flags = vma->vm_flags & VM_READ ? PF_R : 0; 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,7 +2022,7 @@ static int elf_core_dump(struct coredump_params *cprm)
unsigned long addr; unsigned long addr;
unsigned long end; unsigned long end;
end = vma->vm_start + vma_dump_size(vma, mm_flags); end = vma->vm_start + vma_dump_size(vma, cprm->mm_flags);
for (addr = vma->vm_start; addr < end; addr += PAGE_SIZE) { for (addr = vma->vm_start; addr < end; addr += PAGE_SIZE) {
struct page *page; struct page *page;
......
...@@ -1626,7 +1626,6 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm) ...@@ -1626,7 +1626,6 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
#endif #endif
int thread_status_size = 0; int thread_status_size = 0;
elf_addr_t *auxv; elf_addr_t *auxv;
unsigned long mm_flags;
struct elf_phdr *phdr4note = NULL; struct elf_phdr *phdr4note = NULL;
struct elf_shdr *shdr4extnum = NULL; struct elf_shdr *shdr4extnum = NULL;
Elf_Half e_phnum; Elf_Half e_phnum;
...@@ -1769,14 +1768,7 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm) ...@@ -1769,14 +1768,7 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
/* Page-align dumped data */ /* Page-align dumped data */
dataoff = offset = roundup(offset, ELF_EXEC_PAGESIZE); dataoff = offset = roundup(offset, ELF_EXEC_PAGESIZE);
/* offset += elf_core_vma_data_size(cprm->mm_flags);
* We must use the same mm->flags while dumping core to avoid
* inconsistency between the program headers and bodies, otherwise an
* unusable core file can be generated.
*/
mm_flags = current->mm->flags;
offset += elf_core_vma_data_size(mm_flags);
offset += elf_core_extra_data_size(); offset += elf_core_extra_data_size();
e_shoff = offset; e_shoff = offset;
...@@ -1809,7 +1801,7 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm) ...@@ -1809,7 +1801,7 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
phdr.p_offset = offset; phdr.p_offset = offset;
phdr.p_vaddr = vma->vm_start; phdr.p_vaddr = vma->vm_start;
phdr.p_paddr = 0; phdr.p_paddr = 0;
phdr.p_filesz = maydump(vma, mm_flags) ? sz : 0; phdr.p_filesz = maydump(vma, cprm->mm_flags) ? sz : 0;
phdr.p_memsz = sz; phdr.p_memsz = sz;
offset += phdr.p_filesz; offset += phdr.p_filesz;
phdr.p_flags = vma->vm_flags & VM_READ ? PF_R : 0; 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,7 +1839,7 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
goto end_coredump; goto end_coredump;
if (elf_fdpic_dump_segments(cprm->file, &size, &cprm->limit, if (elf_fdpic_dump_segments(cprm->file, &size, &cprm->limit,
mm_flags) < 0) cprm->mm_flags) < 0)
goto end_coredump; goto end_coredump;
if (!elf_core_write_extra_data(cprm->file, &size, cprm->limit)) 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,14 +1748,19 @@ void set_dumpable(struct mm_struct *mm, int value)
} }
} }
int get_dumpable(struct mm_struct *mm) static int __get_dumpable(unsigned long mm_flags)
{ {
int ret; int ret;
ret = mm->flags & 0x3; ret = mm_flags & MMF_DUMPABLE_MASK;
return (ret >= 2) ? 2 : ret; return (ret >= 2) ? 2 : ret;
} }
int get_dumpable(struct mm_struct *mm)
{
return __get_dumpable(mm->flags);
}
static void wait_for_dump_helpers(struct file *file) static void wait_for_dump_helpers(struct file *file)
{ {
struct pipe_inode_info *pipe; struct pipe_inode_info *pipe;
...@@ -1799,6 +1804,12 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs) ...@@ -1799,6 +1804,12 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs)
.signr = signr, .signr = signr,
.regs = regs, .regs = regs,
.limit = rlimit(RLIMIT_CORE), .limit = rlimit(RLIMIT_CORE),
/*
* We must use the same mm->flags while dumping core to avoid
* inconsistency of bit flags, since this flag is not protected
* by any locks.
*/
.mm_flags = mm->flags,
}; };
audit_core_dumps(signr); audit_core_dumps(signr);
...@@ -1817,7 +1828,7 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs) ...@@ -1817,7 +1828,7 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs)
/* /*
* If another thread got here first, or we are not dumpable, bail out. * If another thread got here first, or we are not dumpable, bail out.
*/ */
if (mm->core_state || !get_dumpable(mm)) { if (mm->core_state || !__get_dumpable(cprm.mm_flags)) {
up_write(&mm->mmap_sem); up_write(&mm->mmap_sem);
put_cred(cred); put_cred(cred);
goto fail; goto fail;
...@@ -1828,7 +1839,8 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs) ...@@ -1828,7 +1839,8 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs)
* process nor do we know its entire history. We only know it * process nor do we know its entire history. We only know it
* was tainted so we dump it as root in mode 2. * was tainted so we dump it as root in mode 2.
*/ */
if (get_dumpable(mm) == 2) { /* Setuid core dump mode */ if (__get_dumpable(cprm.mm_flags) == 2) {
/* Setuid core dump mode */
flag = O_EXCL; /* Stop rewrite attacks */ flag = O_EXCL; /* Stop rewrite attacks */
cred->fsuid = 0; /* Dump root private */ cred->fsuid = 0; /* Dump root private */
} }
......
...@@ -74,6 +74,7 @@ struct coredump_params { ...@@ -74,6 +74,7 @@ struct coredump_params {
struct pt_regs *regs; struct pt_regs *regs;
struct file *file; struct file *file;
unsigned long limit; unsigned long limit;
unsigned long mm_flags;
}; };
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment