|
@@ -1994,18 +1994,6 @@ static void fill_extnum_info(struct elfhdr *elf, struct elf_shdr *shdr4extnum,
|
|
|
shdr4extnum->sh_info = segs;
|
|
|
}
|
|
|
|
|
|
-static size_t elf_core_vma_data_size(struct vm_area_struct *gate_vma,
|
|
|
- unsigned long mm_flags)
|
|
|
-{
|
|
|
- struct vm_area_struct *vma;
|
|
|
- size_t size = 0;
|
|
|
-
|
|
|
- for (vma = first_vma(current, gate_vma); vma != NULL;
|
|
|
- vma = next_vma(vma, gate_vma))
|
|
|
- size += vma_dump_size(vma, mm_flags);
|
|
|
- return size;
|
|
|
-}
|
|
|
-
|
|
|
/*
|
|
|
* Actual dumper
|
|
|
*
|
|
@@ -2017,7 +2005,8 @@ static int elf_core_dump(struct coredump_params *cprm)
|
|
|
{
|
|
|
int has_dumped = 0;
|
|
|
mm_segment_t fs;
|
|
|
- int segs;
|
|
|
+ int segs, i;
|
|
|
+ size_t vma_data_size = 0;
|
|
|
struct vm_area_struct *vma, *gate_vma;
|
|
|
struct elfhdr *elf = NULL;
|
|
|
loff_t offset = 0, dataoff;
|
|
@@ -2026,6 +2015,7 @@ static int elf_core_dump(struct coredump_params *cprm)
|
|
|
struct elf_shdr *shdr4extnum = NULL;
|
|
|
Elf_Half e_phnum;
|
|
|
elf_addr_t e_shoff;
|
|
|
+ elf_addr_t *vma_filesz = NULL;
|
|
|
|
|
|
/*
|
|
|
* We no longer stop all VM operations.
|
|
@@ -2093,7 +2083,20 @@ static int elf_core_dump(struct coredump_params *cprm)
|
|
|
|
|
|
dataoff = offset = roundup(offset, ELF_EXEC_PAGESIZE);
|
|
|
|
|
|
- offset += elf_core_vma_data_size(gate_vma, cprm->mm_flags);
|
|
|
+ vma_filesz = kmalloc_array(segs - 1, sizeof(*vma_filesz), GFP_KERNEL);
|
|
|
+ if (!vma_filesz)
|
|
|
+ goto end_coredump;
|
|
|
+
|
|
|
+ for (i = 0, vma = first_vma(current, gate_vma); vma != NULL;
|
|
|
+ vma = next_vma(vma, gate_vma)) {
|
|
|
+ unsigned long dump_size;
|
|
|
+
|
|
|
+ dump_size = vma_dump_size(vma, cprm->mm_flags);
|
|
|
+ vma_filesz[i++] = dump_size;
|
|
|
+ vma_data_size += dump_size;
|
|
|
+ }
|
|
|
+
|
|
|
+ offset += vma_data_size;
|
|
|
offset += elf_core_extra_data_size();
|
|
|
e_shoff = offset;
|
|
|
|
|
@@ -2113,7 +2116,7 @@ static int elf_core_dump(struct coredump_params *cprm)
|
|
|
goto end_coredump;
|
|
|
|
|
|
/* Write program headers for segments dump */
|
|
|
- for (vma = first_vma(current, gate_vma); vma != NULL;
|
|
|
+ for (i = 0, vma = first_vma(current, gate_vma); vma != NULL;
|
|
|
vma = next_vma(vma, gate_vma)) {
|
|
|
struct elf_phdr phdr;
|
|
|
|
|
@@ -2121,7 +2124,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, cprm->mm_flags);
|
|
|
+ phdr.p_filesz = vma_filesz[i++];
|
|
|
phdr.p_memsz = vma->vm_end - vma->vm_start;
|
|
|
offset += phdr.p_filesz;
|
|
|
phdr.p_flags = vma->vm_flags & VM_READ ? PF_R : 0;
|
|
@@ -2149,12 +2152,12 @@ static int elf_core_dump(struct coredump_params *cprm)
|
|
|
if (!dump_skip(cprm, dataoff - cprm->written))
|
|
|
goto end_coredump;
|
|
|
|
|
|
- for (vma = first_vma(current, gate_vma); vma != NULL;
|
|
|
+ for (i = 0, vma = first_vma(current, gate_vma); vma != NULL;
|
|
|
vma = next_vma(vma, gate_vma)) {
|
|
|
unsigned long addr;
|
|
|
unsigned long end;
|
|
|
|
|
|
- end = vma->vm_start + vma_dump_size(vma, cprm->mm_flags);
|
|
|
+ end = vma->vm_start + vma_filesz[i++];
|
|
|
|
|
|
for (addr = vma->vm_start; addr < end; addr += PAGE_SIZE) {
|
|
|
struct page *page;
|
|
@@ -2187,6 +2190,7 @@ end_coredump:
|
|
|
cleanup:
|
|
|
free_note_info(&info);
|
|
|
kfree(shdr4extnum);
|
|
|
+ kfree(vma_filesz);
|
|
|
kfree(phdr4note);
|
|
|
kfree(elf);
|
|
|
out:
|