lkml.org 
[lkml]   [2018]   [Mar]   [11]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Date
    Subject[PATCH 3.16 72/76] x86: fix SMAP in 32-bit environments
    3.16.56-rc1 review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Linus Torvalds <torvalds@linux-foundation.org>

    commit de9e478b9d49f3a0214310d921450cf5bb4a21e6 upstream.

    In commit 11f1a4b9755f ("x86: reorganize SMAP handling in user space
    accesses") I changed how the stac/clac instructions were generated
    around the user space accesses, which then made it possible to do
    batched accesses efficiently for user string copies etc.

    However, in doing so, I completely spaced out, and didn't even think
    about the 32-bit case. And nobody really even seemed to notice, because
    SMAP doesn't even exist until modern Skylake processors, and you'd have
    to be crazy to run 32-bit kernels on a modern CPU.

    Which brings us to Andy Lutomirski.

    He actually tested the 32-bit kernel on new hardware, and noticed that
    it doesn't work. My bad. The trivial fix is to add the required
    uaccess begin/end markers around the raw accesses in <asm/uaccess_32.h>.

    I feel a bit bad about this patch, just because that header file really
    should be cleaned up to avoid all the duplicated code in it, and this
    commit just expands on the problem. But this just fixes the bug without
    any bigger cleanup surgery.

    Reported-and-tested-by: Andy Lutomirski <luto@kernel.org>
    Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
    [bwh: Backported to 3.16: There's no 'case 8' in __copy_to_user_inatomic()]
    Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
    ---
    --- a/arch/x86/include/asm/uaccess_32.h
    +++ b/arch/x86/include/asm/uaccess_32.h
    @@ -48,16 +48,22 @@ __copy_to_user_inatomic(void __user *to,

    switch (n) {
    case 1:
    + __uaccess_begin();
    __put_user_size(*(u8 *)from, (u8 __user *)to,
    1, ret, 1);
    + __uaccess_end();
    return ret;
    case 2:
    + __uaccess_begin();
    __put_user_size(*(u16 *)from, (u16 __user *)to,
    2, ret, 2);
    + __uaccess_end();
    return ret;
    case 4:
    + __uaccess_begin();
    __put_user_size(*(u32 *)from, (u32 __user *)to,
    4, ret, 4);
    + __uaccess_end();
    return ret;
    }
    }
    @@ -98,13 +104,19 @@ __copy_from_user_inatomic(void *to, cons

    switch (n) {
    case 1:
    + __uaccess_begin();
    __get_user_size(*(u8 *)to, from, 1, ret, 1);
    + __uaccess_end();
    return ret;
    case 2:
    + __uaccess_begin();
    __get_user_size(*(u16 *)to, from, 2, ret, 2);
    + __uaccess_end();
    return ret;
    case 4:
    + __uaccess_begin();
    __get_user_size(*(u32 *)to, from, 4, ret, 4);
    + __uaccess_end();
    return ret;
    }
    }
    @@ -142,13 +154,19 @@ __copy_from_user(void *to, const void __

    switch (n) {
    case 1:
    + __uaccess_begin();
    __get_user_size(*(u8 *)to, from, 1, ret, 1);
    + __uaccess_end();
    return ret;
    case 2:
    + __uaccess_begin();
    __get_user_size(*(u16 *)to, from, 2, ret, 2);
    + __uaccess_end();
    return ret;
    case 4:
    + __uaccess_begin();
    __get_user_size(*(u32 *)to, from, 4, ret, 4);
    + __uaccess_end();
    return ret;
    }
    }
    @@ -164,13 +182,19 @@ static __always_inline unsigned long __c

    switch (n) {
    case 1:
    + __uaccess_begin();
    __get_user_size(*(u8 *)to, from, 1, ret, 1);
    + __uaccess_end();
    return ret;
    case 2:
    + __uaccess_begin();
    __get_user_size(*(u16 *)to, from, 2, ret, 2);
    + __uaccess_end();
    return ret;
    case 4:
    + __uaccess_begin();
    __get_user_size(*(u32 *)to, from, 4, ret, 4);
    + __uaccess_end();
    return ret;
    }
    }
    \
     
     \ /
      Last update: 2018-03-12 04:13    [W:4.178 / U:0.624 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site