[PATCH] ntdll: Place PEB before first TEB.

Paul Gofman pgofman at codeweavers.com
Mon Nov 22 11:33:35 CST 2021


Signed-off-by: Paul Gofman <pgofman at codeweavers.com>
---
 dlls/ntdll/tests/wow64.c  | 25 +++++++++++++++++++++++++
 dlls/ntdll/thread.c       |  4 +---
 dlls/ntdll/unix/debug.c   |  2 +-
 dlls/ntdll/unix/virtual.c | 15 ++++++++-------
 4 files changed, 35 insertions(+), 11 deletions(-)

diff --git a/dlls/ntdll/tests/wow64.c b/dlls/ntdll/tests/wow64.c
index be2f2138933..3d2548843be 100644
--- a/dlls/ntdll/tests/wow64.c
+++ b/dlls/ntdll/tests/wow64.c
@@ -225,6 +225,14 @@ static void test_query_architectures(void)
     }
 }
 
+static TEB *test_thread_teb_addr;
+
+static DWORD WINAPI test_teb_addr_thread(void *ptr)
+{
+    test_thread_teb_addr = NtCurrentTeb();
+    return 0;
+}
+
 static void test_peb_teb(void)
 {
     PROCESS_BASIC_INFORMATION proc_info;
@@ -232,6 +240,7 @@ static void test_peb_teb(void)
     PROCESS_INFORMATION pi;
     STARTUPINFOA si = {0};
     NTSTATUS status;
+    HANDLE thread;
     void *redir;
     SIZE_T res;
     TEB teb;
@@ -419,6 +428,22 @@ static void test_peb_teb(void)
     ok( !NtCurrentTeb()->GdiBatchCount, "GdiBatchCount set to %x\n", NtCurrentTeb()->GdiBatchCount );
     ok( !NtCurrentTeb()->WowTebOffset || broken( NtCurrentTeb()->WowTebOffset == 1 ), /* vista */
         "WowTebOffset set to %x\n", NtCurrentTeb()->WowTebOffset );
+
+    thread = CreateThread( NULL, 0, test_teb_addr_thread, NULL, 0, NULL );
+    WaitForSingleObject( thread, INFINITE );
+    if (test_thread_teb_addr > NtCurrentTeb())
+    {
+        if (sizeof(void *) > sizeof(int) || is_wow64)
+        {
+            ok( (char *)NtCurrentTeb() - NtCurrentTeb()->WowTebOffset == (char *)NtCurrentTeb()->Peb + 0x1000,
+                "Got unexpected teb %p, peb %p.\n", NtCurrentTeb(), NtCurrentTeb()->Peb );
+        }
+    }
+    else
+    {
+        /* Before Win10 1607. */
+        win_skip( "Old teb placement.\n" );
+    }
 }
 
 static void test_selectors(void)
diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c
index 37dc7c8ab37..dcf226294e8 100644
--- a/dlls/ntdll/thread.c
+++ b/dlls/ntdll/thread.c
@@ -63,9 +63,7 @@ static inline struct debug_info *get_info(void)
 
 static void init_options(void)
 {
-    unsigned int offset = page_size * (sizeof(void *) / 4);
-
-    debug_options = (struct __wine_debug_channel *)((char *)NtCurrentTeb()->Peb + offset);
+    debug_options = (struct __wine_debug_channel *)((char *)NtCurrentTeb()->Peb - 3 * page_size);
     while (debug_options[nb_debug_options].name[0]) nb_debug_options++;
 }
 
diff --git a/dlls/ntdll/unix/debug.c b/dlls/ntdll/unix/debug.c
index 26e7decc059..7744d421f6d 100644
--- a/dlls/ntdll/unix/debug.c
+++ b/dlls/ntdll/unix/debug.c
@@ -324,7 +324,7 @@ void dbg_init(void)
 
     if (nb_debug_options == -1) init_options();
 
-    options = (struct __wine_debug_channel *)((char *)peb + (is_win64 ? 2 : 1) * page_size);
+    options = (struct __wine_debug_channel *)((char *)peb - 3 * page_size);
     memcpy( options, debug_options, nb_debug_options * sizeof(*options) );
     free( debug_options );
     debug_options = options;
diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c
index 5873a3e2335..1dcde261bcf 100644
--- a/dlls/ntdll/unix/virtual.c
+++ b/dlls/ntdll/unix/virtual.c
@@ -2986,6 +2986,7 @@ static TEB *init_teb( void *ptr, BOOL is_wow )
  */
 TEB *virtual_alloc_first_teb(void)
 {
+    static const BOOL is_wow = FALSE;
     void *ptr;
     NTSTATUS status;
     SIZE_T data_size = page_size;
@@ -3003,12 +3004,12 @@ TEB *virtual_alloc_first_teb(void)
 
     NtAllocateVirtualMemory( NtCurrentProcess(), &teb_block, is_win64 ? 0x7fffffff : 0, &total,
                              MEM_RESERVE | MEM_TOP_DOWN, PAGE_READWRITE );
-    teb_block_pos = 30;
-    ptr = (char *)teb_block + 30 * block_size;
+    teb_block_pos = 2;
+    ptr = (char *)teb_block;
     data_size = 2 * block_size;
     NtAllocateVirtualMemory( NtCurrentProcess(), (void **)&ptr, 0, &data_size, MEM_COMMIT, PAGE_READWRITE );
-    peb = (PEB *)((char *)teb_block + 31 * block_size + (is_win64 ? 0 : page_size));
-    return init_teb( ptr, FALSE );
+    peb = (PEB *)((char *)teb_block + block_size - page_size - (is_win64 && is_wow ? page_size : 0));
+    return init_teb( (char *)ptr + block_size, is_wow );
 }
 
 
@@ -3033,7 +3034,7 @@ NTSTATUS virtual_alloc_teb( TEB **ret_teb )
     }
     else
     {
-        if (!teb_block_pos)
+        if (teb_block_pos == 32)
         {
             SIZE_T total = 32 * block_size;
 
@@ -3044,9 +3045,9 @@ NTSTATUS virtual_alloc_teb( TEB **ret_teb )
                 return status;
             }
             teb_block = ptr;
-            teb_block_pos = 32;
+            teb_block_pos = 0;
         }
-        ptr = ((char *)teb_block + --teb_block_pos * block_size);
+        ptr = ((char *)teb_block + teb_block_pos++ * block_size);
         NtAllocateVirtualMemory( NtCurrentProcess(), (void **)&ptr, 0, &block_size,
                                  MEM_COMMIT, PAGE_READWRITE );
     }
-- 
2.33.1




More information about the wine-devel mailing list