All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] x86/umip: Add emulation for 64-bit processes
@ 2019-09-05 23:22 Brendan Shanks
  2019-09-07 21:26 ` Ricardo Neri
                   ` (2 more replies)
  0 siblings, 3 replies; 10+ messages in thread
From: Brendan Shanks @ 2019-09-05 23:22 UTC (permalink / raw)
  To: linux-kernel
  Cc: Ricardo Neri, Brendan Shanks, Thomas Gleixner, Ingo Molnar,
	Borislav Petkov, H. Peter Anvin, x86, Eric W. Biederman

Add emulation of the sgdt, sidt, and smsw instructions for 64-bit
processes.

Wine users have encountered a number of 64-bit Windows games that use
these instructions (particularly sgdt), and were crashing when run on
UMIP-enabled systems.

Originally-by: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
Signed-off-by: Brendan Shanks <bshanks@codeweavers.com>
---
 arch/x86/kernel/umip.c | 55 +++++++++++++++++++++++++-----------------
 1 file changed, 33 insertions(+), 22 deletions(-)

diff --git a/arch/x86/kernel/umip.c b/arch/x86/kernel/umip.c
index 5b345add550f..1812e95d2f55 100644
--- a/arch/x86/kernel/umip.c
+++ b/arch/x86/kernel/umip.c
@@ -51,9 +51,7 @@
  * The instruction smsw is emulated to return the value that the register CR0
  * has at boot time as set in the head_32.
  *
- * Also, emulation is provided only for 32-bit processes; 64-bit processes
- * that attempt to use the instructions that UMIP protects will receive the
- * SIGSEGV signal issued as a consequence of the general protection fault.
+ * Emulation is provided for both 32-bit and 64-bit processes.
  *
  * Care is taken to appropriately emulate the results when segmentation is
  * used. That is, rather than relying on USER_DS and USER_CS, the function
@@ -63,17 +61,18 @@
  * application uses a local descriptor table.
  */
 
-#define UMIP_DUMMY_GDT_BASE 0xfffe0000
-#define UMIP_DUMMY_IDT_BASE 0xffff0000
+#define UMIP_DUMMY_GDT_BASE 0xfffffffffffe0000ULL
+#define UMIP_DUMMY_IDT_BASE 0xffffffffffff0000ULL
 
 /*
  * The SGDT and SIDT instructions store the contents of the global descriptor
  * table and interrupt table registers, respectively. The destination is a
  * memory operand of X+2 bytes. X bytes are used to store the base address of
- * the table and 2 bytes are used to store the limit. In 32-bit processes, the
- * only processes for which emulation is provided, X has a value of 4.
+ * the table and 2 bytes are used to store the limit. In 32-bit processes X
+ * has a value of 4, in 64-bit processes X has a value of 8.
  */
-#define UMIP_GDT_IDT_BASE_SIZE 4
+#define UMIP_GDT_IDT_BASE_SIZE_64BIT 8
+#define UMIP_GDT_IDT_BASE_SIZE_32BIT 4
 #define UMIP_GDT_IDT_LIMIT_SIZE 2
 
 #define	UMIP_INST_SGDT	0	/* 0F 01 /0 */
@@ -189,6 +188,7 @@ static int identify_insn(struct insn *insn)
  * @umip_inst:	A constant indicating the instruction to emulate
  * @data:	Buffer into which the dummy result is stored
  * @data_size:	Size of the emulated result
+ * @x86_64:     true if process is 64-bit, false otherwise
  *
  * Emulate an instruction protected by UMIP and provide a dummy result. The
  * result of the emulation is saved in @data. The size of the results depends
@@ -202,11 +202,8 @@ static int identify_insn(struct insn *insn)
  * 0 on success, -EINVAL on error while emulating.
  */
 static int emulate_umip_insn(struct insn *insn, int umip_inst,
-			     unsigned char *data, int *data_size)
+			     unsigned char *data, int *data_size, bool x86_64)
 {
-	unsigned long dummy_base_addr, dummy_value;
-	unsigned short dummy_limit = 0;
-
 	if (!data || !data_size || !insn)
 		return -EINVAL;
 	/*
@@ -219,6 +216,9 @@ static int emulate_umip_insn(struct insn *insn, int umip_inst,
 	 * is always returned irrespective of the operand size.
 	 */
 	if (umip_inst == UMIP_INST_SGDT || umip_inst == UMIP_INST_SIDT) {
+		u64 dummy_base_addr;
+		u16 dummy_limit = 0;
+
 		/* SGDT and SIDT do not use registers operands. */
 		if (X86_MODRM_MOD(insn->modrm.value) == 3)
 			return -EINVAL;
@@ -228,13 +228,24 @@ static int emulate_umip_insn(struct insn *insn, int umip_inst,
 		else
 			dummy_base_addr = UMIP_DUMMY_IDT_BASE;
 
-		*data_size = UMIP_GDT_IDT_LIMIT_SIZE + UMIP_GDT_IDT_BASE_SIZE;
+		/*
+		 * 64-bit processes use the entire dummy base address.
+		 * 32-bit processes use the lower 32 bits of the base address.
+		 * dummy_base_addr is always 64 bits, but we memcpy the correct
+		 * number of bytes from it to the destination.
+		 */
+		if (x86_64)
+			*data_size = UMIP_GDT_IDT_BASE_SIZE_64BIT;
+		else
+			*data_size = UMIP_GDT_IDT_BASE_SIZE_32BIT;
+
+		memcpy(data + 2, &dummy_base_addr, *data_size);
 
-		memcpy(data + 2, &dummy_base_addr, UMIP_GDT_IDT_BASE_SIZE);
+		*data_size += UMIP_GDT_IDT_LIMIT_SIZE;
 		memcpy(data, &dummy_limit, UMIP_GDT_IDT_LIMIT_SIZE);
 
 	} else if (umip_inst == UMIP_INST_SMSW) {
-		dummy_value = CR0_STATE;
+		unsigned long dummy_value = CR0_STATE;
 
 		/*
 		 * Even though the CR0 register has 4 bytes, the number
@@ -291,10 +302,9 @@ static void force_sig_info_umip_fault(void __user *addr, struct pt_regs *regs)
  * @regs:	Registers as saved when entering the #GP handler
  *
  * The instructions sgdt, sidt, str, smsw, sldt cause a general protection
- * fault if executed with CPL > 0 (i.e., from user space). If the offending
- * user-space process is not in long mode, this function fixes the exception
- * up and provides dummy results for sgdt, sidt and smsw; str and sldt are not
- * fixed up. Also long mode user-space processes are not fixed up.
+ * fault if executed with CPL > 0 (i.e., from user space). This function fixes
+ * the exception up and provides dummy results for sgdt, sidt and smsw; str
+ * and sldt are not fixed up.
  *
  * If operands are memory addresses, results are copied to user-space memory as
  * indicated by the instruction pointed by eIP using the registers indicated in
@@ -373,13 +383,14 @@ bool fixup_umip_exception(struct pt_regs *regs)
 	umip_pr_warning(regs, "%s instruction cannot be used by applications.\n",
 			umip_insns[umip_inst]);
 
-	/* Do not emulate SLDT, STR or user long mode processes. */
-	if (umip_inst == UMIP_INST_STR || umip_inst == UMIP_INST_SLDT || user_64bit_mode(regs))
+	/* Do not emulate SLDT or STR. */
+	if (umip_inst == UMIP_INST_STR || umip_inst == UMIP_INST_SLDT)
 		return false;
 
 	umip_pr_warning(regs, "For now, expensive software emulation returns the result.\n");
 
-	if (emulate_umip_insn(&insn, umip_inst, dummy_data, &dummy_data_size))
+	if (emulate_umip_insn(&insn, umip_inst, dummy_data, &dummy_data_size,
+			      user_64bit_mode(regs)))
 		return false;
 
 	/*
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH] x86/umip: Add emulation for 64-bit processes
  2019-09-05 23:22 [PATCH] x86/umip: Add emulation for 64-bit processes Brendan Shanks
@ 2019-09-07 21:26 ` Ricardo Neri
  2019-09-08  7:22   ` Borislav Petkov
  2019-09-09 22:34   ` Brendan Shanks
  2019-09-09 12:04 ` hpa
  2019-09-10  6:41 ` [tip: x86/asm] x86/umip: Add emulation (spoofing) for UMIP covered instructions in 64-bit processes as well tip-bot2 for Brendan Shanks
  2 siblings, 2 replies; 10+ messages in thread
From: Ricardo Neri @ 2019-09-07 21:26 UTC (permalink / raw)
  To: Brendan Shanks
  Cc: linux-kernel, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	H. Peter Anvin, x86, Eric W. Biederman

On Thu, Sep 05, 2019 at 04:22:21PM -0700, Brendan Shanks wrote:
> Add emulation of the sgdt, sidt, and smsw instructions for 64-bit
> processes.
> 
> Wine users have encountered a number of 64-bit Windows games that use
> these instructions (particularly sgdt), and were crashing when run on
> UMIP-enabled systems.

Emulation support for 64-bit processes was not initially included
because no use cases had been identified. Brendan has found one.

Here is the relevant e-mail thread: https://lkml.org/lkml/2017/1/26/12

FWIW,

Reviewed-by: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>

Only one minor comment below...

> 
> Originally-by: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
> Signed-off-by: Brendan Shanks <bshanks@codeweavers.com>
> ---
>  arch/x86/kernel/umip.c | 55 +++++++++++++++++++++++++-----------------
>  1 file changed, 33 insertions(+), 22 deletions(-)
> 
> diff --git a/arch/x86/kernel/umip.c b/arch/x86/kernel/umip.c
> index 5b345add550f..1812e95d2f55 100644
> --- a/arch/x86/kernel/umip.c
> +++ b/arch/x86/kernel/umip.c
> @@ -51,9 +51,7 @@
>   * The instruction smsw is emulated to return the value that the register CR0
>   * has at boot time as set in the head_32.
>   *
> - * Also, emulation is provided only for 32-bit processes; 64-bit processes
> - * that attempt to use the instructions that UMIP protects will receive the
> - * SIGSEGV signal issued as a consequence of the general protection fault.
> + * Emulation is provided for both 32-bit and 64-bit processes.
>   *
>   * Care is taken to appropriately emulate the results when segmentation is
>   * used. That is, rather than relying on USER_DS and USER_CS, the function
> @@ -63,17 +61,18 @@
>   * application uses a local descriptor table.
>   */
>  
> -#define UMIP_DUMMY_GDT_BASE 0xfffe0000
> -#define UMIP_DUMMY_IDT_BASE 0xffff0000
> +#define UMIP_DUMMY_GDT_BASE 0xfffffffffffe0000ULL
> +#define UMIP_DUMMY_IDT_BASE 0xffffffffffff0000ULL
>  
>  /*
>   * The SGDT and SIDT instructions store the contents of the global descriptor
>   * table and interrupt table registers, respectively. The destination is a
>   * memory operand of X+2 bytes. X bytes are used to store the base address of
> - * the table and 2 bytes are used to store the limit. In 32-bit processes, the
> - * only processes for which emulation is provided, X has a value of 4.
> + * the table and 2 bytes are used to store the limit. In 32-bit processes X
> + * has a value of 4, in 64-bit processes X has a value of 8.
>   */
> -#define UMIP_GDT_IDT_BASE_SIZE 4
> +#define UMIP_GDT_IDT_BASE_SIZE_64BIT 8
> +#define UMIP_GDT_IDT_BASE_SIZE_32BIT 4
>  #define UMIP_GDT_IDT_LIMIT_SIZE 2
>  
>  #define	UMIP_INST_SGDT	0	/* 0F 01 /0 */
> @@ -189,6 +188,7 @@ static int identify_insn(struct insn *insn)
>   * @umip_inst:	A constant indicating the instruction to emulate
>   * @data:	Buffer into which the dummy result is stored
>   * @data_size:	Size of the emulated result
> + * @x86_64:     true if process is 64-bit, false otherwise
>   *
>   * Emulate an instruction protected by UMIP and provide a dummy result. The
>   * result of the emulation is saved in @data. The size of the results depends
> @@ -202,11 +202,8 @@ static int identify_insn(struct insn *insn)
>   * 0 on success, -EINVAL on error while emulating.
>   */
>  static int emulate_umip_insn(struct insn *insn, int umip_inst,
> -			     unsigned char *data, int *data_size)
> +			     unsigned char *data, int *data_size, bool x86_64)
>  {
> -	unsigned long dummy_base_addr, dummy_value;
> -	unsigned short dummy_limit = 0;
> -
>  	if (!data || !data_size || !insn)
>  		return -EINVAL;
>  	/*
> @@ -219,6 +216,9 @@ static int emulate_umip_insn(struct insn *insn, int umip_inst,
>  	 * is always returned irrespective of the operand size.
>  	 */
>  	if (umip_inst == UMIP_INST_SGDT || umip_inst == UMIP_INST_SIDT) {
> +		u64 dummy_base_addr;
> +		u16 dummy_limit = 0;
> +
>  		/* SGDT and SIDT do not use registers operands. */
>  		if (X86_MODRM_MOD(insn->modrm.value) == 3)
>  			return -EINVAL;
> @@ -228,13 +228,24 @@ static int emulate_umip_insn(struct insn *insn, int umip_inst,
>  		else
>  			dummy_base_addr = UMIP_DUMMY_IDT_BASE;
>  
> -		*data_size = UMIP_GDT_IDT_LIMIT_SIZE + UMIP_GDT_IDT_BASE_SIZE;

Maybe a blank line here?

Thanks and BR,
Ricardo

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] x86/umip: Add emulation for 64-bit processes
  2019-09-07 21:26 ` Ricardo Neri
@ 2019-09-08  7:22   ` Borislav Petkov
  2019-09-09 11:56     ` hpa
  2019-09-09 22:34   ` Brendan Shanks
  1 sibling, 1 reply; 10+ messages in thread
From: Borislav Petkov @ 2019-09-08  7:22 UTC (permalink / raw)
  To: Ricardo Neri
  Cc: Brendan Shanks, linux-kernel, Thomas Gleixner, Ingo Molnar,
	H. Peter Anvin, x86, Eric W. Biederman

On Sat, Sep 07, 2019 at 02:26:10PM -0700, Ricardo Neri wrote:
> > Wine users have encountered a number of 64-bit Windows games that use
> > these instructions (particularly sgdt), and were crashing when run on
> > UMIP-enabled systems.
> 
> Emulation support for 64-bit processes was not initially included
> because no use cases had been identified.

AFAIR, we said at the time that 64-bit doesn't need it because this is
legacy software only and 64-bit will get fixed properly not to use those
insns. I can probably guess how that went ...

-- 
Regards/Gruss,
    Boris.

https://people.kernel.org/tglx/notes-about-netiquette

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] x86/umip: Add emulation for 64-bit processes
  2019-09-08  7:22   ` Borislav Petkov
@ 2019-09-09 11:56     ` hpa
  0 siblings, 0 replies; 10+ messages in thread
From: hpa @ 2019-09-09 11:56 UTC (permalink / raw)
  To: Borislav Petkov, Ricardo Neri
  Cc: Brendan Shanks, linux-kernel, Thomas Gleixner, Ingo Molnar, x86,
	Eric W. Biederman

On September 8, 2019 8:22:48 AM GMT+01:00, Borislav Petkov <bp@alien8.de> wrote:
>On Sat, Sep 07, 2019 at 02:26:10PM -0700, Ricardo Neri wrote:
>> > Wine users have encountered a number of 64-bit Windows games that
>use
>> > these instructions (particularly sgdt), and were crashing when run
>on
>> > UMIP-enabled systems.
>> 
>> Emulation support for 64-bit processes was not initially included
>> because no use cases had been identified.
>
>AFAIR, we said at the time that 64-bit doesn't need it because this is
>legacy software only and 64-bit will get fixed properly not to use
>those
>insns. I can probably guess how that went ...

I don't think Windows games was something we considered. However, needing to simulate these instructions is not a huge surprise. The important thing is that by simulating them, we can plug the leak of some very high value kernel information – mainly the GDT, IDT and TSS addresses.
-- 
Sent from my Android device with K-9 Mail. Please excuse my brevity.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] x86/umip: Add emulation for 64-bit processes
  2019-09-05 23:22 [PATCH] x86/umip: Add emulation for 64-bit processes Brendan Shanks
  2019-09-07 21:26 ` Ricardo Neri
@ 2019-09-09 12:04 ` hpa
  2019-09-10  6:28   ` Ingo Molnar
  2019-09-10  6:41 ` [tip: x86/asm] x86/umip: Add emulation (spoofing) for UMIP covered instructions in 64-bit processes as well tip-bot2 for Brendan Shanks
  2 siblings, 1 reply; 10+ messages in thread
From: hpa @ 2019-09-09 12:04 UTC (permalink / raw)
  To: Brendan Shanks, linux-kernel
  Cc: Ricardo Neri, Thomas Gleixner, Ingo Molnar, Borislav Petkov, x86,
	Eric W. Biederman

On September 6, 2019 12:22:21 AM GMT+01:00, Brendan Shanks <bshanks@codeweavers.com> wrote:
>Add emulation of the sgdt, sidt, and smsw instructions for 64-bit
>processes.
>
>Wine users have encountered a number of 64-bit Windows games that use
>these instructions (particularly sgdt), and were crashing when run on
>UMIP-enabled systems.
>
>Originally-by: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
>Signed-off-by: Brendan Shanks <bshanks@codeweavers.com>
>---
> arch/x86/kernel/umip.c | 55 +++++++++++++++++++++++++-----------------
> 1 file changed, 33 insertions(+), 22 deletions(-)
>
>diff --git a/arch/x86/kernel/umip.c b/arch/x86/kernel/umip.c
>index 5b345add550f..1812e95d2f55 100644
>--- a/arch/x86/kernel/umip.c
>+++ b/arch/x86/kernel/umip.c
>@@ -51,9 +51,7 @@
>* The instruction smsw is emulated to return the value that the
>register CR0
>  * has at boot time as set in the head_32.
>  *
>- * Also, emulation is provided only for 32-bit processes; 64-bit
>processes
>- * that attempt to use the instructions that UMIP protects will
>receive the
>- * SIGSEGV signal issued as a consequence of the general protection
>fault.
>+ * Emulation is provided for both 32-bit and 64-bit processes.
>  *
>* Care is taken to appropriately emulate the results when segmentation
>is
>* used. That is, rather than relying on USER_DS and USER_CS, the
>function
>@@ -63,17 +61,18 @@
>  * application uses a local descriptor table.
>  */
> 
>-#define UMIP_DUMMY_GDT_BASE 0xfffe0000
>-#define UMIP_DUMMY_IDT_BASE 0xffff0000
>+#define UMIP_DUMMY_GDT_BASE 0xfffffffffffe0000ULL
>+#define UMIP_DUMMY_IDT_BASE 0xffffffffffff0000ULL
> 
> /*
>* The SGDT and SIDT instructions store the contents of the global
>descriptor
>* table and interrupt table registers, respectively. The destination is
>a
>* memory operand of X+2 bytes. X bytes are used to store the base
>address of
>- * the table and 2 bytes are used to store the limit. In 32-bit
>processes, the
>- * only processes for which emulation is provided, X has a value of 4.
>+ * the table and 2 bytes are used to store the limit. In 32-bit
>processes X
>+ * has a value of 4, in 64-bit processes X has a value of 8.
>  */
>-#define UMIP_GDT_IDT_BASE_SIZE 4
>+#define UMIP_GDT_IDT_BASE_SIZE_64BIT 8
>+#define UMIP_GDT_IDT_BASE_SIZE_32BIT 4
> #define UMIP_GDT_IDT_LIMIT_SIZE 2
> 
> #define	UMIP_INST_SGDT	0	/* 0F 01 /0 */
>@@ -189,6 +188,7 @@ static int identify_insn(struct insn *insn)
>  * @umip_inst:	A constant indicating the instruction to emulate
>  * @data:	Buffer into which the dummy result is stored
>  * @data_size:	Size of the emulated result
>+ * @x86_64:     true if process is 64-bit, false otherwise
>  *
>* Emulate an instruction protected by UMIP and provide a dummy result.
>The
>* result of the emulation is saved in @data. The size of the results
>depends
>@@ -202,11 +202,8 @@ static int identify_insn(struct insn *insn)
>  * 0 on success, -EINVAL on error while emulating.
>  */
> static int emulate_umip_insn(struct insn *insn, int umip_inst,
>-			     unsigned char *data, int *data_size)
>+			     unsigned char *data, int *data_size, bool x86_64)
> {
>-	unsigned long dummy_base_addr, dummy_value;
>-	unsigned short dummy_limit = 0;
>-
> 	if (!data || !data_size || !insn)
> 		return -EINVAL;
> 	/*
>@@ -219,6 +216,9 @@ static int emulate_umip_insn(struct insn *insn, int
>umip_inst,
> 	 * is always returned irrespective of the operand size.
> 	 */
> 	if (umip_inst == UMIP_INST_SGDT || umip_inst == UMIP_INST_SIDT) {
>+		u64 dummy_base_addr;
>+		u16 dummy_limit = 0;
>+
> 		/* SGDT and SIDT do not use registers operands. */
> 		if (X86_MODRM_MOD(insn->modrm.value) == 3)
> 			return -EINVAL;
>@@ -228,13 +228,24 @@ static int emulate_umip_insn(struct insn *insn,
>int umip_inst,
> 		else
> 			dummy_base_addr = UMIP_DUMMY_IDT_BASE;
> 
>-		*data_size = UMIP_GDT_IDT_LIMIT_SIZE + UMIP_GDT_IDT_BASE_SIZE;
>+		/*
>+		 * 64-bit processes use the entire dummy base address.
>+		 * 32-bit processes use the lower 32 bits of the base address.
>+		 * dummy_base_addr is always 64 bits, but we memcpy the correct
>+		 * number of bytes from it to the destination.
>+		 */
>+		if (x86_64)
>+			*data_size = UMIP_GDT_IDT_BASE_SIZE_64BIT;
>+		else
>+			*data_size = UMIP_GDT_IDT_BASE_SIZE_32BIT;
>+
>+		memcpy(data + 2, &dummy_base_addr, *data_size);
> 
>-		memcpy(data + 2, &dummy_base_addr, UMIP_GDT_IDT_BASE_SIZE);
>+		*data_size += UMIP_GDT_IDT_LIMIT_SIZE;
> 		memcpy(data, &dummy_limit, UMIP_GDT_IDT_LIMIT_SIZE);
> 
> 	} else if (umip_inst == UMIP_INST_SMSW) {
>-		dummy_value = CR0_STATE;
>+		unsigned long dummy_value = CR0_STATE;
> 
> 		/*
> 		 * Even though the CR0 register has 4 bytes, the number
>@@ -291,10 +302,9 @@ static void force_sig_info_umip_fault(void __user
>*addr, struct pt_regs *regs)
>  * @regs:	Registers as saved when entering the #GP handler
>  *
>* The instructions sgdt, sidt, str, smsw, sldt cause a general
>protection
>- * fault if executed with CPL > 0 (i.e., from user space). If the
>offending
>- * user-space process is not in long mode, this function fixes the
>exception
>- * up and provides dummy results for sgdt, sidt and smsw; str and sldt
>are not
>- * fixed up. Also long mode user-space processes are not fixed up.
>+ * fault if executed with CPL > 0 (i.e., from user space). This
>function fixes
>+ * the exception up and provides dummy results for sgdt, sidt and
>smsw; str
>+ * and sldt are not fixed up.
>  *
>* If operands are memory addresses, results are copied to user-space
>memory as
>* indicated by the instruction pointed by eIP using the registers
>indicated in
>@@ -373,13 +383,14 @@ bool fixup_umip_exception(struct pt_regs *regs)
>	umip_pr_warning(regs, "%s instruction cannot be used by
>applications.\n",
> 			umip_insns[umip_inst]);
> 
>-	/* Do not emulate SLDT, STR or user long mode processes. */
>-	if (umip_inst == UMIP_INST_STR || umip_inst == UMIP_INST_SLDT ||
>user_64bit_mode(regs))
>+	/* Do not emulate SLDT or STR. */
>+	if (umip_inst == UMIP_INST_STR || umip_inst == UMIP_INST_SLDT)
> 		return false;
> 
>	umip_pr_warning(regs, "For now, expensive software emulation returns
>the result.\n");
> 
>-	if (emulate_umip_insn(&insn, umip_inst, dummy_data,
>&dummy_data_size))
>+	if (emulate_umip_insn(&insn, umip_inst, dummy_data, &dummy_data_size,
>+			      user_64bit_mode(regs)))
> 		return false;
> 
> 	/*

I would strongly suggest that we change the term "emulation" to "spoofing" for these instructions. We need to explain that we do *not* execute these instructions the was the CPU would have, and unlike the native instructions do not leak kernel information.
-- 
Sent from my Android device with K-9 Mail. Please excuse my brevity.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] x86/umip: Add emulation for 64-bit processes
  2019-09-07 21:26 ` Ricardo Neri
  2019-09-08  7:22   ` Borislav Petkov
@ 2019-09-09 22:34   ` Brendan Shanks
  1 sibling, 0 replies; 10+ messages in thread
From: Brendan Shanks @ 2019-09-09 22:34 UTC (permalink / raw)
  To: Ricardo Neri
  Cc: linux-kernel, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	H. Peter Anvin, x86, Eric W. Biederman


> On Sep 7, 2019, at 2:26 PM, Ricardo Neri <ricardo.neri-calderon@linux.intel.com> wrote:
> 
> On Thu, Sep 05, 2019 at 04:22:21PM -0700, Brendan Shanks wrote:
>> 
>> 	if (umip_inst == UMIP_INST_SGDT || umip_inst == UMIP_INST_SIDT) {
>> +		u64 dummy_base_addr;
>> +		u16 dummy_limit = 0;
>> +
>> 		/* SGDT and SIDT do not use registers operands. */
>> 		if (X86_MODRM_MOD(insn->modrm.value) == 3)
>> 			return -EINVAL;
>> @@ -228,13 +228,24 @@ static int emulate_umip_insn(struct insn *insn, int umip_inst,
>> 		else
>> 			dummy_base_addr = UMIP_DUMMY_IDT_BASE;
>> 
>> -		*data_size = UMIP_GDT_IDT_LIMIT_SIZE + UMIP_GDT_IDT_BASE_SIZE;
> 
> Maybe a blank line here?

Adding a blank line in place of the removed line? I’m not sure I see the need for it, there’s already a blank line above, and it's followed by the block comment.

Brendan

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] x86/umip: Add emulation for 64-bit processes
  2019-09-09 12:04 ` hpa
@ 2019-09-10  6:28   ` Ingo Molnar
  2019-09-10  6:32     ` hpa
  0 siblings, 1 reply; 10+ messages in thread
From: Ingo Molnar @ 2019-09-10  6:28 UTC (permalink / raw)
  To: hpa
  Cc: Brendan Shanks, linux-kernel, Ricardo Neri, Thomas Gleixner,
	Ingo Molnar, Borislav Petkov, x86, Eric W. Biederman


* hpa@zytor.com <hpa@zytor.com> wrote:

> I would strongly suggest that we change the term "emulation" to 
> "spoofing" for these instructions. We need to explain that we do *not* 
> execute these instructions the was the CPU would have, and unlike the 
> native instructions do not leak kernel information.

Ok, I've edited the patch to add the 'spoofing' wording where 
appropriate, and I also made minor fixes such as consistently 
capitalizing instruction names.

Can I also add your Reviewed-by tag?

So the patch should show up in tip:x86/asm today-ish, and barring any 
complications is v5.4 material.

Thanks,

	Ingo

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] x86/umip: Add emulation for 64-bit processes
  2019-09-10  6:28   ` Ingo Molnar
@ 2019-09-10  6:32     ` hpa
  2019-09-10  6:37       ` [PATCH v2] " Ingo Molnar
  0 siblings, 1 reply; 10+ messages in thread
From: hpa @ 2019-09-10  6:32 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Brendan Shanks, linux-kernel, Ricardo Neri, Thomas Gleixner,
	Ingo Molnar, Borislav Petkov, x86, Eric W. Biederman

On September 10, 2019 7:28:28 AM GMT+01:00, Ingo Molnar <mingo@kernel.org> wrote:
>
>* hpa@zytor.com <hpa@zytor.com> wrote:
>
>> I would strongly suggest that we change the term "emulation" to 
>> "spoofing" for these instructions. We need to explain that we do
>*not* 
>> execute these instructions the was the CPU would have, and unlike the
>
>> native instructions do not leak kernel information.
>
>Ok, I've edited the patch to add the 'spoofing' wording where 
>appropriate, and I also made minor fixes such as consistently 
>capitalizing instruction names.
>
>Can I also add your Reviewed-by tag?
>
>So the patch should show up in tip:x86/asm today-ish, and barring any 
>complications is v5.4 material.
>
>Thanks,
>
>	Ingo

Yes, please do.

Reviewed-by: H. Peter Anvin (Intel) <hpa@zytor.com>
-- 
Sent from my Android device with K-9 Mail. Please excuse my brevity.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH v2] x86/umip: Add emulation for 64-bit processes
  2019-09-10  6:32     ` hpa
@ 2019-09-10  6:37       ` Ingo Molnar
  0 siblings, 0 replies; 10+ messages in thread
From: Ingo Molnar @ 2019-09-10  6:37 UTC (permalink / raw)
  To: hpa
  Cc: Brendan Shanks, linux-kernel, Ricardo Neri, Thomas Gleixner,
	Ingo Molnar, Borislav Petkov, x86, Eric W. Biederman


* hpa@zytor.com <hpa@zytor.com> wrote:

> On September 10, 2019 7:28:28 AM GMT+01:00, Ingo Molnar <mingo@kernel.org> wrote:
> >
> >* hpa@zytor.com <hpa@zytor.com> wrote:
> >
> >> I would strongly suggest that we change the term "emulation" to 
> >> "spoofing" for these instructions. We need to explain that we do
> >*not* 
> >> execute these instructions the was the CPU would have, and unlike the
> >
> >> native instructions do not leak kernel information.
> >
> >Ok, I've edited the patch to add the 'spoofing' wording where 
> >appropriate, and I also made minor fixes such as consistently 
> >capitalizing instruction names.
> >
> >Can I also add your Reviewed-by tag?
> >
> >So the patch should show up in tip:x86/asm today-ish, and barring any 
> >complications is v5.4 material.
> >
> >Thanks,
> >
> >	Ingo
> 
> Yes, please do.
> 
> Reviewed-by: H. Peter Anvin (Intel) <hpa@zytor.com>

Thanks!

I've attached the updated version of the patch I'm testing.

	Ingo

==================>
From e86c2c8b9380440bbe761b8e2f63ab6b04a45ac2 Mon Sep 17 00:00:00 2001
From: Brendan Shanks <bshanks@codeweavers.com>
Date: Thu, 5 Sep 2019 16:22:21 -0700
Subject: [PATCH] x86/umip: Add emulation (spoofing) for UMIP covered instructions in 64-bit processes as well

Add emulation (spoofing) of the SGDT, SIDT, and SMSW instructions for 64-bit
processes.

Wine users have encountered a number of 64-bit Windows games that use
these instructions (particularly SGDT), and were crashing when run on
UMIP-enabled systems.

Originally-by: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
Signed-off-by: Brendan Shanks <bshanks@codeweavers.com>
Reviewed-by: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
Reviewed-by: H. Peter Anvin (Intel) <hpa@zytor.com>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: Eric W. Biederman <ebiederm@xmission.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/20190905232222.14900-1-bshanks@codeweavers.com
[ Minor edits: capitalization, added 'spoofing' wording. ]
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
 arch/x86/kernel/umip.c | 65 +++++++++++++++++++++++++++++---------------------
 1 file changed, 38 insertions(+), 27 deletions(-)

diff --git a/arch/x86/kernel/umip.c b/arch/x86/kernel/umip.c
index 5b345add550f..548fefed71ee 100644
--- a/arch/x86/kernel/umip.c
+++ b/arch/x86/kernel/umip.c
@@ -19,7 +19,7 @@
 /** DOC: Emulation for User-Mode Instruction Prevention (UMIP)
  *
  * The feature User-Mode Instruction Prevention present in recent Intel
- * processor prevents a group of instructions (sgdt, sidt, sldt, smsw, and str)
+ * processor prevents a group of instructions (SGDT, SIDT, SLDT, SMSW and STR)
  * from being executed with CPL > 0. Otherwise, a general protection fault is
  * issued.
  *
@@ -36,8 +36,8 @@
  * DOSEMU2) rely on this subset of instructions to function.
  *
  * The instructions protected by UMIP can be split in two groups. Those which
- * return a kernel memory address (sgdt and sidt) and those which return a
- * value (sldt, str and smsw).
+ * return a kernel memory address (SGDT and SIDT) and those which return a
+ * value (SLDT, STR and SMSW).
  *
  * For the instructions that return a kernel memory address, applications
  * such as WineHQ rely on the result being located in the kernel memory space,
@@ -45,15 +45,13 @@
  * value that, lies close to the top of the kernel memory. The limit for the GDT
  * and the IDT are set to zero.
  *
- * Given that sldt and str are not commonly used in programs that run on WineHQ
+ * Given that SLDT and STR are not commonly used in programs that run on WineHQ
  * or DOSEMU2, they are not emulated.
  *
  * The instruction smsw is emulated to return the value that the register CR0
  * has at boot time as set in the head_32.
  *
- * Also, emulation is provided only for 32-bit processes; 64-bit processes
- * that attempt to use the instructions that UMIP protects will receive the
- * SIGSEGV signal issued as a consequence of the general protection fault.
+ * Emulation is provided for both 32-bit and 64-bit processes.
  *
  * Care is taken to appropriately emulate the results when segmentation is
  * used. That is, rather than relying on USER_DS and USER_CS, the function
@@ -63,17 +61,18 @@
  * application uses a local descriptor table.
  */
 
-#define UMIP_DUMMY_GDT_BASE 0xfffe0000
-#define UMIP_DUMMY_IDT_BASE 0xffff0000
+#define UMIP_DUMMY_GDT_BASE 0xfffffffffffe0000ULL
+#define UMIP_DUMMY_IDT_BASE 0xffffffffffff0000ULL
 
 /*
  * The SGDT and SIDT instructions store the contents of the global descriptor
  * table and interrupt table registers, respectively. The destination is a
  * memory operand of X+2 bytes. X bytes are used to store the base address of
- * the table and 2 bytes are used to store the limit. In 32-bit processes, the
- * only processes for which emulation is provided, X has a value of 4.
+ * the table and 2 bytes are used to store the limit. In 32-bit processes X
+ * has a value of 4, in 64-bit processes X has a value of 8.
  */
-#define UMIP_GDT_IDT_BASE_SIZE 4
+#define UMIP_GDT_IDT_BASE_SIZE_64BIT 8
+#define UMIP_GDT_IDT_BASE_SIZE_32BIT 4
 #define UMIP_GDT_IDT_LIMIT_SIZE 2
 
 #define	UMIP_INST_SGDT	0	/* 0F 01 /0 */
@@ -189,6 +188,7 @@ static int identify_insn(struct insn *insn)
  * @umip_inst:	A constant indicating the instruction to emulate
  * @data:	Buffer into which the dummy result is stored
  * @data_size:	Size of the emulated result
+ * @x86_64:	true if process is 64-bit, false otherwise
  *
  * Emulate an instruction protected by UMIP and provide a dummy result. The
  * result of the emulation is saved in @data. The size of the results depends
@@ -202,11 +202,8 @@ static int identify_insn(struct insn *insn)
  * 0 on success, -EINVAL on error while emulating.
  */
 static int emulate_umip_insn(struct insn *insn, int umip_inst,
-			     unsigned char *data, int *data_size)
+			     unsigned char *data, int *data_size, bool x86_64)
 {
-	unsigned long dummy_base_addr, dummy_value;
-	unsigned short dummy_limit = 0;
-
 	if (!data || !data_size || !insn)
 		return -EINVAL;
 	/*
@@ -219,6 +216,9 @@ static int emulate_umip_insn(struct insn *insn, int umip_inst,
 	 * is always returned irrespective of the operand size.
 	 */
 	if (umip_inst == UMIP_INST_SGDT || umip_inst == UMIP_INST_SIDT) {
+		u64 dummy_base_addr;
+		u16 dummy_limit = 0;
+
 		/* SGDT and SIDT do not use registers operands. */
 		if (X86_MODRM_MOD(insn->modrm.value) == 3)
 			return -EINVAL;
@@ -228,13 +228,24 @@ static int emulate_umip_insn(struct insn *insn, int umip_inst,
 		else
 			dummy_base_addr = UMIP_DUMMY_IDT_BASE;
 
-		*data_size = UMIP_GDT_IDT_LIMIT_SIZE + UMIP_GDT_IDT_BASE_SIZE;
+		/*
+		 * 64-bit processes use the entire dummy base address.
+		 * 32-bit processes use the lower 32 bits of the base address.
+		 * dummy_base_addr is always 64 bits, but we memcpy the correct
+		 * number of bytes from it to the destination.
+		 */
+		if (x86_64)
+			*data_size = UMIP_GDT_IDT_BASE_SIZE_64BIT;
+		else
+			*data_size = UMIP_GDT_IDT_BASE_SIZE_32BIT;
+
+		memcpy(data + 2, &dummy_base_addr, *data_size);
 
-		memcpy(data + 2, &dummy_base_addr, UMIP_GDT_IDT_BASE_SIZE);
+		*data_size += UMIP_GDT_IDT_LIMIT_SIZE;
 		memcpy(data, &dummy_limit, UMIP_GDT_IDT_LIMIT_SIZE);
 
 	} else if (umip_inst == UMIP_INST_SMSW) {
-		dummy_value = CR0_STATE;
+		unsigned long dummy_value = CR0_STATE;
 
 		/*
 		 * Even though the CR0 register has 4 bytes, the number
@@ -290,11 +301,10 @@ static void force_sig_info_umip_fault(void __user *addr, struct pt_regs *regs)
  * fixup_umip_exception() - Fixup a general protection fault caused by UMIP
  * @regs:	Registers as saved when entering the #GP handler
  *
- * The instructions sgdt, sidt, str, smsw, sldt cause a general protection
- * fault if executed with CPL > 0 (i.e., from user space). If the offending
- * user-space process is not in long mode, this function fixes the exception
- * up and provides dummy results for sgdt, sidt and smsw; str and sldt are not
- * fixed up. Also long mode user-space processes are not fixed up.
+ * The instructions SGDT, SIDT, STR, SMSW and SLDT cause a general protection
+ * fault if executed with CPL > 0 (i.e., from user space). This function fixes
+ * the exception up and provides dummy results for SGDT, SIDT and SMSW; STR
+ * and SLDT are not fixed up.
  *
  * If operands are memory addresses, results are copied to user-space memory as
  * indicated by the instruction pointed by eIP using the registers indicated in
@@ -373,13 +383,14 @@ bool fixup_umip_exception(struct pt_regs *regs)
 	umip_pr_warning(regs, "%s instruction cannot be used by applications.\n",
 			umip_insns[umip_inst]);
 
-	/* Do not emulate SLDT, STR or user long mode processes. */
-	if (umip_inst == UMIP_INST_STR || umip_inst == UMIP_INST_SLDT || user_64bit_mode(regs))
+	/* Do not emulate (spoof) SLDT or STR. */
+	if (umip_inst == UMIP_INST_STR || umip_inst == UMIP_INST_SLDT)
 		return false;
 
 	umip_pr_warning(regs, "For now, expensive software emulation returns the result.\n");
 
-	if (emulate_umip_insn(&insn, umip_inst, dummy_data, &dummy_data_size))
+	if (emulate_umip_insn(&insn, umip_inst, dummy_data, &dummy_data_size,
+			      user_64bit_mode(regs)))
 		return false;
 
 	/*

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [tip: x86/asm] x86/umip: Add emulation (spoofing) for UMIP covered instructions in 64-bit processes as well
  2019-09-05 23:22 [PATCH] x86/umip: Add emulation for 64-bit processes Brendan Shanks
  2019-09-07 21:26 ` Ricardo Neri
  2019-09-09 12:04 ` hpa
@ 2019-09-10  6:41 ` tip-bot2 for Brendan Shanks
  2 siblings, 0 replies; 10+ messages in thread
From: tip-bot2 for Brendan Shanks @ 2019-09-10  6:41 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Ricardo Neri, Brendan Shanks, H. Peter Anvin (Intel),
	Andy Lutomirski, Borislav Petkov, Brian Gerst, Denys Vlasenko,
	Eric W. Biederman, Linus Torvalds, Peter Zijlstra,
	Thomas Gleixner, Ingo Molnar, linux-kernel

The following commit has been merged into the x86/asm branch of tip:

Commit-ID:     e86c2c8b9380440bbe761b8e2f63ab6b04a45ac2
Gitweb:        https://git.kernel.org/tip/e86c2c8b9380440bbe761b8e2f63ab6b04a45ac2
Author:        Brendan Shanks <bshanks@codeweavers.com>
AuthorDate:    Thu, 05 Sep 2019 16:22:21 -07:00
Committer:     Ingo Molnar <mingo@kernel.org>
CommitterDate: Tue, 10 Sep 2019 08:36:16 +02:00

x86/umip: Add emulation (spoofing) for UMIP covered instructions in 64-bit processes as well

Add emulation (spoofing) of the SGDT, SIDT, and SMSW instructions for 64-bit
processes.

Wine users have encountered a number of 64-bit Windows games that use
these instructions (particularly SGDT), and were crashing when run on
UMIP-enabled systems.

Originally-by: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
Signed-off-by: Brendan Shanks <bshanks@codeweavers.com>
Reviewed-by: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
Reviewed-by: H. Peter Anvin (Intel) <hpa@zytor.com>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: Eric W. Biederman <ebiederm@xmission.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/20190905232222.14900-1-bshanks@codeweavers.com
[ Minor edits: capitalization, added 'spoofing' wording. ]
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
 arch/x86/kernel/umip.c | 65 +++++++++++++++++++++++------------------
 1 file changed, 38 insertions(+), 27 deletions(-)

diff --git a/arch/x86/kernel/umip.c b/arch/x86/kernel/umip.c
index 5b345ad..548fefe 100644
--- a/arch/x86/kernel/umip.c
+++ b/arch/x86/kernel/umip.c
@@ -19,7 +19,7 @@
 /** DOC: Emulation for User-Mode Instruction Prevention (UMIP)
  *
  * The feature User-Mode Instruction Prevention present in recent Intel
- * processor prevents a group of instructions (sgdt, sidt, sldt, smsw, and str)
+ * processor prevents a group of instructions (SGDT, SIDT, SLDT, SMSW and STR)
  * from being executed with CPL > 0. Otherwise, a general protection fault is
  * issued.
  *
@@ -36,8 +36,8 @@
  * DOSEMU2) rely on this subset of instructions to function.
  *
  * The instructions protected by UMIP can be split in two groups. Those which
- * return a kernel memory address (sgdt and sidt) and those which return a
- * value (sldt, str and smsw).
+ * return a kernel memory address (SGDT and SIDT) and those which return a
+ * value (SLDT, STR and SMSW).
  *
  * For the instructions that return a kernel memory address, applications
  * such as WineHQ rely on the result being located in the kernel memory space,
@@ -45,15 +45,13 @@
  * value that, lies close to the top of the kernel memory. The limit for the GDT
  * and the IDT are set to zero.
  *
- * Given that sldt and str are not commonly used in programs that run on WineHQ
+ * Given that SLDT and STR are not commonly used in programs that run on WineHQ
  * or DOSEMU2, they are not emulated.
  *
  * The instruction smsw is emulated to return the value that the register CR0
  * has at boot time as set in the head_32.
  *
- * Also, emulation is provided only for 32-bit processes; 64-bit processes
- * that attempt to use the instructions that UMIP protects will receive the
- * SIGSEGV signal issued as a consequence of the general protection fault.
+ * Emulation is provided for both 32-bit and 64-bit processes.
  *
  * Care is taken to appropriately emulate the results when segmentation is
  * used. That is, rather than relying on USER_DS and USER_CS, the function
@@ -63,17 +61,18 @@
  * application uses a local descriptor table.
  */
 
-#define UMIP_DUMMY_GDT_BASE 0xfffe0000
-#define UMIP_DUMMY_IDT_BASE 0xffff0000
+#define UMIP_DUMMY_GDT_BASE 0xfffffffffffe0000ULL
+#define UMIP_DUMMY_IDT_BASE 0xffffffffffff0000ULL
 
 /*
  * The SGDT and SIDT instructions store the contents of the global descriptor
  * table and interrupt table registers, respectively. The destination is a
  * memory operand of X+2 bytes. X bytes are used to store the base address of
- * the table and 2 bytes are used to store the limit. In 32-bit processes, the
- * only processes for which emulation is provided, X has a value of 4.
+ * the table and 2 bytes are used to store the limit. In 32-bit processes X
+ * has a value of 4, in 64-bit processes X has a value of 8.
  */
-#define UMIP_GDT_IDT_BASE_SIZE 4
+#define UMIP_GDT_IDT_BASE_SIZE_64BIT 8
+#define UMIP_GDT_IDT_BASE_SIZE_32BIT 4
 #define UMIP_GDT_IDT_LIMIT_SIZE 2
 
 #define	UMIP_INST_SGDT	0	/* 0F 01 /0 */
@@ -189,6 +188,7 @@ static int identify_insn(struct insn *insn)
  * @umip_inst:	A constant indicating the instruction to emulate
  * @data:	Buffer into which the dummy result is stored
  * @data_size:	Size of the emulated result
+ * @x86_64:	true if process is 64-bit, false otherwise
  *
  * Emulate an instruction protected by UMIP and provide a dummy result. The
  * result of the emulation is saved in @data. The size of the results depends
@@ -202,11 +202,8 @@ static int identify_insn(struct insn *insn)
  * 0 on success, -EINVAL on error while emulating.
  */
 static int emulate_umip_insn(struct insn *insn, int umip_inst,
-			     unsigned char *data, int *data_size)
+			     unsigned char *data, int *data_size, bool x86_64)
 {
-	unsigned long dummy_base_addr, dummy_value;
-	unsigned short dummy_limit = 0;
-
 	if (!data || !data_size || !insn)
 		return -EINVAL;
 	/*
@@ -219,6 +216,9 @@ static int emulate_umip_insn(struct insn *insn, int umip_inst,
 	 * is always returned irrespective of the operand size.
 	 */
 	if (umip_inst == UMIP_INST_SGDT || umip_inst == UMIP_INST_SIDT) {
+		u64 dummy_base_addr;
+		u16 dummy_limit = 0;
+
 		/* SGDT and SIDT do not use registers operands. */
 		if (X86_MODRM_MOD(insn->modrm.value) == 3)
 			return -EINVAL;
@@ -228,13 +228,24 @@ static int emulate_umip_insn(struct insn *insn, int umip_inst,
 		else
 			dummy_base_addr = UMIP_DUMMY_IDT_BASE;
 
-		*data_size = UMIP_GDT_IDT_LIMIT_SIZE + UMIP_GDT_IDT_BASE_SIZE;
+		/*
+		 * 64-bit processes use the entire dummy base address.
+		 * 32-bit processes use the lower 32 bits of the base address.
+		 * dummy_base_addr is always 64 bits, but we memcpy the correct
+		 * number of bytes from it to the destination.
+		 */
+		if (x86_64)
+			*data_size = UMIP_GDT_IDT_BASE_SIZE_64BIT;
+		else
+			*data_size = UMIP_GDT_IDT_BASE_SIZE_32BIT;
+
+		memcpy(data + 2, &dummy_base_addr, *data_size);
 
-		memcpy(data + 2, &dummy_base_addr, UMIP_GDT_IDT_BASE_SIZE);
+		*data_size += UMIP_GDT_IDT_LIMIT_SIZE;
 		memcpy(data, &dummy_limit, UMIP_GDT_IDT_LIMIT_SIZE);
 
 	} else if (umip_inst == UMIP_INST_SMSW) {
-		dummy_value = CR0_STATE;
+		unsigned long dummy_value = CR0_STATE;
 
 		/*
 		 * Even though the CR0 register has 4 bytes, the number
@@ -290,11 +301,10 @@ static void force_sig_info_umip_fault(void __user *addr, struct pt_regs *regs)
  * fixup_umip_exception() - Fixup a general protection fault caused by UMIP
  * @regs:	Registers as saved when entering the #GP handler
  *
- * The instructions sgdt, sidt, str, smsw, sldt cause a general protection
- * fault if executed with CPL > 0 (i.e., from user space). If the offending
- * user-space process is not in long mode, this function fixes the exception
- * up and provides dummy results for sgdt, sidt and smsw; str and sldt are not
- * fixed up. Also long mode user-space processes are not fixed up.
+ * The instructions SGDT, SIDT, STR, SMSW and SLDT cause a general protection
+ * fault if executed with CPL > 0 (i.e., from user space). This function fixes
+ * the exception up and provides dummy results for SGDT, SIDT and SMSW; STR
+ * and SLDT are not fixed up.
  *
  * If operands are memory addresses, results are copied to user-space memory as
  * indicated by the instruction pointed by eIP using the registers indicated in
@@ -373,13 +383,14 @@ bool fixup_umip_exception(struct pt_regs *regs)
 	umip_pr_warning(regs, "%s instruction cannot be used by applications.\n",
 			umip_insns[umip_inst]);
 
-	/* Do not emulate SLDT, STR or user long mode processes. */
-	if (umip_inst == UMIP_INST_STR || umip_inst == UMIP_INST_SLDT || user_64bit_mode(regs))
+	/* Do not emulate (spoof) SLDT or STR. */
+	if (umip_inst == UMIP_INST_STR || umip_inst == UMIP_INST_SLDT)
 		return false;
 
 	umip_pr_warning(regs, "For now, expensive software emulation returns the result.\n");
 
-	if (emulate_umip_insn(&insn, umip_inst, dummy_data, &dummy_data_size))
+	if (emulate_umip_insn(&insn, umip_inst, dummy_data, &dummy_data_size,
+			      user_64bit_mode(regs)))
 		return false;
 
 	/*

^ permalink raw reply related	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2019-09-10  6:41 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-09-05 23:22 [PATCH] x86/umip: Add emulation for 64-bit processes Brendan Shanks
2019-09-07 21:26 ` Ricardo Neri
2019-09-08  7:22   ` Borislav Petkov
2019-09-09 11:56     ` hpa
2019-09-09 22:34   ` Brendan Shanks
2019-09-09 12:04 ` hpa
2019-09-10  6:28   ` Ingo Molnar
2019-09-10  6:32     ` hpa
2019-09-10  6:37       ` [PATCH v2] " Ingo Molnar
2019-09-10  6:41 ` [tip: x86/asm] x86/umip: Add emulation (spoofing) for UMIP covered instructions in 64-bit processes as well tip-bot2 for Brendan Shanks

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.