Alexandre Julliard : ntdll: Validate the extended context before modifying the other registers.

Alexandre Julliard julliard at winehq.org
Mon Jun 7 16:30:35 CDT 2021


Module: wine
Branch: master
Commit: ba5d73d796e5ed5b3da857162eb8c9097c03807d
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=ba5d73d796e5ed5b3da857162eb8c9097c03807d

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Mon Jun  7 13:16:24 2021 +0200

ntdll: Validate the extended context before modifying the other registers.

Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/ntdll/unix/signal_i386.c   | 27 ++++++++++++++++-----------
 dlls/ntdll/unix/signal_x86_64.c | 27 ++++++++++++++++-----------
 2 files changed, 32 insertions(+), 22 deletions(-)

diff --git a/dlls/ntdll/unix/signal_i386.c b/dlls/ntdll/unix/signal_i386.c
index c3f8c01d350..b66a7bd8995 100644
--- a/dlls/ntdll/unix/signal_i386.c
+++ b/dlls/ntdll/unix/signal_i386.c
@@ -994,7 +994,19 @@ NTSTATUS WINAPI NtSetContextThread( HANDLE handle, const CONTEXT *context )
     struct syscall_frame *frame = x86_thread_data()->syscall_frame;
     DWORD flags = context->ContextFlags & ~CONTEXT_i386;
     BOOL self = (handle == GetCurrentThread());
-    XSTATE *xs;
+
+    if ((flags & CONTEXT_XSTATE) && (cpu_info.ProcessorFeatureBits & CPU_FEATURE_AVX))
+    {
+        CONTEXT_EX *context_ex = (CONTEXT_EX *)(context + 1);
+        XSTATE *xs = (XSTATE *)((char *)context_ex + context_ex->XState.Offset);
+
+        if (context_ex->XState.Length < offsetof(XSTATE, YmmContext) ||
+            context_ex->XState.Length > sizeof(XSTATE))
+            return STATUS_INVALID_PARAMETER;
+        if ((xs->Mask & XSTATE_MASK_GSSE) && (context_ex->XState.Length < sizeof(XSTATE)))
+            return STATUS_BUFFER_OVERFLOW;
+    }
+    else flags &= ~CONTEXT_XSTATE;
 
     /* debug registers require a server call */
     if (self && (flags & CONTEXT_DEBUG_REGISTERS))
@@ -1066,25 +1078,18 @@ NTSTATUS WINAPI NtSetContextThread( HANDLE handle, const CONTEXT *context )
         }
         xsave->xstate.mask |= XSTATE_MASK_LEGACY_FLOATING_POINT;
     }
-    if ((cpu_info.ProcessorFeatureBits & CPU_FEATURE_AVX) && (xs = xstate_from_context( context )))
+    if (flags & CONTEXT_XSTATE)
     {
         struct syscall_xsave *xsave = get_syscall_xsave( frame );
         CONTEXT_EX *context_ex = (CONTEXT_EX *)(context + 1);
-
-        if (context_ex->XState.Length < offsetof(XSTATE, YmmContext)
-            || context_ex->XState.Length > sizeof(XSTATE))
-            return STATUS_INVALID_PARAMETER;
+        XSTATE *xs = (XSTATE *)((char *)context_ex + context_ex->XState.Offset);
 
         if (xs->Mask & XSTATE_MASK_GSSE)
         {
-            if (context_ex->XState.Length < sizeof(XSTATE))
-                return STATUS_BUFFER_OVERFLOW;
-
             xsave->xstate.mask |= XSTATE_MASK_GSSE;
             memcpy( &xsave->xstate.ymm_high, &xs->YmmContext, sizeof(xsave->xstate.ymm_high) );
         }
-        else
-            xsave->xstate.mask &= ~XSTATE_MASK_GSSE;
+        else xsave->xstate.mask &= ~XSTATE_MASK_GSSE;
     }
 
     return STATUS_SUCCESS;
diff --git a/dlls/ntdll/unix/signal_x86_64.c b/dlls/ntdll/unix/signal_x86_64.c
index 59c030ae6a4..086bfdfe066 100644
--- a/dlls/ntdll/unix/signal_x86_64.c
+++ b/dlls/ntdll/unix/signal_x86_64.c
@@ -1618,7 +1618,19 @@ NTSTATUS WINAPI NtSetContextThread( HANDLE handle, const CONTEXT *context )
     BOOL self = (handle == GetCurrentThread());
     struct syscall_frame *frame;
     struct syscall_xsave *xsave;
-    XSTATE *xs;
+
+    if ((flags & CONTEXT_XSTATE) && (cpu_info.ProcessorFeatureBits & CPU_FEATURE_AVX))
+    {
+        CONTEXT_EX *context_ex = (CONTEXT_EX *)(context + 1);
+        XSTATE *xs = (XSTATE *)((char *)context_ex + context_ex->XState.Offset);
+
+        if (context_ex->XState.Length < offsetof(XSTATE, YmmContext) ||
+            context_ex->XState.Length > sizeof(XSTATE))
+            return STATUS_INVALID_PARAMETER;
+        if ((xs->Mask & XSTATE_MASK_GSSE) && (context_ex->XState.Length < sizeof(XSTATE)))
+            return STATUS_BUFFER_OVERFLOW;
+    }
+    else flags &= ~CONTEXT_XSTATE;
 
     /* debug registers require a server call */
     if (self && (flags & CONTEXT_DEBUG_REGISTERS))
@@ -1684,24 +1696,17 @@ NTSTATUS WINAPI NtSetContextThread( HANDLE handle, const CONTEXT *context )
         xsave->xsave = context->u.FltSave;
         xsave->xstate.Mask |= XSTATE_MASK_LEGACY;
     }
-    if ((cpu_info.ProcessorFeatureBits & CPU_FEATURE_AVX) && (xs = xstate_from_context( context )))
+    if (flags & CONTEXT_XSTATE)
     {
         CONTEXT_EX *context_ex = (CONTEXT_EX *)(context + 1);
-
-        if (context_ex->XState.Length < offsetof(XSTATE, YmmContext)
-            || context_ex->XState.Length > sizeof(XSTATE))
-            return STATUS_INVALID_PARAMETER;
+        XSTATE *xs = (XSTATE *)((char *)context_ex + context_ex->XState.Offset);
 
         if (xs->Mask & XSTATE_MASK_GSSE)
         {
-            if (context_ex->XState.Length < sizeof(XSTATE))
-                return STATUS_BUFFER_OVERFLOW;
-
             xsave->xstate.Mask |= XSTATE_MASK_GSSE;
             memcpy( &xsave->xstate.YmmContext, &xs->YmmContext, sizeof(xs->YmmContext) );
         }
-        else
-            xsave->xstate.Mask &= ~XSTATE_MASK_GSSE;
+        else xsave->xstate.Mask &= ~XSTATE_MASK_GSSE;
     }
     return STATUS_SUCCESS;
 }




More information about the wine-cvs mailing list