Messages in this thread Patch in this message | | | Date | Sun, 06 Jun 2021 01:47:56 +0200 | From | Thomas Gleixner <> | Subject | [patch V2 14/14] x86/fpu: Deduplicate copy_uabi_from_user/kernel_to_xstate() |
| |
copy_uabi_from_user_to_xstate() and copy_uabi_from_kernel_to_xstate() are almost identical except for the copy function.
Unify them.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Acked-by: Andy Lutomirski <luto@kernel.org> --- V2: Adjusted to the rename. --- arch/x86/kernel/fpu/xstate.c | 83 +++++++++++++++---------------------------- 1 file changed, 29 insertions(+), 54 deletions(-)
--- a/arch/x86/kernel/fpu/xstate.c +++ b/arch/x86/kernel/fpu/xstate.c @@ -1124,20 +1124,30 @@ void copy_uabi_xstate_to_kernel(struct m fill_gap(&to, &last, size); } -/* - * Convert from a ptrace standard-format kernel buffer to kernel XSAVES format - * and copy to the target thread. This is called from xstateregs_set(). - */ -int copy_uabi_from_kernel_to_xstate(struct xregs_state *xsave, const void *kbuf) +static int copy_from_buffer(void *dst, unsigned int offset, unsigned int size, + const void *kbuf, const void __user *ubuf) +{ + if (kbuf) { + memcpy(dst, kbuf + offset, size); + } else { + if (copy_from_user(dst, ubuf + offset, size)) + return -EFAULT; + } + return 0; +} + +static int copy_uabi_to_xstate(struct xregs_state *xsave, const void *kbuf, + const void __user *ubuf) { unsigned int offset, size; - int i; struct xstate_header hdr; + int i; offset = offsetof(struct xregs_state, header); size = sizeof(hdr); - memcpy(&hdr, kbuf + offset, size); + if (copy_from_buffer(&hdr, offset, size, kbuf, ubuf)) + return -EFAULT; if (validate_user_xstate_header(&hdr)) return -EINVAL; @@ -1151,7 +1161,8 @@ int copy_uabi_from_kernel_to_xstate(stru offset = xstate_offsets[i]; size = xstate_sizes[i]; - memcpy(dst, kbuf + offset, size); + if (copy_from_buffer(dst, offset, size, kbuf, ubuf)) + return -EFAULT; } } @@ -1179,6 +1190,15 @@ int copy_uabi_from_kernel_to_xstate(stru } /* + * Convert from a ptrace standard-format kernel buffer to kernel XSAVES format + * and copy to the target thread. This is called from xstateregs_set(). + */ +int copy_uabi_from_kernel_to_xstate(struct xregs_state *xsave, const void *kbuf) +{ + return copy_uabi_to_xstate(xsave, kbuf, NULL); +} + +/* * Convert from a sigreturn standard-format user-space buffer to kernel * XSAVES format and copy to the target thread. This is called from the * sigreturn() and rt_sigreturn() system calls. @@ -1186,52 +1206,7 @@ int copy_uabi_from_kernel_to_xstate(stru int copy_uabi_from_user_to_xstate(struct xregs_state *xsave, const void __user *ubuf) { - unsigned int offset, size; - int i; - struct xstate_header hdr; - - offset = offsetof(struct xregs_state, header); - size = sizeof(hdr); - - if (copy_from_user(&hdr, ubuf + offset, size)) - return -EFAULT; - - if (validate_user_xstate_header(&hdr)) - return -EINVAL; - - for (i = 0; i < XFEATURE_MAX; i++) { - u64 mask = ((u64)1 << i); - - if (hdr.xfeatures & mask) { - void *dst = __raw_xsave_addr(xsave, i); - - offset = xstate_offsets[i]; - size = xstate_sizes[i]; - - if (copy_from_user(dst, ubuf + offset, size)) - return -EFAULT; - } - } - - if (xfeatures_mxcsr_quirk(hdr.xfeatures)) { - offset = offsetof(struct fxregs_state, mxcsr); - size = MXCSR_AND_FLAGS_SIZE; - if (copy_from_user(&xsave->i387.mxcsr, 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_ALL; - - /* - * Add back in the features that came in from userspace: - */ - xsave->header.xfeatures |= hdr.xfeatures; - - return 0; + return copy_uabi_to_xstate(xsave, NULL, ubuf); } /*
| |