lkml.org 
[lkml]   [2021]   [Jul]   [27]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v5 3/6] mm: simplify compat_sys_move_pages
    Date
    From: Arnd Bergmann <arnd@arndb.de>

    The compat move_pages() implementation uses compat_alloc_user_space()
    for converting the pointer array. Moving the compat handling into
    the function itself is a bit simpler and lets us avoid the
    compat_alloc_user_space() call.

    Reviewed-by: Christoph Hellwig <hch@lst.de>
    Signed-off-by: Arnd Bergmann <arnd@arndb.de>
    ---
    mm/migrate.c | 45 ++++++++++++++++++++++++++++++---------------
    1 file changed, 30 insertions(+), 15 deletions(-)

    diff --git a/mm/migrate.c b/mm/migrate.c
    index 34a9ad3e0a4f..60634d2653b9 100644
    --- a/mm/migrate.c
    +++ b/mm/migrate.c
    @@ -1820,6 +1820,23 @@ static void do_pages_stat_array(struct mm_struct *mm, unsigned long nr_pages,
    mmap_read_unlock(mm);
    }

    +static int get_compat_pages_array(const void __user *chunk_pages[],
    + const void __user * __user *pages,
    + unsigned long chunk_nr)
    +{
    + compat_uptr_t __user *pages32 = (compat_uptr_t __user *)pages;
    + compat_uptr_t p;
    + int i;
    +
    + for (i = 0; i < chunk_nr; i++) {
    + if (get_user(p, pages32 + i))
    + return -EFAULT;
    + chunk_pages[i] = compat_ptr(p);
    + }
    +
    + return 0;
    +}
    +
    /*
    * Determine the nodes of a user array of pages and store it in
    * a user array of status.
    @@ -1839,8 +1856,15 @@ static int do_pages_stat(struct mm_struct *mm, unsigned long nr_pages,
    if (chunk_nr > DO_PAGES_STAT_CHUNK_NR)
    chunk_nr = DO_PAGES_STAT_CHUNK_NR;

    - if (copy_from_user(chunk_pages, pages, chunk_nr * sizeof(*chunk_pages)))
    - break;
    + if (in_compat_syscall()) {
    + if (get_compat_pages_array(chunk_pages, pages,
    + chunk_nr))
    + break;
    + } else {
    + if (copy_from_user(chunk_pages, pages,
    + chunk_nr * sizeof(*chunk_pages)))
    + break;
    + }

    do_pages_stat_array(mm, chunk_nr, chunk_pages, chunk_status);

    @@ -1945,23 +1969,14 @@ SYSCALL_DEFINE6(move_pages, pid_t, pid, unsigned long, nr_pages,

    #ifdef CONFIG_COMPAT
    COMPAT_SYSCALL_DEFINE6(move_pages, pid_t, pid, compat_ulong_t, nr_pages,
    - compat_uptr_t __user *, pages32,
    + compat_uptr_t __user *, pages,
    const int __user *, nodes,
    int __user *, status,
    int, flags)
    {
    - const void __user * __user *pages;
    - int i;
    -
    - pages = compat_alloc_user_space(nr_pages * sizeof(void *));
    - for (i = 0; i < nr_pages; i++) {
    - compat_uptr_t p;
    -
    - if (get_user(p, pages32 + i) ||
    - put_user(compat_ptr(p), pages + i))
    - return -EFAULT;
    - }
    - return kernel_move_pages(pid, nr_pages, pages, nodes, status, flags);
    + return kernel_move_pages(pid, nr_pages,
    + (const void __user *__user *)pages,
    + nodes, status, flags);
    }
    #endif /* CONFIG_COMPAT */

    --
    2.29.2
    \
     
     \ /
      Last update: 2021-07-27 16:52    [W:5.021 / U:0.012 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site