Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 164468
b: refs/heads/master
c: f3e8fcc
h: refs/heads/master
v: v3
  • Loading branch information
Hugh Dickins authored and Linus Torvalds committed Sep 22, 2009
1 parent adf3309 commit 21a2a8a
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 69 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 1c3aff1ceec2cc86810e2690e67873ff0c505862
refs/heads/master: f3e8fccd06d27773186a0094371daf2d84c79469
44 changes: 14 additions & 30 deletions trunk/fs/binfmt_elf.c
Original file line number Diff line number Diff line change
Expand Up @@ -1280,9 +1280,6 @@ static int writenote(struct memelfnote *men, struct file *file,
#define DUMP_WRITE(addr, nr) \
if ((size += (nr)) > limit || !dump_write(file, (addr), (nr))) \
goto end_coredump;
#define DUMP_SEEK(off) \
if (!dump_seek(file, (off))) \
goto end_coredump;

static void fill_elf_header(struct elfhdr *elf, int segs,
u16 machine, u32 flags, u8 osabi)
Expand Down Expand Up @@ -2016,7 +2013,8 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file, un
goto end_coredump;

/* Align to page */
DUMP_SEEK(dataoff - foffset);
if (!dump_seek(file, dataoff - foffset))
goto end_coredump;

for (vma = first_vma(current, gate_vma); vma != NULL;
vma = next_vma(vma, gate_vma)) {
Expand All @@ -2027,33 +2025,19 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file, un

for (addr = vma->vm_start; addr < end; addr += PAGE_SIZE) {
struct page *page;
struct vm_area_struct *tmp_vma;

if (get_user_pages(current, current->mm, addr, 1, 0, 1,
&page, &tmp_vma) <= 0) {
DUMP_SEEK(PAGE_SIZE);
} else {
if (page == ZERO_PAGE(0)) {
if (!dump_seek(file, PAGE_SIZE)) {
page_cache_release(page);
goto end_coredump;
}
} else {
void *kaddr;
flush_cache_page(tmp_vma, addr,
page_to_pfn(page));
kaddr = kmap(page);
if ((size += PAGE_SIZE) > limit ||
!dump_write(file, kaddr,
PAGE_SIZE)) {
kunmap(page);
page_cache_release(page);
goto end_coredump;
}
kunmap(page);
}
int stop;

page = get_dump_page(addr);
if (page) {
void *kaddr = kmap(page);
stop = ((size += PAGE_SIZE) > limit) ||
!dump_write(file, kaddr, PAGE_SIZE);
kunmap(page);
page_cache_release(page);
}
} else
stop = !dump_seek(file, PAGE_SIZE);
if (stop)
goto end_coredump;
}
}

Expand Down
56 changes: 19 additions & 37 deletions trunk/fs/binfmt_elf_fdpic.c
Original file line number Diff line number Diff line change
Expand Up @@ -1325,9 +1325,6 @@ static int writenote(struct memelfnote *men, struct file *file)
#define DUMP_WRITE(addr, nr) \
if ((size += (nr)) > limit || !dump_write(file, (addr), (nr))) \
goto end_coredump;
#define DUMP_SEEK(off) \
if (!dump_seek(file, (off))) \
goto end_coredump;

static inline void fill_elf_fdpic_header(struct elfhdr *elf, int segs)
{
Expand Down Expand Up @@ -1518,50 +1515,34 @@ static int elf_fdpic_dump_segments(struct file *file, size_t *size,
unsigned long *limit, unsigned long mm_flags)
{
struct vm_area_struct *vma;
int err = 0;

for (vma = current->mm->mmap; vma; vma = vma->vm_next) {
unsigned long addr;

if (!maydump(vma, mm_flags))
continue;

for (addr = vma->vm_start;
addr < vma->vm_end;
addr += PAGE_SIZE
) {
struct vm_area_struct *vma;
struct page *page;

if (get_user_pages(current, current->mm, addr, 1, 0, 1,
&page, &vma) <= 0) {
DUMP_SEEK(file->f_pos + PAGE_SIZE);
}
else if (page == ZERO_PAGE(0)) {
page_cache_release(page);
DUMP_SEEK(file->f_pos + PAGE_SIZE);
}
else {
void *kaddr;

flush_cache_page(vma, addr, page_to_pfn(page));
kaddr = kmap(page);
if ((*size += PAGE_SIZE) > *limit ||
!dump_write(file, kaddr, PAGE_SIZE)
) {
kunmap(page);
page_cache_release(page);
return -EIO;
}
for (addr = vma->vm_start; addr < vma->vm_end;
addr += PAGE_SIZE) {
struct page *page = get_dump_page(addr);
if (page) {
void *kaddr = kmap(page);
*size += PAGE_SIZE;
if (*size > *limit)
err = -EFBIG;
else if (!dump_write(file, kaddr, PAGE_SIZE))
err = -EIO;
kunmap(page);
page_cache_release(page);
}
} else if (!dump_seek(file, file->f_pos + PAGE_SIZE))
err = -EFBIG;
if (err)
goto out;
}
}

return 0;

end_coredump:
return -EFBIG;
out:
return err;
}
#endif

Expand Down Expand Up @@ -1802,7 +1783,8 @@ static int elf_fdpic_core_dump(long signr, struct pt_regs *regs,
goto end_coredump;
}

DUMP_SEEK(dataoff);
if (!dump_seek(file, dataoff))
goto end_coredump;

if (elf_fdpic_dump_segments(file, &size, &limit, mm_flags) < 0)
goto end_coredump;
Expand Down
1 change: 1 addition & 0 deletions trunk/include/linux/mm.h
Original file line number Diff line number Diff line change
Expand Up @@ -817,6 +817,7 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
struct page **pages, struct vm_area_struct **vmas);
int get_user_pages_fast(unsigned long start, int nr_pages, int write,
struct page **pages);
struct page *get_dump_page(unsigned long addr);

extern int try_to_release_page(struct page * page, gfp_t gfp_mask);
extern void do_invalidatepage(struct page *page, unsigned long offset);
Expand Down
33 changes: 32 additions & 1 deletion trunk/mm/memory.c
Original file line number Diff line number Diff line change
Expand Up @@ -1423,9 +1423,40 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm,

return __get_user_pages(tsk, mm, start, nr_pages, flags, pages, vmas);
}

EXPORT_SYMBOL(get_user_pages);

/**
* get_dump_page() - pin user page in memory while writing it to core dump
* @addr: user address
*
* Returns struct page pointer of user page pinned for dump,
* to be freed afterwards by page_cache_release() or put_page().
*
* Returns NULL on any kind of failure - a hole must then be inserted into
* the corefile, to preserve alignment with its headers; and also returns
* NULL wherever the ZERO_PAGE, or an anonymous pte_none, has been found -
* allowing a hole to be left in the corefile to save diskspace.
*
* Called without mmap_sem, but after all other threads have been killed.
*/
#ifdef CONFIG_ELF_CORE
struct page *get_dump_page(unsigned long addr)
{
struct vm_area_struct *vma;
struct page *page;

if (__get_user_pages(current, current->mm, addr, 1,
GUP_FLAGS_FORCE, &page, &vma) < 1)
return NULL;
if (page == ZERO_PAGE(0)) {
page_cache_release(page);
return NULL;
}
flush_cache_page(vma, addr, page_to_pfn(page));
return page;
}
#endif /* CONFIG_ELF_CORE */

pte_t *get_locked_pte(struct mm_struct *mm, unsigned long addr,
spinlock_t **ptl)
{
Expand Down

0 comments on commit 21a2a8a

Please sign in to comment.