lkml.org 
[lkml]   [2017]   [Jan]   [26]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 11/14] x86/fpu: Split copy_user_to_xstate() into copy_kernel_to_xstate() & copy_user_to_xstate()
    Date
    Similar to:

    x86/fpu: Split copy_xstate_to_user() into copy_xstate_to_kernel() & copy_xstate_to_user()

    No change in functionality.

    Cc: Andy Lutomirski <luto@kernel.org>
    Cc: Borislav Petkov <bp@alien8.de>
    Cc: Dave Hansen <dave.hansen@linux.intel.com>
    Cc: Fenghua Yu <fenghua.yu@intel.com>
    Cc: H. Peter Anvin <hpa@zytor.com>
    Cc: Linus Torvalds <torvalds@linux-foundation.org>
    Cc: Oleg Nesterov <oleg@redhat.com>
    Cc: Rik van Riel <riel@redhat.com>
    Cc: Thomas Gleixner <tglx@linutronix.de>
    Cc: Yu-cheng Yu <yu-cheng.yu@intel.com>
    Cc: Fenghua Yu <fenghua.yu@intel.com>
    Signed-off-by: Ingo Molnar <mingo@kernel.org>
    ---
    arch/x86/include/asm/fpu/xstate.h | 4 ++--
    arch/x86/kernel/fpu/regset.c | 10 ++++++---
    arch/x86/kernel/fpu/xstate.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
    3 files changed, 74 insertions(+), 6 deletions(-)

    diff --git a/arch/x86/include/asm/fpu/xstate.h b/arch/x86/include/asm/fpu/xstate.h
    index fed6617a1079..79af79dbcab6 100644
    --- a/arch/x86/include/asm/fpu/xstate.h
    +++ b/arch/x86/include/asm/fpu/xstate.h
    @@ -50,6 +50,6 @@ const void *get_xsave_field_ptr(int xstate_field);
    int using_compacted_format(void);
    int copy_xstate_to_kernel(void *kbuf, struct xregs_state *xsave, unsigned int offset, unsigned int size);
    int copy_xstate_to_user(void __user *ubuf, struct xregs_state *xsave, unsigned int offset, unsigned int size);
    -int copy_user_to_xstate(const void *kbuf, const void __user *ubuf,
    - struct xregs_state *xsave);
    +int copy_kernel_to_xstate(const void *kbuf, const void __user *ubuf, struct xregs_state *xsave);
    +int copy_user_to_xstate(const void *kbuf, const void __user *ubuf, struct xregs_state *xsave);
    #endif
    diff --git a/arch/x86/kernel/fpu/regset.c b/arch/x86/kernel/fpu/regset.c
    index 72cf367627e2..ea9e53d2bd8a 100644
    --- a/arch/x86/kernel/fpu/regset.c
    +++ b/arch/x86/kernel/fpu/regset.c
    @@ -133,10 +133,14 @@ int xstateregs_set(struct task_struct *target, const struct user_regset *regset,

    fpu__activate_fpstate_write(fpu);

    - if (boot_cpu_has(X86_FEATURE_XSAVES))
    - ret = copy_user_to_xstate(kbuf, ubuf, xsave);
    - else
    + if (boot_cpu_has(X86_FEATURE_XSAVES)) {
    + if (kbuf)
    + ret = copy_kernel_to_xstate(kbuf, ubuf, xsave);
    + else
    + ret = copy_user_to_xstate(kbuf, ubuf, xsave);
    + } else {
    ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, xsave, 0, -1);
    + }

    /*
    * In case of failure, mark all states as init:
    diff --git a/arch/x86/kernel/fpu/xstate.c b/arch/x86/kernel/fpu/xstate.c
    index 7d24fe305d4b..aed9b2cb4d3d 100644
    --- a/arch/x86/kernel/fpu/xstate.c
    +++ b/arch/x86/kernel/fpu/xstate.c
    @@ -1083,7 +1083,71 @@ int copy_xstate_to_user(void __user *ubuf, struct xregs_state *xsave, unsigned i
    }

    /*
    - * Convert from a ptrace standard-format buffer to kernel XSAVES format
    + * Convert from a ptrace standard-format kernel buffer to kernel XSAVES format
    + * and copy to the target thread. This is called from xstateregs_set() and
    + * there we check the CPU has XSAVES and a whole standard-sized buffer
    + * exists.
    + */
    +int copy_kernel_to_xstate(const void *kbuf, const void __user *ubuf,
    + struct xregs_state *xsave)
    +{
    + unsigned int offset, size;
    + int i;
    + u64 xfeatures;
    + u64 allowed_features;
    +
    + offset = offsetof(struct xregs_state, header);
    + size = sizeof(xfeatures);
    +
    + if (kbuf) {
    + memcpy(&xfeatures, kbuf + offset, size);
    + } else {
    + if (__copy_from_user(&xfeatures, ubuf + offset, size))
    + return -EFAULT;
    + }
    +
    + /*
    + * Reject if the user sets any disabled or supervisor features:
    + */
    + allowed_features = xfeatures_mask & ~XFEATURE_MASK_SUPERVISOR;
    +
    + if (xfeatures & ~allowed_features)
    + return -EINVAL;
    +
    + for (i = 0; i < XFEATURE_MAX; i++) {
    + u64 mask = ((u64)1 << i);
    +
    + if (xfeatures & mask) {
    + void *dst = __raw_xsave_addr(xsave, 1 << i);
    +
    + offset = xstate_offsets[i];
    + size = xstate_sizes[i];
    +
    + if (kbuf) {
    + memcpy(dst, kbuf + offset, size);
    + } else {
    + if (__copy_from_user(dst, ubuf + offset, size))
    + return -EFAULT;
    + }
    + }
    + }
    +
    + /*
    + * The state that came in from userspace was user-state only.
    + * Mask all the user states out of 'xfeatures':
    + */
    + xsave->header.xfeatures &= XFEATURE_MASK_SUPERVISOR;
    +
    + /*
    + * Add back in the features that came in from userspace:
    + */
    + xsave->header.xfeatures |= xfeatures;
    +
    + return 0;
    +}
    +
    +/*
    + * Convert from a ptrace standard-format user-space buffer to kernel XSAVES format
    * and copy to the target thread. This is called from xstateregs_set() and
    * there we check the CPU has XSAVES and a whole standard-sized buffer
    * exists.
    --
    2.7.4
    \
     
     \ /
      Last update: 2017-01-26 11:27    [W:7.157 / U:0.196 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site