Skip to content

Commit

Permalink
elf coredump: make offset calculation process and writing process exp…
Browse files Browse the repository at this point in the history
…licit

By the next patch, elf_core_dump() and elf_fdpic_core_dump() will support
extended numbering and so will produce the corefiles with section header
table in a special case.

The problem is the process of writing a file header offset of the section
header table into e_shoff field of the ELF header.  ELF header is
positioned at the beginning of the corefile, while section header at the
end.  So, we need to take which of the following ways:

 1. Seek backward to retry writing operation for ELF header
    after writing process for a whole part

 2. Make offset calculation process and writing process
    totally sequential

The clause 1.  is not always possible: one cannot assume that file system
supports seek function.  Consider the no_llseek case.

Therefore, this patch adopts the clause 2.

Signed-off-by: Daisuke HATAYAMA <d.hatayama@jp.fujitsu.com>
Cc: "Luck, Tony" <tony.luck@intel.com>
Cc: Jeff Dike <jdike@addtoit.com>
Cc: David Howells <dhowells@redhat.com>
Cc: Greg Ungerer <gerg@snapgear.com>
Cc: Roland McGrath <roland@redhat.com>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Alexander Viro <viro@zeniv.linux.org.uk>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
Cc: <linux-arch@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
  • Loading branch information
Daisuke HATAYAMA authored and torvalds committed Mar 6, 2010
1 parent 1fcccba commit 93eb211
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 24 deletions.
27 changes: 16 additions & 11 deletions fs/binfmt_elf.c
Original file line number Diff line number Diff line change
Expand Up @@ -1856,6 +1856,7 @@ static int elf_core_dump(struct coredump_params *cprm)
loff_t offset = 0, dataoff, foffset;
unsigned long mm_flags;
struct elf_note_info info;
struct elf_phdr *phdr4note = NULL;

/*
* We no longer stop all VM operations.
Expand Down Expand Up @@ -1898,28 +1899,22 @@ static int elf_core_dump(struct coredump_params *cprm)
fs = get_fs();
set_fs(KERNEL_DS);

size += sizeof(*elf);
if (size > cprm->limit || !dump_write(cprm->file, elf, sizeof(*elf)))
goto end_coredump;

offset += sizeof(*elf); /* Elf header */
offset += (segs + 1) * sizeof(struct elf_phdr); /* Program headers */
foffset = offset;

/* Write notes phdr entry */
{
struct elf_phdr phdr;
size_t sz = get_note_info_size(&info);

sz += elf_coredump_extra_notes_size();

fill_elf_note_phdr(&phdr, sz, offset);
offset += sz;

size += sizeof(phdr);
if (size > cprm->limit
|| !dump_write(cprm->file, &phdr, sizeof(phdr)))
phdr4note = kmalloc(sizeof(*phdr4note), GFP_KERNEL);
if (!phdr4note)
goto end_coredump;

fill_elf_note_phdr(phdr4note, sz, offset);
offset += sz;
}

dataoff = offset = roundup(offset, ELF_EXEC_PAGESIZE);
Expand All @@ -1931,6 +1926,15 @@ static int elf_core_dump(struct coredump_params *cprm)
*/
mm_flags = current->mm->flags;

size += sizeof(*elf);
if (size > cprm->limit || !dump_write(cprm->file, elf, sizeof(*elf)))
goto end_coredump;

size += sizeof(*phdr4note);
if (size > cprm->limit
|| !dump_write(cprm->file, phdr4note, sizeof(*phdr4note)))
goto end_coredump;

/* Write program headers for segments dump */
for (vma = first_vma(current, gate_vma); vma != NULL;
vma = next_vma(vma, gate_vma)) {
Expand Down Expand Up @@ -2004,6 +2008,7 @@ static int elf_core_dump(struct coredump_params *cprm)

cleanup:
free_note_info(&info);
kfree(phdr4note);
kfree(elf);
out:
return has_dumped;
Expand Down
29 changes: 16 additions & 13 deletions fs/binfmt_elf_fdpic.c
Original file line number Diff line number Diff line change
Expand Up @@ -1600,6 +1600,7 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
int thread_status_size = 0;
elf_addr_t *auxv;
unsigned long mm_flags;
struct elf_phdr *phdr4note = NULL;

/*
* We no longer stop all VM operations.
Expand Down Expand Up @@ -1706,32 +1707,25 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
fs = get_fs();
set_fs(KERNEL_DS);

size += sizeof(*elf);
if (size > cprm->limit
|| !dump_write(cprm->file, elf, sizeof(*elf)))
goto end_coredump;

offset += sizeof(*elf); /* Elf header */
offset += (segs+1) * sizeof(struct elf_phdr); /* Program headers */
foffset = offset;

/* Write notes phdr entry */
{
struct elf_phdr phdr;
int sz = 0;

for (i = 0; i < numnote; i++)
sz += notesize(notes + i);

sz += thread_status_size;

fill_elf_note_phdr(&phdr, sz, offset);
offset += sz;

size += sizeof(phdr);
if (size > cprm->limit
|| !dump_write(cprm->file, &phdr, sizeof(phdr)))
phdr4note = kmalloc(sizeof(*phdr4note), GFP_KERNEL);
if (!phdr4note)
goto end_coredump;

fill_elf_note_phdr(phdr4note, sz, offset);
offset += sz;
}

/* Page-align dumped data */
Expand All @@ -1744,6 +1738,15 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
*/
mm_flags = current->mm->flags;

size += sizeof(*elf);
if (size > cprm->limit || !dump_write(cprm->file, elf, sizeof(*elf)))
goto end_coredump;

size += sizeof(*phdr4note);
if (size > cprm->limit
|| !dump_write(cprm->file, phdr4note, sizeof(*phdr4note)))
goto end_coredump;

/* write program headers for segments dump */
for (vma = current->mm->mmap; vma; vma = vma->vm_next) {
struct elf_phdr phdr;
Expand Down Expand Up @@ -1815,7 +1818,7 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
list_del(tmp);
kfree(list_entry(tmp, struct elf_thread_status, list));
}

kfree(phdr4note);
kfree(elf);
kfree(prstatus);
kfree(psinfo);
Expand Down

0 comments on commit 93eb211

Please sign in to comment.