|
@@ -1505,6 +1505,22 @@ static int elf_dump_thread_status(long signr, struct elf_thread_status *t)
|
|
return sz;
|
|
return sz;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static void fill_extnum_info(struct elfhdr *elf, struct elf_shdr *shdr4extnum,
|
|
|
|
+ elf_addr_t e_shoff, int segs)
|
|
|
|
+{
|
|
|
|
+ elf->e_shoff = e_shoff;
|
|
|
|
+ elf->e_shentsize = sizeof(*shdr4extnum);
|
|
|
|
+ elf->e_shnum = 1;
|
|
|
|
+ elf->e_shstrndx = SHN_UNDEF;
|
|
|
|
+
|
|
|
|
+ memset(shdr4extnum, 0, sizeof(*shdr4extnum));
|
|
|
|
+
|
|
|
|
+ shdr4extnum->sh_type = SHT_NULL;
|
|
|
|
+ shdr4extnum->sh_size = elf->e_shnum;
|
|
|
|
+ shdr4extnum->sh_link = elf->e_shstrndx;
|
|
|
|
+ shdr4extnum->sh_info = segs;
|
|
|
|
+}
|
|
|
|
+
|
|
/*
|
|
/*
|
|
* dump the segments for an MMU process
|
|
* dump the segments for an MMU process
|
|
*/
|
|
*/
|
|
@@ -1569,6 +1585,17 @@ static int elf_fdpic_dump_segments(struct file *file, size_t *size,
|
|
}
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
|
|
|
|
+static size_t elf_core_vma_data_size(unsigned long mm_flags)
|
|
|
|
+{
|
|
|
|
+ struct vm_area_struct *vma;
|
|
|
|
+ size_t size = 0;
|
|
|
|
+
|
|
|
|
+ for (vma = current->mm->mmap; vma; vma->vm_next)
|
|
|
|
+ if (maydump(vma, mm_flags))
|
|
|
|
+ size += vma->vm_end - vma->vm_start;
|
|
|
|
+ return size;
|
|
|
|
+}
|
|
|
|
+
|
|
/*
|
|
/*
|
|
* Actual dumper
|
|
* Actual dumper
|
|
*
|
|
*
|
|
@@ -1601,6 +1628,9 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
|
|
elf_addr_t *auxv;
|
|
elf_addr_t *auxv;
|
|
unsigned long mm_flags;
|
|
unsigned long mm_flags;
|
|
struct elf_phdr *phdr4note = NULL;
|
|
struct elf_phdr *phdr4note = NULL;
|
|
|
|
+ struct elf_shdr *shdr4extnum = NULL;
|
|
|
|
+ Elf_Half e_phnum;
|
|
|
|
+ elf_addr_t e_shoff;
|
|
|
|
|
|
/*
|
|
/*
|
|
* We no longer stop all VM operations.
|
|
* We no longer stop all VM operations.
|
|
@@ -1667,8 +1697,16 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
|
|
segs = current->mm->map_count;
|
|
segs = current->mm->map_count;
|
|
segs += elf_core_extra_phdrs();
|
|
segs += elf_core_extra_phdrs();
|
|
|
|
|
|
|
|
+ /* for notes section */
|
|
|
|
+ segs++;
|
|
|
|
+
|
|
|
|
+ /* If segs > PN_XNUM(0xffff), then e_phnum overflows. To avoid
|
|
|
|
+ * this, kernel supports extended numbering. Have a look at
|
|
|
|
+ * include/linux/elf.h for further information. */
|
|
|
|
+ e_phnum = segs > PN_XNUM ? PN_XNUM : segs;
|
|
|
|
+
|
|
/* Set up header */
|
|
/* Set up header */
|
|
- fill_elf_fdpic_header(elf, segs + 1); /* including notes section */
|
|
|
|
|
|
+ fill_elf_fdpic_header(elf, e_phnum);
|
|
|
|
|
|
has_dumped = 1;
|
|
has_dumped = 1;
|
|
current->flags |= PF_DUMPCORE;
|
|
current->flags |= PF_DUMPCORE;
|
|
@@ -1708,7 +1746,7 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
|
|
set_fs(KERNEL_DS);
|
|
set_fs(KERNEL_DS);
|
|
|
|
|
|
offset += sizeof(*elf); /* Elf header */
|
|
offset += sizeof(*elf); /* Elf header */
|
|
- offset += (segs+1) * sizeof(struct elf_phdr); /* Program headers */
|
|
|
|
|
|
+ offset += segs * sizeof(struct elf_phdr); /* Program headers */
|
|
foffset = offset;
|
|
foffset = offset;
|
|
|
|
|
|
/* Write notes phdr entry */
|
|
/* Write notes phdr entry */
|
|
@@ -1738,6 +1776,19 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
|
|
*/
|
|
*/
|
|
mm_flags = current->mm->flags;
|
|
mm_flags = current->mm->flags;
|
|
|
|
|
|
|
|
+ offset += elf_core_vma_data_size(mm_flags);
|
|
|
|
+ offset += elf_core_extra_data_size();
|
|
|
|
+ e_shoff = offset;
|
|
|
|
+
|
|
|
|
+ if (e_phnum == PN_XNUM) {
|
|
|
|
+ shdr4extnum = kmalloc(sizeof(*shdr4extnum), GFP_KERNEL);
|
|
|
|
+ if (!shdr4extnum)
|
|
|
|
+ goto end_coredump;
|
|
|
|
+ fill_extnum_info(elf, shdr4extnum, e_shoff, segs);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ offset = dataoff;
|
|
|
|
+
|
|
size += sizeof(*elf);
|
|
size += sizeof(*elf);
|
|
if (size > cprm->limit || !dump_write(cprm->file, elf, sizeof(*elf)))
|
|
if (size > cprm->limit || !dump_write(cprm->file, elf, sizeof(*elf)))
|
|
goto end_coredump;
|
|
goto end_coredump;
|
|
@@ -1802,6 +1853,14 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
|
|
if (!elf_core_write_extra_data(cprm->file, &size, cprm->limit))
|
|
if (!elf_core_write_extra_data(cprm->file, &size, cprm->limit))
|
|
goto end_coredump;
|
|
goto end_coredump;
|
|
|
|
|
|
|
|
+ if (e_phnum == PN_XNUM) {
|
|
|
|
+ size += sizeof(*shdr4extnum);
|
|
|
|
+ if (size > cprm->limit
|
|
|
|
+ || !dump_write(cprm->file, shdr4extnum,
|
|
|
|
+ sizeof(*shdr4extnum)))
|
|
|
|
+ goto end_coredump;
|
|
|
|
+ }
|
|
|
|
+
|
|
if (cprm->file->f_pos != offset) {
|
|
if (cprm->file->f_pos != offset) {
|
|
/* Sanity check */
|
|
/* Sanity check */
|
|
printk(KERN_WARNING
|
|
printk(KERN_WARNING
|