aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorDaisuke HATAYAMA <d.hatayama@jp.fujitsu.com>2010-03-05 16:44:09 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2010-03-06 14:26:46 -0500
commit93eb211e6c9ff6054fcf9c5b9e344d8d9ad29175 (patch)
tree424990890a34e626df8e2c68f4952d4d4734b63b /fs
parent1fcccbac89f5bbc5e41aa72086960059fce372da (diff)
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 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>
Diffstat (limited to 'fs')
-rw-r--r--fs/binfmt_elf.c27
-rw-r--r--fs/binfmt_elf_fdpic.c29
2 files changed, 32 insertions, 24 deletions
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index c1a499599b7d..6fc49b6ed936 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -1856,6 +1856,7 @@ static int elf_core_dump(struct coredump_params *cprm)
1856 loff_t offset = 0, dataoff, foffset; 1856 loff_t offset = 0, dataoff, foffset;
1857 unsigned long mm_flags; 1857 unsigned long mm_flags;
1858 struct elf_note_info info; 1858 struct elf_note_info info;
1859 struct elf_phdr *phdr4note = NULL;
1859 1860
1860 /* 1861 /*
1861 * We no longer stop all VM operations. 1862 * We no longer stop all VM operations.
@@ -1898,28 +1899,22 @@ static int elf_core_dump(struct coredump_params *cprm)
1898 fs = get_fs(); 1899 fs = get_fs();
1899 set_fs(KERNEL_DS); 1900 set_fs(KERNEL_DS);
1900 1901
1901 size += sizeof(*elf);
1902 if (size > cprm->limit || !dump_write(cprm->file, elf, sizeof(*elf)))
1903 goto end_coredump;
1904
1905 offset += sizeof(*elf); /* Elf header */ 1902 offset += sizeof(*elf); /* Elf header */
1906 offset += (segs + 1) * sizeof(struct elf_phdr); /* Program headers */ 1903 offset += (segs + 1) * sizeof(struct elf_phdr); /* Program headers */
1907 foffset = offset; 1904 foffset = offset;
1908 1905
1909 /* Write notes phdr entry */ 1906 /* Write notes phdr entry */
1910 { 1907 {
1911 struct elf_phdr phdr;
1912 size_t sz = get_note_info_size(&info); 1908 size_t sz = get_note_info_size(&info);
1913 1909
1914 sz += elf_coredump_extra_notes_size(); 1910 sz += elf_coredump_extra_notes_size();
1915 1911
1916 fill_elf_note_phdr(&phdr, sz, offset); 1912 phdr4note = kmalloc(sizeof(*phdr4note), GFP_KERNEL);
1917 offset += sz; 1913 if (!phdr4note)
1918
1919 size += sizeof(phdr);
1920 if (size > cprm->limit
1921 || !dump_write(cprm->file, &phdr, sizeof(phdr)))
1922 goto end_coredump; 1914 goto end_coredump;
1915
1916 fill_elf_note_phdr(phdr4note, sz, offset);
1917 offset += sz;
1923 } 1918 }
1924 1919
1925 dataoff = offset = roundup(offset, ELF_EXEC_PAGESIZE); 1920 dataoff = offset = roundup(offset, ELF_EXEC_PAGESIZE);
@@ -1931,6 +1926,15 @@ static int elf_core_dump(struct coredump_params *cprm)
1931 */ 1926 */
1932 mm_flags = current->mm->flags; 1927 mm_flags = current->mm->flags;
1933 1928
1929 size += sizeof(*elf);
1930 if (size > cprm->limit || !dump_write(cprm->file, elf, sizeof(*elf)))
1931 goto end_coredump;
1932
1933 size += sizeof(*phdr4note);
1934 if (size > cprm->limit
1935 || !dump_write(cprm->file, phdr4note, sizeof(*phdr4note)))
1936 goto end_coredump;
1937
1934 /* Write program headers for segments dump */ 1938 /* Write program headers for segments dump */
1935 for (vma = first_vma(current, gate_vma); vma != NULL; 1939 for (vma = first_vma(current, gate_vma); vma != NULL;
1936 vma = next_vma(vma, gate_vma)) { 1940 vma = next_vma(vma, gate_vma)) {
@@ -2004,6 +2008,7 @@ end_coredump:
2004 2008
2005cleanup: 2009cleanup:
2006 free_note_info(&info); 2010 free_note_info(&info);
2011 kfree(phdr4note);
2007 kfree(elf); 2012 kfree(elf);
2008out: 2013out:
2009 return has_dumped; 2014 return has_dumped;
diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c
index 952699a86ec3..112da491d75d 100644
--- a/fs/binfmt_elf_fdpic.c
+++ b/fs/binfmt_elf_fdpic.c
@@ -1600,6 +1600,7 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
1600 int thread_status_size = 0; 1600 int thread_status_size = 0;
1601 elf_addr_t *auxv; 1601 elf_addr_t *auxv;
1602 unsigned long mm_flags; 1602 unsigned long mm_flags;
1603 struct elf_phdr *phdr4note = NULL;
1603 1604
1604 /* 1605 /*
1605 * We no longer stop all VM operations. 1606 * We no longer stop all VM operations.
@@ -1706,18 +1707,12 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
1706 fs = get_fs(); 1707 fs = get_fs();
1707 set_fs(KERNEL_DS); 1708 set_fs(KERNEL_DS);
1708 1709
1709 size += sizeof(*elf);
1710 if (size > cprm->limit
1711 || !dump_write(cprm->file, elf, sizeof(*elf)))
1712 goto end_coredump;
1713
1714 offset += sizeof(*elf); /* Elf header */ 1710 offset += sizeof(*elf); /* Elf header */
1715 offset += (segs+1) * sizeof(struct elf_phdr); /* Program headers */ 1711 offset += (segs+1) * sizeof(struct elf_phdr); /* Program headers */
1716 foffset = offset; 1712 foffset = offset;
1717 1713
1718 /* Write notes phdr entry */ 1714 /* Write notes phdr entry */
1719 { 1715 {
1720 struct elf_phdr phdr;
1721 int sz = 0; 1716 int sz = 0;
1722 1717
1723 for (i = 0; i < numnote; i++) 1718 for (i = 0; i < numnote; i++)
@@ -1725,13 +1720,12 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
1725 1720
1726 sz += thread_status_size; 1721 sz += thread_status_size;
1727 1722
1728 fill_elf_note_phdr(&phdr, sz, offset); 1723 phdr4note = kmalloc(sizeof(*phdr4note), GFP_KERNEL);
1729 offset += sz; 1724 if (!phdr4note)
1730
1731 size += sizeof(phdr);
1732 if (size > cprm->limit
1733 || !dump_write(cprm->file, &phdr, sizeof(phdr)))
1734 goto end_coredump; 1725 goto end_coredump;
1726
1727 fill_elf_note_phdr(phdr4note, sz, offset);
1728 offset += sz;
1735 } 1729 }
1736 1730
1737 /* Page-align dumped data */ 1731 /* Page-align dumped data */
@@ -1744,6 +1738,15 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
1744 */ 1738 */
1745 mm_flags = current->mm->flags; 1739 mm_flags = current->mm->flags;
1746 1740
1741 size += sizeof(*elf);
1742 if (size > cprm->limit || !dump_write(cprm->file, elf, sizeof(*elf)))
1743 goto end_coredump;
1744
1745 size += sizeof(*phdr4note);
1746 if (size > cprm->limit
1747 || !dump_write(cprm->file, phdr4note, sizeof(*phdr4note)))
1748 goto end_coredump;
1749
1747 /* write program headers for segments dump */ 1750 /* write program headers for segments dump */
1748 for (vma = current->mm->mmap; vma; vma = vma->vm_next) { 1751 for (vma = current->mm->mmap; vma; vma = vma->vm_next) {
1749 struct elf_phdr phdr; 1752 struct elf_phdr phdr;
@@ -1815,7 +1818,7 @@ cleanup:
1815 list_del(tmp); 1818 list_del(tmp);
1816 kfree(list_entry(tmp, struct elf_thread_status, list)); 1819 kfree(list_entry(tmp, struct elf_thread_status, list));
1817 } 1820 }
1818 1821 kfree(phdr4note);
1819 kfree(elf); 1822 kfree(elf);
1820 kfree(prstatus); 1823 kfree(prstatus);
1821 kfree(psinfo); 1824 kfree(psinfo);