diff options
Diffstat (limited to 'fs/binfmt_elf.c')
-rw-r--r-- | fs/binfmt_elf.c | 124 |
1 files changed, 58 insertions, 66 deletions
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index b7c1603cd4bd..b9b3bb51b1e4 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c | |||
@@ -501,22 +501,22 @@ static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex, | |||
501 | } | 501 | } |
502 | } | 502 | } |
503 | 503 | ||
504 | /* | 504 | if (last_bss > elf_bss) { |
505 | * Now fill out the bss section. First pad the last page up | 505 | /* |
506 | * to the page boundary, and then perform a mmap to make sure | 506 | * Now fill out the bss section. First pad the last page up |
507 | * that there are zero-mapped pages up to and including the | 507 | * to the page boundary, and then perform a mmap to make sure |
508 | * last bss page. | 508 | * that there are zero-mapped pages up to and including the |
509 | */ | 509 | * last bss page. |
510 | if (padzero(elf_bss)) { | 510 | */ |
511 | error = -EFAULT; | 511 | if (padzero(elf_bss)) { |
512 | goto out_close; | 512 | error = -EFAULT; |
513 | } | 513 | goto out_close; |
514 | } | ||
514 | 515 | ||
515 | /* What we have mapped so far */ | 516 | /* What we have mapped so far */ |
516 | elf_bss = ELF_PAGESTART(elf_bss + ELF_MIN_ALIGN - 1); | 517 | elf_bss = ELF_PAGESTART(elf_bss + ELF_MIN_ALIGN - 1); |
517 | 518 | ||
518 | /* Map the last of the bss segment */ | 519 | /* Map the last of the bss segment */ |
519 | if (last_bss > elf_bss) { | ||
520 | down_write(¤t->mm->mmap_sem); | 520 | down_write(¤t->mm->mmap_sem); |
521 | error = do_brk(elf_bss, last_bss - elf_bss); | 521 | error = do_brk(elf_bss, last_bss - elf_bss); |
522 | up_write(¤t->mm->mmap_sem); | 522 | up_write(¤t->mm->mmap_sem); |
@@ -1280,9 +1280,6 @@ static int writenote(struct memelfnote *men, struct file *file, | |||
1280 | #define DUMP_WRITE(addr, nr) \ | 1280 | #define DUMP_WRITE(addr, nr) \ |
1281 | if ((size += (nr)) > limit || !dump_write(file, (addr), (nr))) \ | 1281 | if ((size += (nr)) > limit || !dump_write(file, (addr), (nr))) \ |
1282 | goto end_coredump; | 1282 | goto end_coredump; |
1283 | #define DUMP_SEEK(off) \ | ||
1284 | if (!dump_seek(file, (off))) \ | ||
1285 | goto end_coredump; | ||
1286 | 1283 | ||
1287 | static void fill_elf_header(struct elfhdr *elf, int segs, | 1284 | static void fill_elf_header(struct elfhdr *elf, int segs, |
1288 | u16 machine, u32 flags, u8 osabi) | 1285 | u16 machine, u32 flags, u8 osabi) |
@@ -1714,42 +1711,52 @@ struct elf_note_info { | |||
1714 | int numnote; | 1711 | int numnote; |
1715 | }; | 1712 | }; |
1716 | 1713 | ||
1717 | static int fill_note_info(struct elfhdr *elf, int phdrs, | 1714 | static int elf_note_info_init(struct elf_note_info *info) |
1718 | struct elf_note_info *info, | ||
1719 | long signr, struct pt_regs *regs) | ||
1720 | { | 1715 | { |
1721 | #define NUM_NOTES 6 | 1716 | memset(info, 0, sizeof(*info)); |
1722 | struct list_head *t; | ||
1723 | |||
1724 | info->notes = NULL; | ||
1725 | info->prstatus = NULL; | ||
1726 | info->psinfo = NULL; | ||
1727 | info->fpu = NULL; | ||
1728 | #ifdef ELF_CORE_COPY_XFPREGS | ||
1729 | info->xfpu = NULL; | ||
1730 | #endif | ||
1731 | INIT_LIST_HEAD(&info->thread_list); | 1717 | INIT_LIST_HEAD(&info->thread_list); |
1732 | 1718 | ||
1733 | info->notes = kmalloc(NUM_NOTES * sizeof(struct memelfnote), | 1719 | /* Allocate space for six ELF notes */ |
1734 | GFP_KERNEL); | 1720 | info->notes = kmalloc(6 * sizeof(struct memelfnote), GFP_KERNEL); |
1735 | if (!info->notes) | 1721 | if (!info->notes) |
1736 | return 0; | 1722 | return 0; |
1737 | info->psinfo = kmalloc(sizeof(*info->psinfo), GFP_KERNEL); | 1723 | info->psinfo = kmalloc(sizeof(*info->psinfo), GFP_KERNEL); |
1738 | if (!info->psinfo) | 1724 | if (!info->psinfo) |
1739 | return 0; | 1725 | goto notes_free; |
1740 | info->prstatus = kmalloc(sizeof(*info->prstatus), GFP_KERNEL); | 1726 | info->prstatus = kmalloc(sizeof(*info->prstatus), GFP_KERNEL); |
1741 | if (!info->prstatus) | 1727 | if (!info->prstatus) |
1742 | return 0; | 1728 | goto psinfo_free; |
1743 | info->fpu = kmalloc(sizeof(*info->fpu), GFP_KERNEL); | 1729 | info->fpu = kmalloc(sizeof(*info->fpu), GFP_KERNEL); |
1744 | if (!info->fpu) | 1730 | if (!info->fpu) |
1745 | return 0; | 1731 | goto prstatus_free; |
1746 | #ifdef ELF_CORE_COPY_XFPREGS | 1732 | #ifdef ELF_CORE_COPY_XFPREGS |
1747 | info->xfpu = kmalloc(sizeof(*info->xfpu), GFP_KERNEL); | 1733 | info->xfpu = kmalloc(sizeof(*info->xfpu), GFP_KERNEL); |
1748 | if (!info->xfpu) | 1734 | if (!info->xfpu) |
1749 | return 0; | 1735 | goto fpu_free; |
1736 | #endif | ||
1737 | return 1; | ||
1738 | #ifdef ELF_CORE_COPY_XFPREGS | ||
1739 | fpu_free: | ||
1740 | kfree(info->fpu); | ||
1750 | #endif | 1741 | #endif |
1742 | prstatus_free: | ||
1743 | kfree(info->prstatus); | ||
1744 | psinfo_free: | ||
1745 | kfree(info->psinfo); | ||
1746 | notes_free: | ||
1747 | kfree(info->notes); | ||
1748 | return 0; | ||
1749 | } | ||
1750 | |||
1751 | static int fill_note_info(struct elfhdr *elf, int phdrs, | ||
1752 | struct elf_note_info *info, | ||
1753 | long signr, struct pt_regs *regs) | ||
1754 | { | ||
1755 | struct list_head *t; | ||
1756 | |||
1757 | if (!elf_note_info_init(info)) | ||
1758 | return 0; | ||
1751 | 1759 | ||
1752 | info->thread_status_size = 0; | ||
1753 | if (signr) { | 1760 | if (signr) { |
1754 | struct core_thread *ct; | 1761 | struct core_thread *ct; |
1755 | struct elf_thread_status *ets; | 1762 | struct elf_thread_status *ets; |
@@ -1809,8 +1816,6 @@ static int fill_note_info(struct elfhdr *elf, int phdrs, | |||
1809 | #endif | 1816 | #endif |
1810 | 1817 | ||
1811 | return 1; | 1818 | return 1; |
1812 | |||
1813 | #undef NUM_NOTES | ||
1814 | } | 1819 | } |
1815 | 1820 | ||
1816 | static size_t get_note_info_size(struct elf_note_info *info) | 1821 | static size_t get_note_info_size(struct elf_note_info *info) |
@@ -2016,7 +2021,8 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file, un | |||
2016 | goto end_coredump; | 2021 | goto end_coredump; |
2017 | 2022 | ||
2018 | /* Align to page */ | 2023 | /* Align to page */ |
2019 | DUMP_SEEK(dataoff - foffset); | 2024 | if (!dump_seek(file, dataoff - foffset)) |
2025 | goto end_coredump; | ||
2020 | 2026 | ||
2021 | for (vma = first_vma(current, gate_vma); vma != NULL; | 2027 | for (vma = first_vma(current, gate_vma); vma != NULL; |
2022 | vma = next_vma(vma, gate_vma)) { | 2028 | vma = next_vma(vma, gate_vma)) { |
@@ -2027,33 +2033,19 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file, un | |||
2027 | 2033 | ||
2028 | for (addr = vma->vm_start; addr < end; addr += PAGE_SIZE) { | 2034 | for (addr = vma->vm_start; addr < end; addr += PAGE_SIZE) { |
2029 | struct page *page; | 2035 | struct page *page; |
2030 | struct vm_area_struct *tmp_vma; | 2036 | int stop; |
2031 | 2037 | ||
2032 | if (get_user_pages(current, current->mm, addr, 1, 0, 1, | 2038 | page = get_dump_page(addr); |
2033 | &page, &tmp_vma) <= 0) { | 2039 | if (page) { |
2034 | DUMP_SEEK(PAGE_SIZE); | 2040 | void *kaddr = kmap(page); |
2035 | } else { | 2041 | stop = ((size += PAGE_SIZE) > limit) || |
2036 | if (page == ZERO_PAGE(0)) { | 2042 | !dump_write(file, kaddr, PAGE_SIZE); |
2037 | if (!dump_seek(file, PAGE_SIZE)) { | 2043 | kunmap(page); |
2038 | page_cache_release(page); | ||
2039 | goto end_coredump; | ||
2040 | } | ||
2041 | } else { | ||
2042 | void *kaddr; | ||
2043 | flush_cache_page(tmp_vma, addr, | ||
2044 | page_to_pfn(page)); | ||
2045 | kaddr = kmap(page); | ||
2046 | if ((size += PAGE_SIZE) > limit || | ||
2047 | !dump_write(file, kaddr, | ||
2048 | PAGE_SIZE)) { | ||
2049 | kunmap(page); | ||
2050 | page_cache_release(page); | ||
2051 | goto end_coredump; | ||
2052 | } | ||
2053 | kunmap(page); | ||
2054 | } | ||
2055 | page_cache_release(page); | 2044 | page_cache_release(page); |
2056 | } | 2045 | } else |
2046 | stop = !dump_seek(file, PAGE_SIZE); | ||
2047 | if (stop) | ||
2048 | goto end_coredump; | ||
2057 | } | 2049 | } |
2058 | } | 2050 | } |
2059 | 2051 | ||