forked from Minki/linux
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: Masami Hiramatsu <mhiramat@redhat.com> Acked-by: Roland 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: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
8d9032bbe4
commit
30736a4d43
@ -1882,7 +1882,6 @@ static int elf_core_dump(struct coredump_params *cprm)
|
||||
struct vm_area_struct *vma, *gate_vma;
|
||||
struct elfhdr *elf = NULL;
|
||||
loff_t offset = 0, dataoff, foffset;
|
||||
unsigned long mm_flags;
|
||||
struct elf_note_info info;
|
||||
struct elf_phdr *phdr4note = NULL;
|
||||
struct elf_shdr *shdr4extnum = NULL;
|
||||
@ -1957,14 +1956,7 @@ static int elf_core_dump(struct coredump_params *cprm)
|
||||
|
||||
dataoff = offset = roundup(offset, ELF_EXEC_PAGESIZE);
|
||||
|
||||
/*
|
||||
* 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_vma_data_size(gate_vma, cprm->mm_flags);
|
||||
offset += elf_core_extra_data_size();
|
||||
e_shoff = offset;
|
||||
|
||||
@ -1995,7 +1987,7 @@ static int elf_core_dump(struct coredump_params *cprm)
|
||||
phdr.p_offset = offset;
|
||||
phdr.p_vaddr = vma->vm_start;
|
||||
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;
|
||||
offset += phdr.p_filesz;
|
||||
phdr.p_flags = vma->vm_flags & VM_READ ? PF_R : 0;
|
||||
@ -2030,7 +2022,7 @@ static int elf_core_dump(struct coredump_params *cprm)
|
||||
unsigned long addr;
|
||||
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) {
|
||||
struct page *page;
|
||||
|
@ -1626,7 +1626,6 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
|
||||
#endif
|
||||
int thread_status_size = 0;
|
||||
elf_addr_t *auxv;
|
||||
unsigned long mm_flags;
|
||||
struct elf_phdr *phdr4note = NULL;
|
||||
struct elf_shdr *shdr4extnum = NULL;
|
||||
Elf_Half e_phnum;
|
||||
@ -1769,14 +1768,7 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
|
||||
/* Page-align dumped data */
|
||||
dataoff = offset = roundup(offset, ELF_EXEC_PAGESIZE);
|
||||
|
||||
/*
|
||||
* 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_vma_data_size(cprm->mm_flags);
|
||||
offset += elf_core_extra_data_size();
|
||||
e_shoff = offset;
|
||||
|
||||
@ -1809,7 +1801,7 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
|
||||
phdr.p_offset = offset;
|
||||
phdr.p_vaddr = vma->vm_start;
|
||||
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;
|
||||
offset += phdr.p_filesz;
|
||||
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)
|
||||
goto end_coredump;
|
||||
|
||||
if (elf_fdpic_dump_segments(cprm->file, &size, &cprm->limit,
|
||||
mm_flags) < 0)
|
||||
cprm->mm_flags) < 0)
|
||||
goto end_coredump;
|
||||
|
||||
if (!elf_core_write_extra_data(cprm->file, &size, cprm->limit))
|
||||
|
20
fs/exec.c
20
fs/exec.c
@ -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;
|
||||
|
||||
ret = mm->flags & 0x3;
|
||||
ret = mm_flags & MMF_DUMPABLE_MASK;
|
||||
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)
|
||||
{
|
||||
struct pipe_inode_info *pipe;
|
||||
@ -1799,6 +1804,12 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs)
|
||||
.signr = signr,
|
||||
.regs = regs,
|
||||
.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);
|
||||
@ -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 (mm->core_state || !get_dumpable(mm)) {
|
||||
if (mm->core_state || !__get_dumpable(cprm.mm_flags)) {
|
||||
up_write(&mm->mmap_sem);
|
||||
put_cred(cred);
|
||||
goto fail;
|
||||
@ -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
|
||||
* 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 */
|
||||
cred->fsuid = 0; /* Dump root private */
|
||||
}
|
||||
|
@ -74,6 +74,7 @@ struct coredump_params {
|
||||
struct pt_regs *regs;
|
||||
struct file *file;
|
||||
unsigned long limit;
|
||||
unsigned long mm_flags;
|
||||
};
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user