Re: Please review a important patch abort fix setting of CPUX86State::gdt::base

2023-01-30 Thread Richard Henderson

On 1/30/23 03:12, fa...@mail.ustc.edu.cn wrote:


1. "The memcpy is definitely wrong, because you're casting a guest address into a 
host address, which is incorrect. You have to use g2h()."
There is no need to use g2h(), Because there are both guest address whether source or 
dest memory. refer to "linux-user/i386/cpu_loop.c" target_cpu_copy_regs 
function, Only use g2h_untagged when convert gdt::base to gdt_table. I don't use and 
modify gdt_table, Only copy gdt::base from source CPU to dest CPU. They are same type so 
no needed to convert by g2h.


This is *not* about the type, this is about the location in host memory, as input to 
memcpy.  The g2h function is 1-to-1, but it is not the identity function.




2. "I'm actually surprised that you need this for TARGET_X86_64 at all ..."
GDT on QEMU User Mode is Pseudorandom GDT,It is NOT kernel private data 
structures. It is NOT Global Descriptor Table. It IS index table of fs and gs. 
And It is Thread local data. The Memory which gdt::base point can be modified 
by syscall SYS_set_thread_data.


Well, then you'll need to fix other assumptions in target/i386/tcg/translate.c, beginning 
with


#if defined(CONFIG_USER_ONLY) && defined(TARGET_X86_64)
#define VM86(S)   false
#define CODE32(S) true
#define SS32(S)   true
#define ADDSEG(S) false

which currently means that whatever you do with set_thread_data won't be recognized at 
translation time.



r~



Re: Re: Please review a important patch abort fix setting of CPUX86State::gdt::base

2023-01-30 Thread fanwj--- via

1. "The memcpy is definitely wrong, because you're casting a guest address into 
a host address, which is incorrect. You have to use g2h()."
There is no need to use g2h(), Because there are both guest address whether 
source or dest memory. refer to "linux-user/i386/cpu_loop.c" 
target_cpu_copy_regs function, Only use g2h_untagged when convert gdt::base to 
gdt_table. I don't use and modify gdt_table, Only copy gdt::base from source 
CPU to dest CPU. They are same type so no needed to convert by g2h.

2. "I'm actually surprised that you need this for TARGET_X86_64 at all ..."
GDT on QEMU User Mode is Pseudorandom GDT,It is NOT kernel private data 
structures. It is NOT Global Descriptor Table. It IS index table of fs and gs. 
And It is Thread local data. The Memory which gdt::base point can be modified 
by syscall SYS_set_thread_data.

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/x86/kernel/tls.c

SYS_get_thread_area and SYS_set_thread_area used on x32 usually, But They can 
be syscalled on x64 when emulate Wow64 environment. 





-
From:   Richard Henderson
Subject:Re: [PATCH] linux-user: fix bug about incorrect base addresss 
of gdt on i386 and x86_64
Date:   Sat, 14 Jan 2023 19:32:59 -1000
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 
Thunderbird/102.4.2
> On 1/3/23 01:38, fanwenjie wrote:
On linux user mode, CPUX86State::gdt::base from Different CPUX86State Objects 
have same value, It is incorrect! Every CPUX86State::gdt::base Must points to 
independent memory space.

Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1405
Signed-off-by: fanwenjie 
---
  linux-user/i386/cpu_loop.c | 9 +
  linux-user/main.c  | 7 +++
  2 files changed, 16 insertions(+)

diff --git a/linux-user/i386/cpu_loop.c b/linux-user/i386/cpu_loop.c
index 865413c..48511cd 100644
--- a/linux-user/i386/cpu_loop.c
+++ b/linux-user/i386/cpu_loop.c
@@ -314,8 +314,17 @@ void cpu_loop(CPUX86State *env)
  }
  }
+static void target_cpu_free(void *obj)
+{
+CPUArchState* env = ((CPUState*)obj)->env_ptr;
+target_munmap(env->gdt.base, sizeof(uint64_t) * TARGET_GDT_ENTRIES);
+g_free(obj);
+}
+
  void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs)
  {
+CPUState* cpu = env_cpu(env);
+OBJECT(cpu)->free = target_cpu_free;
  env->cr[0] = CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK;
  env->hflags |= HF_PE_MASK | HF_CPL_MASK;
  if (env->features[FEAT_1_EDX] & CPUID_SSE) {
diff --git a/linux-user/main.c b/linux-user/main.c
index a17fed0..3acd9b4 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -234,6 +234,13 @@ CPUArchState *cpu_copy(CPUArchState *env)
new_cpu->tcg_cflags = cpu->tcg_cflags;
  memcpy(new_env, env, sizeof(CPUArchState));
+#if defined(TARGET_I386) || defined(TARGET_X86_64)
+new_env->gdt.base = target_mmap(0, sizeof(uint64_t) * TARGET_GDT_ENTRIES,
+PROT_READ|PROT_WRITE,
+MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
+memcpy((void*)new_env->gdt.base, (void*)env->gdt.base, sizeof(uint64_t) * 
TARGET_GDT_ENTRIES);
+OBJECT(new_cpu)->free = OBJECT(cpu)->free;
+#endif

This isn't a fantastic solution, because neither the ldt nor the gdt should be 
mapped into the user address space -- these are kernel private data structures. 
But cpu.h uses a target_ulong, and seg_helper.c is set up to load data from the 
guest, and it would be a medium sized job to address that.

The memcpy is definitely wrong, because you're casting a guest address into a 
host address, which is incorrect. You have to use g2h().

I'm actually surprised that you need this for TARGET_X86_64 at all -- the two 
TLS segments don't really use the GDT at all, since fs_base and gs_base may be 
set directly.


Re: Please review a important patch abort fix setting of CPUX86State::gdt::base

2023-01-29 Thread Peter Maydell
On Sun, 29 Jan 2023 at 12:10,  wrote:
>
> The patch fix bug abort settting CPUX86State::gdt::base on linux-user, the 
> bug can write dirty data to emulated segment registers of x86
> Patch address:  
> https://lists.nongnu.org/archive/html/qemu-devel/2023-01/msg00142.html
> Bug description: https://gitlab.com/qemu-project/qemu/-/issues/1405

That patch was already reviewed a couple of weeks ago; you got
feedback which you need to address (or if you're not sure what
it is you ought to change in the patch, you should follow up in
that email thread to ask for clarification):

https://lists.nongnu.org/archive/html/qemu-devel/2023-01/msg03078.html

thanks
-- PMM