CVE-2015-2672: Improper Input Validation (CWE-20)
value: The xsave/xrstor implementation in arch/x86/include/asm/xsave.h in the Linux kernel before 3.19.2 creates certain .altinstr_replacement pointers and consequently does not provide any protection against instruction faulting, which allows local users to cause a denial of service (panic) by triggering a fault, as demonstrated by an unaligned memory operand or a non-canonical address memory operand.
CWE description: The product receives input or data, but it does
        not validate or incorrectly validates that the input has the
        properties that are required to process the data safely and
        correctly.
CVSS v3 base score: 5.5
Published: 2016-05-02T10:59Z
Repository: https://github.com/torvalds/linux
Language: C
Files changed: arch/x86/include/asm/xsave.h
Commit date: 2015-03-05 18:20:36 +0100
Commit message: x86/fpu/xsaves: Fix improper uses of __ex_table

Commit:

  f31a9f7c7169 ("x86/xsaves: Use xsaves/xrstors to save and restore xsave area")

introduced alternative instructions for XSAVES/XRSTORS and commit:

  adb9d526e982 ("x86/xsaves: Add xsaves and xrstors support for booting time")

added support for the XSAVES/XRSTORS instructions at boot time.

Unfortunately both failed to properly protect them against faulting:

The 'xstate_fault' macro will use the closest label named '1'
backward and that ends up in the .altinstr_replacement section
rather than in .text. This means that the kernel will never find
in the __ex_table the .text address where this instruction might
fault, leading to serious problems if userspace manages to
trigger the fault.

Signed-off-by: Quentin Casasnovas <quentin.casasnovas@oracle.com>
Signed-off-by: Jamie Iles <jamie.iles@oracle.com>
[ Improved the changelog, fixed some whitespace noise. ]
Acked-by: Borislav Petkov <bp@alien8.de>
Acked-by: Linus Torvalds <torvalds@linux-foundation.org>
Cc: <stable@vger.kernel.org>
Cc: Allan Xavier <mr.a.xavier@gmail.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Fixes: adb9d526e982 ("x86/xsaves: Add xsaves and xrstors support for booting time")
Fixes: f31a9f7c7169 ("x86/xsaves: Use xsaves/xrstors to save and restore xsave area")
Signed-off-by: Ingo Molnar <mingo@kernel.org>

Diff: diff --git a/arch/x86/include/asm/xsave.h b/arch/x86/include/asm/xsave.h
index 5fa9770035dc93..c9a6d68b8d623b 100644
--- a/arch/x86/include/asm/xsave.h
+++ b/arch/x86/include/asm/xsave.h
@@ -80,22 +80,19 @@ static inline int xsave_state_booting(struct xsave_struct *fx, u64 mask)
 	WARN_ON(system_state != SYSTEM_BOOTING);
 
 	if (boot_cpu_has(X86_FEATURE_XSAVES))
 		asm volatile("1:"XSAVES"\n\t"
 			"2:\n\t"
-			: : "D" (fx), "m" (*fx), "a" (lmask), "d" (hmask)
+			     xstate_fault
+			: "D" (fx), "m" (*fx), "a" (lmask), "d" (hmask)
 			:   "memory");
 	else
 		asm volatile("1:"XSAVE"\n\t"
 			"2:\n\t"
-			: : "D" (fx), "m" (*fx), "a" (lmask), "d" (hmask)
+			     xstate_fault
+			: "D" (fx), "m" (*fx), "a" (lmask), "d" (hmask)
 			:   "memory");
-
-	asm volatile(xstate_fault
-		     : "0" (0)
-		     : "memory");
-
 	return err;
 }
 
 /*
  * This function is called only during boot time when x86 caps are not set
@@ -110,22 +107,19 @@ static inline int xrstor_state_booting(struct xsave_struct *fx, u64 mask)
 	WARN_ON(system_state != SYSTEM_BOOTING);
 
 	if (boot_cpu_has(X86_FEATURE_XSAVES))
 		asm volatile("1:"XRSTORS"\n\t"
 			"2:\n\t"
-			: : "D" (fx), "m" (*fx), "a" (lmask), "d" (hmask)
+			     xstate_fault
+			: "D" (fx), "m" (*fx), "a" (lmask), "d" (hmask)
 			:   "memory");
 	else
 		asm volatile("1:"XRSTOR"\n\t"
 			"2:\n\t"
-			: : "D" (fx), "m" (*fx), "a" (lmask), "d" (hmask)
+			     xstate_fault
+			: "D" (fx), "m" (*fx), "a" (lmask), "d" (hmask)
 			:   "memory");
-
-	asm volatile(xstate_fault
-		     : "0" (0)
-		     : "memory");
-
 	return err;
 }
 
 /*
  * Save processor xstate to xsave area.
@@ -147,13 +141,13 @@ static inline int xsave_state(struct xsave_struct *fx, u64 mask)
 	 *
 	 * If none of xsaves and xsaveopt is enabled, use xsave.
 	 */
 	alternative_input_2(
 		"1:"XSAVE,
-		"1:"XSAVEOPT,
+		XSAVEOPT,
 		X86_FEATURE_XSAVEOPT,
-		"1:"XSAVES,
+		XSAVES,
 		X86_FEATURE_XSAVES,
 		[fx] "D" (fx), "a" (lmask), "d" (hmask) :
 		"memory");
 	asm volatile("2:\n\t"
 		     xstate_fault
@@ -176,11 +170,11 @@ static inline int xrstor_state(struct xsave_struct *fx, u64 mask)
 	 * Use xrstors to restore context if it is enabled. xrstors supports
 	 * compacted format of xsave area which is not supported by xrstor.
 	 */
 	alternative_input(
 		"1: " XRSTOR,
-		"1: " XRSTORS,
+		XRSTORS,
 		X86_FEATURE_XSAVES,
 		"D" (fx), "m" (*fx), "a" (lmask), "d" (hmask)
 		: "memory");
 
 	asm volatile("2:\n"

Vulnerable code: 			: : "D" (fx), "m" (*fx), "a" (lmask), "d" (hmask)
			: : "D" (fx), "m" (*fx), "a" (lmask), "d" (hmask)

	asm volatile(xstate_fault
		     : "0" (0)
		     : "memory");

			: : "D" (fx), "m" (*fx), "a" (lmask), "d" (hmask)
			: : "D" (fx), "m" (*fx), "a" (lmask), "d" (hmask)

	asm volatile(xstate_fault
		     : "0" (0)
		     : "memory");

		"1:"XSAVEOPT,
		"1:"XSAVES,
		"1: " XRSTORS,
Fixed code: 			     xstate_fault
			: "D" (fx), "m" (*fx), "a" (lmask), "d" (hmask)
			     xstate_fault
			: "D" (fx), "m" (*fx), "a" (lmask), "d" (hmask)
			     xstate_fault
			: "D" (fx), "m" (*fx), "a" (lmask), "d" (hmask)
			     xstate_fault
			: "D" (fx), "m" (*fx), "a" (lmask), "d" (hmask)
		XSAVEOPT,
		XSAVES,
		XRSTORS,