lkml.org 
[lkml]   [2020]   [Jan]   [23]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v3 6/7] powerpc/32s: Prepare allow_user_access() for user_access_begin()
    Date
    In preparation of implementing user_access_begin and friends
    on powerpc, allow_user_access() need to be prepared for
    user_access_begin()

    user_access_end() doesn't provide the address and size which
    were passed to user_access_begin(), required by prevent_user_access()
    to know which segment to modify. But user_access_end() takes an
    opaque value returned by user_access_begin().

    Make allow_user_access() return the value it writes to current->kuap.
    This will allow user_access_end() to recalculate the segment range
    without having to read current->kuap.

    Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
    ---
    v3: Replaces the patch "Prepare prevent_user_access() for user_access_end()"
    ---
    arch/powerpc/include/asm/book3s/32/kup.h | 15 ++++++++++-----
    arch/powerpc/include/asm/book3s/64/kup-radix.h | 7 +++++--
    arch/powerpc/include/asm/kup.h | 8 ++++++--
    arch/powerpc/include/asm/nohash/32/kup-8xx.h | 6 ++++--
    4 files changed, 25 insertions(+), 11 deletions(-)

    diff --git a/arch/powerpc/include/asm/book3s/32/kup.h b/arch/powerpc/include/asm/book3s/32/kup.h
    index 3c1798e56b55..128dcbf3a19d 100644
    --- a/arch/powerpc/include/asm/book3s/32/kup.h
    +++ b/arch/powerpc/include/asm/book3s/32/kup.h
    @@ -102,23 +102,28 @@ static inline void kuap_update_sr(u32 sr, u32 addr, u32 end)
    isync(); /* Context sync required after mtsrin() */
    }

    -static __always_inline void allow_user_access(void __user *to, const void __user *from,
    - u32 size, unsigned long dir)
    +/* Make sure we never return 0. We only use top and bottom 4 bits */
    +static __always_inline unsigned long
    +allow_user_access(void __user *to, const void __user *from, u32 size, unsigned long dir)
    {
    u32 addr, end;
    + unsigned long kuap;

    BUILD_BUG_ON(!__builtin_constant_p(dir));
    if (!(dir & KUAP_W))
    - return;
    + return 0x100;

    addr = (__force u32)to;

    if (unlikely(addr >= TASK_SIZE || !size))
    - return;
    + return 0x100;

    end = min(addr + size, TASK_SIZE);
    - current->thread.kuap = (addr & 0xf0000000) | ((((end - 1) >> 28) + 1) & 0xf);
    + kuap = (addr & 0xf0000000) | ((((end - 1) >> 28) + 1) & 0xf);
    + current->thread.kuap = kuap;
    kuap_update_sr(mfsrin(addr) & ~SR_KS, addr, end); /* Clear Ks */
    +
    + return kuap;
    }

    static __always_inline void prevent_user_access(void __user *to, const void __user *from,
    diff --git a/arch/powerpc/include/asm/book3s/64/kup-radix.h b/arch/powerpc/include/asm/book3s/64/kup-radix.h
    index f11315306d41..183f0c87017b 100644
    --- a/arch/powerpc/include/asm/book3s/64/kup-radix.h
    +++ b/arch/powerpc/include/asm/book3s/64/kup-radix.h
    @@ -77,8 +77,9 @@ static inline void set_kuap(unsigned long value)
    isync();
    }

    -static __always_inline void allow_user_access(void __user *to, const void __user *from,
    - unsigned long size, unsigned long dir)
    +static __always_inline unsigned long
    +allow_user_access(void __user *to, const void __user *from,
    + unsigned long size, unsigned long dir)
    {
    // This is written so we can resolve to a single case at build time
    BUILD_BUG_ON(!__builtin_constant_p(dir));
    @@ -88,6 +89,8 @@ static __always_inline void allow_user_access(void __user *to, const void __user
    set_kuap(AMR_KUAP_BLOCK_READ);
    else
    set_kuap(0);
    +
    + return 1;
    }

    static inline void prevent_user_access(void __user *to, const void __user *from,
    diff --git a/arch/powerpc/include/asm/kup.h b/arch/powerpc/include/asm/kup.h
    index ff57bfcb88f7..691fec5afd4a 100644
    --- a/arch/powerpc/include/asm/kup.h
    +++ b/arch/powerpc/include/asm/kup.h
    @@ -45,8 +45,12 @@ static inline void setup_kuep(bool disabled) { }
    void setup_kuap(bool disabled);
    #else
    static inline void setup_kuap(bool disabled) { }
    -static inline void allow_user_access(void __user *to, const void __user *from,
    - unsigned long size, unsigned long dir) { }
    +static inline unsigned long allow_user_access(void __user *to, const void __user *from,
    + unsigned long size, unsigned long dir)
    +{
    + return 1;
    +}
    +
    static inline void prevent_user_access(void __user *to, const void __user *from,
    unsigned long size, unsigned long dir) { }
    static inline bool
    diff --git a/arch/powerpc/include/asm/nohash/32/kup-8xx.h b/arch/powerpc/include/asm/nohash/32/kup-8xx.h
    index 1d70c80366fd..ee673d3c0ab6 100644
    --- a/arch/powerpc/include/asm/nohash/32/kup-8xx.h
    +++ b/arch/powerpc/include/asm/nohash/32/kup-8xx.h
    @@ -34,10 +34,12 @@

    #include <asm/reg.h>

    -static inline void allow_user_access(void __user *to, const void __user *from,
    - unsigned long size, unsigned long dir)
    +static inline unsigned long allow_user_access(void __user *to, const void __user *from,
    + unsigned long size, unsigned long dir)
    {
    mtspr(SPRN_MD_AP, MD_APG_INIT);
    +
    + return 1;
    }

    static inline void prevent_user_access(void __user *to, const void __user *from,
    --
    2.25.0
    \
     
     \ /
      Last update: 2020-01-23 14:01    [W:3.423 / U:0.116 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site