lkml.org 
[lkml]   [2022]   [Jan]   [24]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.14 180/186] mips,s390,sh,sparc: gup: Work around the "COW can break either way" issue
    Date
    From: Ben Hutchings <ben@decadent.org.uk>

    In Linux 4.14 and 4.19 these architectures still have their own
    implementations of get_user_pages_fast(). These also need to force
    the write flag on when taking the fast path.

    Fixes: 407faed92b4a ("gup: document and work around "COW can break either way" issue")
    Fixes: 5e24029791e8 ("gup: document and work around "COW can break either way" issue")
    Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
    ---
    arch/mips/mm/gup.c | 9 ++++++++-
    arch/s390/mm/gup.c | 9 ++++++++-
    arch/sh/mm/gup.c | 9 ++++++++-
    arch/sparc/mm/gup.c | 9 ++++++++-
    4 files changed, 32 insertions(+), 4 deletions(-)

    --- a/arch/mips/mm/gup.c
    +++ b/arch/mips/mm/gup.c
    @@ -272,7 +272,14 @@ int get_user_pages_fast(unsigned long st
    next = pgd_addr_end(addr, end);
    if (pgd_none(pgd))
    goto slow;
    - if (!gup_pud_range(pgd, addr, next, write, pages, &nr))
    + /*
    + * The FAST_GUP case requires FOLL_WRITE even for pure reads,
    + * because get_user_pages() may need to cause an early COW in
    + * order to avoid confusing the normal COW routines. So only
    + * targets that are already writable are safe to do by just
    + * looking at the page tables.
    + */
    + if (!gup_pud_range(pgd, addr, next, 1, pages, &nr))
    goto slow;
    } while (pgdp++, addr = next, addr != end);
    local_irq_enable();
    --- a/arch/s390/mm/gup.c
    +++ b/arch/s390/mm/gup.c
    @@ -285,7 +285,14 @@ int get_user_pages_fast(unsigned long st

    might_sleep();
    start &= PAGE_MASK;
    - nr = __get_user_pages_fast(start, nr_pages, write, pages);
    + /*
    + * The FAST_GUP case requires FOLL_WRITE even for pure reads,
    + * because get_user_pages() may need to cause an early COW in
    + * order to avoid confusing the normal COW routines. So only
    + * targets that are already writable are safe to do by just
    + * looking at the page tables.
    + */
    + nr = __get_user_pages_fast(start, nr_pages, 1, pages);
    if (nr == nr_pages)
    return nr;

    --- a/arch/sh/mm/gup.c
    +++ b/arch/sh/mm/gup.c
    @@ -240,7 +240,14 @@ int get_user_pages_fast(unsigned long st
    next = pgd_addr_end(addr, end);
    if (pgd_none(pgd))
    goto slow;
    - if (!gup_pud_range(pgd, addr, next, write, pages, &nr))
    + /*
    + * The FAST_GUP case requires FOLL_WRITE even for pure reads,
    + * because get_user_pages() may need to cause an early COW in
    + * order to avoid confusing the normal COW routines. So only
    + * targets that are already writable are safe to do by just
    + * looking at the page tables.
    + */
    + if (!gup_pud_range(pgd, addr, next, 1, pages, &nr))
    goto slow;
    } while (pgdp++, addr = next, addr != end);
    local_irq_enable();
    --- a/arch/sparc/mm/gup.c
    +++ b/arch/sparc/mm/gup.c
    @@ -262,7 +262,14 @@ int get_user_pages_fast(unsigned long st
    next = pgd_addr_end(addr, end);
    if (pgd_none(pgd))
    goto slow;
    - if (!gup_pud_range(pgd, addr, next, write, pages, &nr))
    + /*
    + * The FAST_GUP case requires FOLL_WRITE even for pure reads,
    + * because get_user_pages() may need to cause an early COW in
    + * order to avoid confusing the normal COW routines. So only
    + * targets that are already writable are safe to do by just
    + * looking at the page tables.
    + */
    + if (!gup_pud_range(pgd, addr, next, 1, pages, &nr))
    goto slow;
    } while (pgdp++, addr = next, addr != end);


    \
     
     \ /
      Last update: 2022-01-24 20:40    [W:4.150 / U:0.088 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site