lkml.org 
[lkml]   [2020]   [Aug]   [27]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    Subject[PATCH v5 1/7] binfmt_elf_fdpic: Stop using dump_emit() on user pointers on !MMU
    From
    dump_emit() is for kernel pointers, and VMAs describe userspace memory.
    Let's be tidy here and avoid accessing userspace pointers under KERNEL_DS,
    even if it probably doesn't matter much on !MMU systems - especially given
    that it looks like we can just use the same get_dump_page() as on MMU if
    we move it out of the CONFIG_MMU block.

    One small change we have to make in get_dump_page() is to use
    __get_user_pages_locked() instead of __get_user_pages(), since the
    latter doesn't exist on nommu. On mmu builds, __get_user_pages_locked()
    will just call __get_user_pages() for us.

    Signed-off-by: Jann Horn <jannh@google.com>
    ---
    fs/binfmt_elf_fdpic.c | 8 ------
    mm/gup.c | 57 +++++++++++++++++++++----------------------
    2 files changed, 28 insertions(+), 37 deletions(-)

    diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c
    index 50f845702b92..a53f83830986 100644
    --- a/fs/binfmt_elf_fdpic.c
    +++ b/fs/binfmt_elf_fdpic.c
    @@ -1529,14 +1529,11 @@ static bool elf_fdpic_dump_segments(struct coredump_params *cprm)
    struct vm_area_struct *vma;

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

    if (!maydump(vma, cprm->mm_flags))
    continue;

    -#ifdef CONFIG_MMU
    for (addr = vma->vm_start; addr < vma->vm_end;
    addr += PAGE_SIZE) {
    bool res;
    @@ -1552,11 +1549,6 @@ static bool elf_fdpic_dump_segments(struct coredump_params *cprm)
    if (!res)
    return false;
    }
    -#else
    - if (!dump_emit(cprm, (void *) vma->vm_start,
    - vma->vm_end - vma->vm_start))
    - return false;
    -#endif
    }
    return true;
    }
    diff --git a/mm/gup.c b/mm/gup.c
    index ae096ea7583f..92519e5a44b3 100644
    --- a/mm/gup.c
    +++ b/mm/gup.c
    @@ -1495,35 +1495,6 @@ int __mm_populate(unsigned long start, unsigned long len, int ignore_errors)
    mmap_read_unlock(mm);
    return ret; /* 0 or negative error code */
    }
    -
    -/**
    - * 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 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_lock, 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->mm, addr, 1,
    - FOLL_FORCE | FOLL_DUMP | FOLL_GET, &page, &vma,
    - NULL) < 1)
    - return NULL;
    - flush_cache_page(vma, addr, page_to_pfn(page));
    - return page;
    -}
    -#endif /* CONFIG_ELF_CORE */
    #else /* CONFIG_MMU */
    static long __get_user_pages_locked(struct mm_struct *mm, unsigned long start,
    unsigned long nr_pages, struct page **pages,
    @@ -1569,6 +1540,34 @@ static long __get_user_pages_locked(struct mm_struct *mm, unsigned long start,
    }
    #endif /* !CONFIG_MMU */

    +/**
    + * 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 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_lock, 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_locked(current->mm, addr, 1, &page, &vma, NULL,
    + FOLL_FORCE | FOLL_DUMP | FOLL_GET) < 1)
    + return NULL;
    + flush_cache_page(vma, addr, page_to_pfn(page));
    + return page;
    +}
    +#endif /* CONFIG_ELF_CORE */
    +
    #if defined(CONFIG_FS_DAX) || defined (CONFIG_CMA)
    static bool check_dax_vmas(struct vm_area_struct **vmas, long nr_pages)
    {
    --
    2.28.0.297.g1956fa8f8d-goog
    \
     
     \ /
      Last update: 2020-08-27 17:10    [W:3.890 / U:0.004 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site