[<prev] [next>] [day] [month] [year] [list]
Message-Id: <20091224.180516.226030603.d.hatayama@jp.fujitsu.com>
Date: Thu, 24 Dec 2009 18:05:16 +0900
(東京 (標準時))
From: Daisuke HATAYAMA <d.hatayama@...fujitsu.com>
To: linux-kernel@...r.kernel.org
Cc: akpm@...ux-foundation.org, mhiramat@...hat.com,
xiyou.wangcong@...il.com, andi@...stfloor.org, jdike@...toit.com,
tony.luck@...el.com
Subject: [PATCH v2, 4/5] elf coredump: make offset calculation process and
writing process explicit
By the next patch, elf_core_dump() and elf_fdpic_core_dump() will
support extended numbering and so will possibly produce the corefiles
with section header table.
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, there are two ways to do this:
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@...fujitsu.com>
---
fs/binfmt_elf.c | 27 ++++++++++++++++-----------
fs/binfmt_elf_fdpic.c | 29 ++++++++++++++++-------------
2 files changed, 32 insertions(+), 24 deletions(-)
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index 1b7e9de..b1ded32 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -1879,6 +1879,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.
@@ -1921,28 +1922,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);
@@ -1954,6 +1949,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)) {
@@ -2027,6 +2031,7 @@ end_coredump:
cleanup:
free_note_info(&info);
+ kfree(phdr4note);
kfree(elf);
out:
return has_dumped;
diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c
index 4c16ff6..cbfa34e 100644
--- a/fs/binfmt_elf_fdpic.c
+++ b/fs/binfmt_elf_fdpic.c
@@ -1588,6 +1588,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.
@@ -1694,18 +1695,12 @@ 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++)
@@ -1713,13 +1708,12 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
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 */
@@ -1732,6 +1726,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;
@@ -1803,7 +1806,7 @@ cleanup:
list_del(tmp);
kfree(list_entry(tmp, struct elf_thread_status, list));
}
-
+ kfree(phdr4note);
kfree(elf);
kfree(prstatus);
kfree(psinfo);
--
1.6.5.1
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists