Commit 1005c2d3 authored by Andy Lutomirski's avatar Andy Lutomirski Committed by Zheng Zengkai
Browse files

x86/fpu: Add address range checks to copy_user_to_xstate()

mainline inclusion
from mainline-v5.13-rc7
commit f72a249b
category: feature
feature: milan cpu
bugzilla: https://gitee.com/openeuler/kernel/issues/I4M9PB


CVE: NA

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

copy_user_to_xstate() uses __copy_from_user(), which provides a negligible
speedup.  Fortunately, both call sites are at least almost correct.

__fpu__restore_sig() checks access_ok() with xstate_sigframe_size()
length and ptrace regset access uses fpu_user_xstate_size. These should
be valid upper bounds on the length, so, at worst, this would cause
spurious failures and not accesses to kernel memory.

Nonetheless, this is far more fragile than necessary and none of these
callers are in a hotpath.

Use copy_from_user() instead.

Signed-off-by: default avatarAndy Lutomirski <luto@kernel.org>
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
Signed-off-by: default avatarBorislav Petkov <bp@suse.de>
Acked-by: default avatarDave Hansen <dave.hansen@linux.intel.com>
Acked-by: default avatarRik van Riel <riel@surriel.com>
Link: https://lkml.kernel.org/r/20210608144346.140254130@linutronix.de


Reviewed-by: default avatarYunfeng Ye <yeyunfeng@huawei.com>
Reviewed-by: default avatarXie XiuQi <xiexiuqi@huawei.com>
Signed-off-by: default avatarZheng Zengkai <zhengzengkai@huawei.com>
parent eeabdc14
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -1242,7 +1242,7 @@ int copy_user_to_xstate(struct xregs_state *xsave, const void __user *ubuf)
	offset = offsetof(struct xregs_state, header);
	size = sizeof(hdr);

	if (__copy_from_user(&hdr, ubuf + offset, size))
	if (copy_from_user(&hdr, ubuf + offset, size))
		return -EFAULT;

	if (validate_user_xstate_header(&hdr))
@@ -1257,7 +1257,7 @@ int copy_user_to_xstate(struct xregs_state *xsave, const void __user *ubuf)
			offset = xstate_offsets[i];
			size = xstate_sizes[i];

			if (__copy_from_user(dst, ubuf + offset, size))
			if (copy_from_user(dst, ubuf + offset, size))
				return -EFAULT;
		}
	}
@@ -1265,7 +1265,7 @@ int copy_user_to_xstate(struct xregs_state *xsave, const void __user *ubuf)
	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))
		if (copy_from_user(&xsave->i387.mxcsr, ubuf + offset, size))
			return -EFAULT;
	}