lkml.org 
[lkml]   [2019]   [Dec]   [10]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH AUTOSEL 5.4 054/350] x86/math-emu: Check __copy_from_user() result
    Date
    From: Arnd Bergmann <arnd@arndb.de>

    [ Upstream commit e6b44ce1925a8329a937c57f0d60ba0d9bb5d226 ]

    The new __must_check annotation on __copy_from_user() successfully
    identified some code that has lacked the check since at least
    linux-2.1.73:

    arch/x86/math-emu/reg_ld_str.c:88:2: error: ignoring return value of \
    function declared with 'warn_unused_result' attribute [-Werror,-Wunused-result]
            __copy_from_user(sti_ptr, s, 10);
            ^~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~
    arch/x86/math-emu/reg_ld_str.c:1129:2: error: ignoring return value of \
    function declared with 'warn_unused_result' attribute [-Werror,-Wunused-result]
            __copy_from_user(register_base + offset, s, other);
            ^~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    arch/x86/math-emu/reg_ld_str.c:1131:3: error: ignoring return value of \
    function declared with 'warn_unused_result' attribute [-Werror,-Wunused-result]
                    __copy_from_user(register_base, s + other, offset);
                    ^~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    In addition, the get_user()/put_user() helpers do not enforce a return
    value check, but actually still require one. These have been missing for
    even longer.

    Change the internal wrappers around get_user()/put_user() to force
    a signal and add a corresponding wrapper around __copy_from_user()
    to check all such cases.

    [ bp: Break long lines. ]

    Fixes: 257e458057e5 ("Import 2.1.73")
    Fixes: 9dd819a15162 ("uaccess: add missing __must_check attributes")
    Signed-off-by: Arnd Bergmann <arnd@arndb.de>
    Signed-off-by: Borislav Petkov <bp@suse.de>
    Reviewed-by: Kees Cook <keescook@chromium.org>
    Cc: "H. Peter Anvin" <hpa@zytor.com>
    Cc: Bill Metzenthen <billm@melbpc.org.au>
    Cc: Ingo Molnar <mingo@redhat.com>
    Cc: Thomas Gleixner <tglx@linutronix.de>
    Cc: x86-ml <x86@kernel.org>
    Link: https://lkml.kernel.org/r/20191001142344.1274185-1-arnd@arndb.de
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    arch/x86/math-emu/fpu_system.h | 6 ++++--
    arch/x86/math-emu/reg_ld_str.c | 6 +++---
    2 files changed, 7 insertions(+), 5 deletions(-)

    diff --git a/arch/x86/math-emu/fpu_system.h b/arch/x86/math-emu/fpu_system.h
    index f98a0c9567646..9b41391867dca 100644
    --- a/arch/x86/math-emu/fpu_system.h
    +++ b/arch/x86/math-emu/fpu_system.h
    @@ -107,6 +107,8 @@ static inline bool seg_writable(struct desc_struct *d)
    #define FPU_access_ok(y,z) if ( !access_ok(y,z) ) \
    math_abort(FPU_info,SIGSEGV)
    #define FPU_abort math_abort(FPU_info, SIGSEGV)
    +#define FPU_copy_from_user(to, from, n) \
    + do { if (copy_from_user(to, from, n)) FPU_abort; } while (0)

    #undef FPU_IGNORE_CODE_SEGV
    #ifdef FPU_IGNORE_CODE_SEGV
    @@ -122,7 +124,7 @@ static inline bool seg_writable(struct desc_struct *d)
    #define FPU_code_access_ok(z) FPU_access_ok((void __user *)FPU_EIP,z)
    #endif

    -#define FPU_get_user(x,y) get_user((x),(y))
    -#define FPU_put_user(x,y) put_user((x),(y))
    +#define FPU_get_user(x,y) do { if (get_user((x),(y))) FPU_abort; } while (0)
    +#define FPU_put_user(x,y) do { if (put_user((x),(y))) FPU_abort; } while (0)

    #endif
    diff --git a/arch/x86/math-emu/reg_ld_str.c b/arch/x86/math-emu/reg_ld_str.c
    index f3779743d15e6..fe6246ff98870 100644
    --- a/arch/x86/math-emu/reg_ld_str.c
    +++ b/arch/x86/math-emu/reg_ld_str.c
    @@ -85,7 +85,7 @@ int FPU_load_extended(long double __user *s, int stnr)

    RE_ENTRANT_CHECK_OFF;
    FPU_access_ok(s, 10);
    - __copy_from_user(sti_ptr, s, 10);
    + FPU_copy_from_user(sti_ptr, s, 10);
    RE_ENTRANT_CHECK_ON;

    return FPU_tagof(sti_ptr);
    @@ -1126,9 +1126,9 @@ void frstor(fpu_addr_modes addr_modes, u_char __user *data_address)
    /* Copy all registers in stack order. */
    RE_ENTRANT_CHECK_OFF;
    FPU_access_ok(s, 80);
    - __copy_from_user(register_base + offset, s, other);
    + FPU_copy_from_user(register_base + offset, s, other);
    if (offset)
    - __copy_from_user(register_base, s + other, offset);
    + FPU_copy_from_user(register_base, s + other, offset);
    RE_ENTRANT_CHECK_ON;

    for (i = 0; i < 8; i++) {
    --
    2.20.1
    \
     
     \ /
      Last update: 2019-12-10 22:08    [W:2.046 / U:0.776 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site