aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Biggers <ebiggers@google.com>2017-09-24 06:59:12 -0400
committerIngo Molnar <mingo@kernel.org>2017-09-26 03:43:48 -0400
commit98c0fad9d60e8b2cd47e15b7bee7df343648f5bb (patch)
tree6a0d7c8458c24aebbd592cbfbb7d1068012ee7d6
parent3d703477bcfe8bb57079d97198cf1e342fe1fef9 (diff)
x86/fpu: Use validate_xstate_header() to validate the xstate_header in copy_user_to_xstate()
Tighten the checks in copy_user_to_xstate(). Signed-off-by: Eric Biggers <ebiggers@google.com> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Andy Lutomirski <luto@amacapital.net> Cc: Andy Lutomirski <luto@kernel.org> Cc: Borislav Petkov <bp@alien8.de> Cc: Dave Hansen <dave.hansen@linux.intel.com> Cc: Dmitry Vyukov <dvyukov@google.com> Cc: Eric Biggers <ebiggers3@gmail.com> Cc: Fenghua Yu <fenghua.yu@intel.com> Cc: Kees Cook <keescook@chromium.org> Cc: Kevin Hao <haokexin@gmail.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Michael Halcrow <mhalcrow@google.com> Cc: Oleg Nesterov <oleg@redhat.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Rik van Riel <riel@redhat.com> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Wanpeng Li <wanpeng.li@hotmail.com> Cc: Yu-cheng Yu <yu-cheng.yu@intel.com> Cc: kernel-hardening@lists.openwall.com Link: http://lkml.kernel.org/r/20170924105913.9157-10-mingo@kernel.org Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--arch/x86/kernel/fpu/xstate.c16
1 files changed, 5 insertions, 11 deletions
diff --git a/arch/x86/kernel/fpu/xstate.c b/arch/x86/kernel/fpu/xstate.c
index b6d78b78b5c2..f1d5476c9022 100644
--- a/arch/x86/kernel/fpu/xstate.c
+++ b/arch/x86/kernel/fpu/xstate.c
@@ -1188,16 +1188,15 @@ int copy_kernel_to_xstate(struct xregs_state *xsave, const void *kbuf)
1188} 1188}
1189 1189
1190/* 1190/*
1191 * Convert from a ptrace standard-format user-space buffer to kernel XSAVES format 1191 * Convert from a ptrace or sigreturn standard-format user-space buffer to
1192 * and copy to the target thread. This is called from xstateregs_set() and 1192 * kernel XSAVES format and copy to the target thread. This is called from
1193 * there we check the CPU has XSAVES and a whole standard-sized buffer 1193 * xstateregs_set(), as well as potentially from the sigreturn() and
1194 * exists. 1194 * rt_sigreturn() system calls.
1195 */ 1195 */
1196int copy_user_to_xstate(struct xregs_state *xsave, const void __user *ubuf) 1196int copy_user_to_xstate(struct xregs_state *xsave, const void __user *ubuf)
1197{ 1197{
1198 unsigned int offset, size; 1198 unsigned int offset, size;
1199 int i; 1199 int i;
1200 u64 allowed_features;
1201 struct xstate_header hdr; 1200 struct xstate_header hdr;
1202 1201
1203 offset = offsetof(struct xregs_state, header); 1202 offset = offsetof(struct xregs_state, header);
@@ -1206,12 +1205,7 @@ int copy_user_to_xstate(struct xregs_state *xsave, const void __user *ubuf)
1206 if (__copy_from_user(&hdr, ubuf + offset, size)) 1205 if (__copy_from_user(&hdr, ubuf + offset, size))
1207 return -EFAULT; 1206 return -EFAULT;
1208 1207
1209 /* 1208 if (validate_xstate_header(&hdr))
1210 * Reject if the user sets any disabled or supervisor features:
1211 */
1212 allowed_features = xfeatures_mask & ~XFEATURE_MASK_SUPERVISOR;
1213
1214 if (hdr.xfeatures & ~allowed_features)
1215 return -EINVAL; 1209 return -EINVAL;
1216 1210
1217 for (i = 0; i < XFEATURE_MAX; i++) { 1211 for (i = 0; i < XFEATURE_MAX; i++) {