[PATCH 2/2] ntdll: Filter EFlags from user-supplied CONTEXT on x86 and x64.

Jinoh Kang wine at gitlab.winehq.org
Mon Jun 20 06:29:36 CDT 2022


From: Jinoh Kang <jinoh.kang.kr at gmail.com>

Signed-off-by: Jinoh Kang <jinoh.kang.kr at gmail.com>
---
 dlls/ntdll/tests/exception.c    |  2 --
 dlls/ntdll/unix/signal_i386.c   |  2 +-
 dlls/ntdll/unix/signal_x86_64.c |  4 ++--
 dlls/ntdll/unix/thread.c        | 20 +++++++++++++++++++-
 dlls/ntdll/unix/unix_private.h  | 13 +++++++++++++
 5 files changed, 35 insertions(+), 6 deletions(-)

diff --git a/dlls/ntdll/tests/exception.c b/dlls/ntdll/tests/exception.c
index ee486380b8d..169045bf5e6 100644
--- a/dlls/ntdll/tests/exception.c
+++ b/dlls/ntdll/tests/exception.c
@@ -10721,7 +10721,6 @@ static void test_eflags_sanitization(void)
         ok(status == STATUS_SUCCESS, "NtSetContextThread failed with %lx\n", status);
         status = pNtGetContextThread(thread, &context);
         ok(status == STATUS_SUCCESS, "NtGetContextThread failed with %lx\n", status);
-        todo_wine
         ok(context.EFlags == max_eflags, "Expected EFlags to be %#lx, got %#lx\n", max_eflags, context.EFlags);
 
         context.EFlags = 0;
@@ -10729,7 +10728,6 @@ static void test_eflags_sanitization(void)
         ok(status == STATUS_SUCCESS, "NtSetContextThread failed with %lx\n", status);
         status = pNtGetContextThread(thread, &context);
         ok(status == STATUS_SUCCESS, "NtGetContextThread failed with %lx\n", status);
-        todo_wine
         ok(context.EFlags == min_eflags, "Expected EFlags to be %#lx, got %#lx\n", max_eflags, context.EFlags);
 
         context.EFlags = old_eflags;
diff --git a/dlls/ntdll/unix/signal_i386.c b/dlls/ntdll/unix/signal_i386.c
index 7be0c39c424..9be0769904d 100644
--- a/dlls/ntdll/unix/signal_i386.c
+++ b/dlls/ntdll/unix/signal_i386.c
@@ -941,7 +941,7 @@ NTSTATUS WINAPI NtSetContextThread( HANDLE handle, const CONTEXT *context )
         frame->esp    = context->Esp;
         frame->ebp    = context->Ebp;
         frame->eip    = context->Eip;
-        frame->eflags = context->EFlags;
+        frame->eflags = arch_flags_reg_from_user( context->EFlags, IMAGE_FILE_MACHINE_I386 );
         frame->cs     = context->SegCs;
         frame->ss     = context->SegSs;
     }
diff --git a/dlls/ntdll/unix/signal_x86_64.c b/dlls/ntdll/unix/signal_x86_64.c
index 6c87e347eac..c4f67a16cc9 100644
--- a/dlls/ntdll/unix/signal_x86_64.c
+++ b/dlls/ntdll/unix/signal_x86_64.c
@@ -1788,7 +1788,7 @@ NTSTATUS WINAPI NtSetContextThread( HANDLE handle, const CONTEXT *context )
         frame->rsp    = context->Rsp;
         frame->rbp    = context->Rbp;
         frame->rip    = context->Rip;
-        frame->eflags = context->EFlags;
+        frame->eflags = arch_flags_reg_from_user( context->EFlags, IMAGE_FILE_MACHINE_AMD64 );
         frame->cs     = context->SegCs;
         frame->ss     = context->SegSs;
     }
@@ -2002,7 +2002,7 @@ NTSTATUS set_thread_wow64_context( HANDLE handle, const void *ctx, ULONG size )
         wow_frame->Esp    = context->Esp;
         wow_frame->Ebp    = context->Ebp;
         wow_frame->Eip    = context->Eip;
-        wow_frame->EFlags = context->EFlags;
+        wow_frame->EFlags = arch_flags_reg_from_user( context->EFlags, IMAGE_FILE_MACHINE_I386 );
         wow_frame->SegCs  = cs32_sel;
         wow_frame->SegSs  = ds64_sel;
         cpu->Flags |= WOW64_CPURESERVED_FLAG_RESET_STATE;
diff --git a/dlls/ntdll/unix/thread.c b/dlls/ntdll/unix/thread.c
index ad47a5fce74..e0d44bb4a38 100644
--- a/dlls/ntdll/unix/thread.c
+++ b/dlls/ntdll/unix/thread.c
@@ -1663,13 +1663,31 @@ NTSTATUS WINAPI NtQueueApcThread( HANDLE handle, PNTAPCFUNC func, ULONG_PTR arg1
 NTSTATUS set_thread_context( HANDLE handle, const void *context, BOOL *self, USHORT machine )
 {
     context_t server_contexts[2];
-    unsigned int count = 0;
+    unsigned int count = 0, i;
     NTSTATUS ret;
 
     context_to_server( &server_contexts[count++], native_machine, context, machine );
     if (machine != native_machine)
         context_to_server( &server_contexts[count++], machine, context, machine );
 
+    for (i = 0; i < count; i++)
+    {
+        unsigned int *flags_ptr;
+        if (!(server_contexts[i].flags & SERVER_CTX_CONTROL)) continue;
+        switch (server_contexts[i].machine)
+        {
+        case IMAGE_FILE_MACHINE_I386:
+            flags_ptr = &server_contexts[i].ctl.i386_regs.eflags;
+            break;
+        case IMAGE_FILE_MACHINE_AMD64:
+            flags_ptr = &server_contexts[i].ctl.x86_64_regs.flags;
+            break;
+        default:
+            continue;
+        }
+        *flags_ptr = arch_flags_reg_from_user( *flags_ptr, machine );
+    }
+
     SERVER_START_REQ( set_thread_context )
     {
         req->handle  = wine_server_obj_handle( handle );
diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h
index 795fc148479..3558f898b36 100644
--- a/dlls/ntdll/unix/unix_private.h
+++ b/dlls/ntdll/unix/unix_private.h
@@ -458,4 +458,17 @@ static inline NTSTATUS map_section( HANDLE mapping, void **ptr, SIZE_T *size, UL
                                0, NULL, size, ViewShare, 0, protect );
 }
 
+static inline DWORD arch_flags_reg_from_user( DWORD flags, USHORT machine )
+{
+    switch (machine)
+    {
+    case IMAGE_FILE_MACHINE_I386:
+        return (flags & 0x003f0fd7) | 0x00000202;
+    case IMAGE_FILE_MACHINE_AMD64:
+        return (flags & 0x00210fd5) | 0x00000200;
+    default:
+        return flags;
+    }
+}
+
 #endif /* __NTDLL_UNIX_PRIVATE_H */
-- 
GitLab

https://gitlab.winehq.org/wine/wine/-/merge_requests/283



More information about the wine-devel mailing list