Jacek Caban : ntdll: Temporarily allow KeUserModeCallback calls from client stack.

Alexandre Julliard julliard at winehq.org
Thu Dec 9 15:34:27 CST 2021


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

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Thu Dec  9 03:15:04 2021 +0100

ntdll: Temporarily allow KeUserModeCallback calls from client stack.

Signed-off-by: Jacek Caban <jacek at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/ntdll/unix/signal_arm.c    | 8 ++++++++
 dlls/ntdll/unix/signal_arm64.c  | 8 ++++++++
 dlls/ntdll/unix/signal_i386.c   | 8 ++++++++
 dlls/ntdll/unix/signal_x86_64.c | 8 ++++++++
 include/wine/unixlib.h          | 2 ++
 5 files changed, 34 insertions(+)

diff --git a/dlls/ntdll/unix/signal_arm.c b/dlls/ntdll/unix/signal_arm.c
index ebc08984adf..2b25fb11caa 100644
--- a/dlls/ntdll/unix/signal_arm.c
+++ b/dlls/ntdll/unix/signal_arm.c
@@ -700,6 +700,14 @@ NTSTATUS WINAPI KeUserModeCallback( ULONG id, const void *args, ULONG len, void
 {
     struct user_callback_frame callback_frame = { { 0 }, ret_ptr, ret_len };
 
+    /* if we have no syscall frame, call the callback directly */
+    if ((char *)&callback_frame < (char *)ntdll_get_thread_data()->kernel_stack ||
+        (char *)&callback_frame > (char *)arm_thread_data()->syscall_frame)
+    {
+        NTSTATUS (WINAPI *func)(const void *, ULONG) = ((void **)NtCurrentTeb()->Peb->KernelCallbackTable)[id];
+        return func( args, len );
+    }
+
     if ((char *)ntdll_get_thread_data()->kernel_stack + min_kernel_stack > (char *)&callback_frame)
         return STATUS_STACK_OVERFLOW;
 
diff --git a/dlls/ntdll/unix/signal_arm64.c b/dlls/ntdll/unix/signal_arm64.c
index f2612412366..3f62927e482 100644
--- a/dlls/ntdll/unix/signal_arm64.c
+++ b/dlls/ntdll/unix/signal_arm64.c
@@ -738,6 +738,14 @@ NTSTATUS WINAPI KeUserModeCallback( ULONG id, const void *args, ULONG len, void
 {
     struct user_callback_frame callback_frame = { {{ 0 }}, ret_ptr, ret_len };
 
+    /* if we have no syscall frame, call the callback directly */
+    if ((char *)&callback_frame < (char *)ntdll_get_thread_data()->kernel_stack ||
+        (char *)&callback_frame > (char *)arm64_thread_data()->syscall_frame)
+    {
+        NTSTATUS (WINAPI *func)(const void *, ULONG) = ((void **)NtCurrentTeb()->Peb->KernelCallbackTable)[id];
+        return func( args, len );
+    }
+
     if ((char *)ntdll_get_thread_data()->kernel_stack + min_kernel_stack > (char *)&callback_frame)
         return STATUS_STACK_OVERFLOW;
 
diff --git a/dlls/ntdll/unix/signal_i386.c b/dlls/ntdll/unix/signal_i386.c
index bf3abc1a587..6bb5649e2b5 100644
--- a/dlls/ntdll/unix/signal_i386.c
+++ b/dlls/ntdll/unix/signal_i386.c
@@ -1569,6 +1569,14 @@ NTSTATUS WINAPI KeUserModeCallback( ULONG id, const void *args, ULONG len, void
 {
     struct user_callback_frame callback_frame = { { 0 }, ret_ptr, ret_len };
 
+    /* if we have no syscall frame, call the callback directly */
+    if ((char *)&callback_frame < (char *)ntdll_get_thread_data()->kernel_stack ||
+        (char *)&callback_frame > (char *)x86_thread_data()->syscall_frame)
+    {
+        NTSTATUS (WINAPI *func)(const void *, ULONG) = ((void **)NtCurrentTeb()->Peb->KernelCallbackTable)[id];
+        return func( args, len );
+    }
+
     if ((char *)ntdll_get_thread_data()->kernel_stack + min_kernel_stack > (char *)&callback_frame)
         return STATUS_STACK_OVERFLOW;
 
diff --git a/dlls/ntdll/unix/signal_x86_64.c b/dlls/ntdll/unix/signal_x86_64.c
index d32e38875a4..46dfa0c94c1 100644
--- a/dlls/ntdll/unix/signal_x86_64.c
+++ b/dlls/ntdll/unix/signal_x86_64.c
@@ -2293,6 +2293,14 @@ NTSTATUS WINAPI KeUserModeCallback( ULONG id, const void *args, ULONG len, void
 {
     struct user_callback_frame callback_frame = { { 0 }, ret_ptr, ret_len };
 
+    /* if we have no syscall frame, call the callback directly */
+    if ((char *)&callback_frame < (char *)ntdll_get_thread_data()->kernel_stack ||
+        (char *)&callback_frame > (char *)amd64_thread_data()->syscall_frame)
+    {
+        NTSTATUS (WINAPI *func)(const void *, ULONG) = ((void **)NtCurrentTeb()->Peb->KernelCallbackTable)[id];
+        return func( args, len );
+    }
+
     if ((char *)ntdll_get_thread_data()->kernel_stack + min_kernel_stack > (char *)&callback_frame)
         return STATUS_STACK_OVERFLOW;
 
diff --git a/include/wine/unixlib.h b/include/wine/unixlib.h
index 942eb3cfd9c..a7cfb8f6cab 100644
--- a/include/wine/unixlib.h
+++ b/include/wine/unixlib.h
@@ -80,6 +80,8 @@ extern void ntdll_set_exception_jmp_buf( __wine_jmp_buf *jmp );
          } \
     } while (0);
 
+NTSTATUS WINAPI KeUserModeCallback( ULONG id, const void *args, ULONG len, void **ret_ptr, ULONG *ret_len );
+
 /* wide char string functions */
 
 static inline size_t ntdll_wcslen( const WCHAR *str )




More information about the wine-cvs mailing list