Re: [PATCH] x86/umip: Add emulation for 64-bit processes

2019-09-10 Thread hpa
On September 10, 2019 7:28:28 AM GMT+01:00, Ingo Molnar  
wrote:
>
>* h...@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) 
-- 
Sent from my Android device with K-9 Mail. Please excuse my brevity.


Re: [PATCH] x86/umip: Add emulation for 64-bit processes

2019-09-10 Thread Ingo Molnar


* h...@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


Re: [PATCH] x86/umip: Add emulation for 64-bit processes

2019-09-09 Thread Brendan Shanks


> On Sep 7, 2019, at 2:26 PM, Ricardo Neri 
>  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

Re: [PATCH] x86/umip: Add emulation for 64-bit processes

2019-09-09 Thread hpa
On September 6, 2019 12:22:21 AM GMT+01:00, 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.
>
>Originally-by: Ricardo Neri 
>Signed-off-by: Brendan Shanks 
>---
> 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 0xfffe
>-#define UMIP_DUMMY_IDT_BASE 0x
>+#define UMIP_DUMMY_GDT_BASE 0xfffeULL
>+#define UMIP_DUMMY_IDT_BASE 0xULL
> 
> /*
>* 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, _base_addr, *data_size);
> 
>-  memcpy(data + 2, _base_addr, UMIP_GDT_IDT_BASE_SIZE);
>+  *data_size += UMIP_GDT_IDT_LIMIT_SIZE;
>   memcpy(data, _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 

Re: [PATCH] x86/umip: Add emulation for 64-bit processes

2019-09-09 Thread hpa
On September 8, 2019 8:22:48 AM GMT+01:00, Borislav Petkov  
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.


Re: [PATCH] x86/umip: Add emulation for 64-bit processes

2019-09-08 Thread Borislav Petkov
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


Re: [PATCH] x86/umip: Add emulation for 64-bit processes

2019-09-07 Thread Ricardo Neri
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 

Only one minor comment below...

> 
> Originally-by: Ricardo Neri 
> Signed-off-by: Brendan Shanks 
> ---
>  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 0xfffe
> -#define UMIP_DUMMY_IDT_BASE 0x
> +#define UMIP_DUMMY_GDT_BASE 0xfffeULL
> +#define UMIP_DUMMY_IDT_BASE 0xULL
>  
>  /*
>   * 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


[PATCH] x86/umip: Add emulation for 64-bit processes

2019-09-05 Thread Brendan Shanks
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 
Signed-off-by: Brendan Shanks 
---
 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 0xfffe
-#define UMIP_DUMMY_IDT_BASE 0x
+#define UMIP_DUMMY_GDT_BASE 0xfffeULL
+#define UMIP_DUMMY_IDT_BASE 0xULL
 
 /*
  * 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
 
 #defineUMIP_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, _base_addr, *data_size);
 
-   memcpy(data + 2, _base_addr, UMIP_GDT_IDT_BASE_SIZE);
+   *data_size += UMIP_GDT_IDT_LIMIT_SIZE;
memcpy(data, _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: