[prev in list] [next in list] [prev in thread] [next in thread] 

List:       wine-devel
Subject:    [PATCH] ntdll: Throw exception if invalid handle is passed to NtClose and debugger enabled.
From:       Alistair Leslie-Hughes <leslie_alistair () hotmail ! com>
Date:       2018-03-31 9:59:25
Message-ID: SL2P216MB0746B21FB53C7B8B4DB4A0D493A00 () SL2P216MB0746 ! KORP216 ! PROD ! OUTLOOK ! COM
[Download RAW message or body]

From: Sebastian Lackner <sebastian@fds-team.de>

Signed-off-by: Alistair Leslie-Hughes <leslie_alistair@hotmail.com>
---
 dlls/ntdll/om.c              | 26 ++++++++++++++++
 dlls/ntdll/tests/exception.c | 71 +++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 96 insertions(+), 1 deletion(-)

diff --git a/dlls/ntdll/om.c b/dlls/ntdll/om.c
index febe5bd81d..0b56251348 100644
--- a/dlls/ntdll/om.c
+++ b/dlls/ntdll/om.c
@@ -38,6 +38,7 @@
 #include "winternl.h"
 #include "ntdll_misc.h"
 #include "wine/server.h"
+#include "wine/exception.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
 
@@ -377,6 +378,12 @@ NTSTATUS WINAPI NtDuplicateObject( HANDLE source_process, HANDLE \
source,  return ret;
 }
 
+static LONG WINAPI invalid_handle_exception_handler( EXCEPTION_POINTERS *eptr )
+{
+    EXCEPTION_RECORD *rec = eptr->ExceptionRecord;
+    return (rec->ExceptionCode == EXCEPTION_INVALID_HANDLE) ? \
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH; +}
+
 /* Everquest 2 / Pirates of the Burning Sea hooks NtClose, so we need a wrapper */
 NTSTATUS close_handle( HANDLE handle )
 {
@@ -390,6 +397,25 @@ NTSTATUS close_handle( HANDLE handle )
     }
     SERVER_END_REQ;
     if (fd != -1) close( fd );
+
+    if (ret == STATUS_INVALID_HANDLE && handle && \
NtCurrentTeb()->Peb->BeingDebugged) +    {
+        __TRY
+        {
+            EXCEPTION_RECORD record;
+            record.ExceptionCode    = EXCEPTION_INVALID_HANDLE;
+            record.ExceptionFlags   = 0;
+            record.ExceptionRecord  = NULL;
+            record.ExceptionAddress = NULL;
+            record.NumberParameters = 0;
+            RtlRaiseException( &record );
+        }
+        __EXCEPT(invalid_handle_exception_handler)
+        {
+        }
+        __ENDTRY
+    }
+
     return ret;
 }
 
diff --git a/dlls/ntdll/tests/exception.c b/dlls/ntdll/tests/exception.c
index b3592e6e1e..64a23110a5 100644
--- a/dlls/ntdll/tests/exception.c
+++ b/dlls/ntdll/tests/exception.c
@@ -52,6 +52,7 @@ static NTSTATUS  (WINAPI *pNtTerminateProcess)(HANDLE handle, LONG \
exit_code);  static NTSTATUS  (WINAPI *pNtQueryInformationProcess)(HANDLE, \
PROCESSINFOCLASS, PVOID, ULONG, PULONG);  static NTSTATUS  (WINAPI \
*pNtSetInformationProcess)(HANDLE, PROCESSINFOCLASS, PVOID, ULONG);  static BOOL      \
(WINAPI *pIsWow64Process)(HANDLE, PBOOL); +static NTSTATUS  (WINAPI \
*pNtClose)(HANDLE);  
 #if defined(__x86_64__)
 typedef struct
@@ -1091,6 +1092,16 @@ static void test_debugger(void)
 
                     if (stage == 10) continuestatus = DBG_EXCEPTION_NOT_HANDLED;
                 }
+                else if (stage == 11 || stage == 12 || stage == 13)
+                {
+                    ok(de.u.Exception.ExceptionRecord.ExceptionCode == \
EXCEPTION_INVALID_HANDLE, +                       "unexpected exception code %08x, \
expected %08x\n", de.u.Exception.ExceptionRecord.ExceptionCode, +                     \
EXCEPTION_INVALID_HANDLE); +                    \
ok(de.u.Exception.ExceptionRecord.NumberParameters == 0, +                       \
"unexpected number of parameters %d, expected 0\n", \
de.u.Exception.ExceptionRecord.NumberParameters); +
+                    if (stage == 12|| stage == 13) continuestatus = \
DBG_EXCEPTION_NOT_HANDLED; +                }
                 else
                     ok(FALSE, "unexpected stage %x\n", stage);
 
@@ -2895,6 +2906,54 @@ static void test_breakpoint(DWORD numexc)
     pRtlRemoveVectoredExceptionHandler(vectored_handler);
 }
 
+static DWORD invalid_handle_exceptions;
+
+static LONG CALLBACK invalid_handle_vectored_handler(EXCEPTION_POINTERS \
*ExceptionInfo) +{
+    PEXCEPTION_RECORD rec = ExceptionInfo->ExceptionRecord;
+    trace("vect. handler %08x addr:%p\n", rec->ExceptionCode, \
rec->ExceptionAddress); +
+    ok(rec->ExceptionCode == EXCEPTION_INVALID_HANDLE, "ExceptionCode is %08x \
instead of %08x\n", +       rec->ExceptionCode, EXCEPTION_INVALID_HANDLE);
+    ok(rec->NumberParameters == 0, "ExceptionParameters is %d instead of 0\n", \
rec->NumberParameters); +
+    invalid_handle_exceptions++;
+    return (rec->ExceptionCode == EXCEPTION_INVALID_HANDLE) ? \
EXCEPTION_CONTINUE_EXECUTION : EXCEPTION_CONTINUE_SEARCH; +}
+
+static void test_closehandle(DWORD numexc, HANDLE handle)
+{
+    PVOID vectored_handler;
+    NTSTATUS status;
+    DWORD res;
+
+    if (!pRtlAddVectoredExceptionHandler || !pRtlRemoveVectoredExceptionHandler || \
!pRtlRaiseException) +    {
+        skip("RtlAddVectoredExceptionHandler or RtlRemoveVectoredExceptionHandler or \
RtlRaiseException not found\n"); +        return;
+    }
+
+    vectored_handler = pRtlAddVectoredExceptionHandler(TRUE, \
&invalid_handle_vectored_handler); +    ok(vectored_handler != 0, \
"RtlAddVectoredExceptionHandler failed\n"); +
+    invalid_handle_exceptions = 0;
+    res = CloseHandle(handle);
+
+    ok(!res || (is_wow64 && res), "CloseHandle(%p) unexpectedly succeeded\n", \
handle); +    ok(GetLastError() == ERROR_INVALID_HANDLE, "wrong error code %d instead \
of %d\n", +       GetLastError(), ERROR_INVALID_HANDLE);
+    ok(invalid_handle_exceptions == numexc, "CloseHandle generated %d exceptions, \
expected %d\n", +       invalid_handle_exceptions, numexc);
+
+    invalid_handle_exceptions = 0;
+    status = pNtClose(handle);
+    ok(status == STATUS_INVALID_HANDLE || (is_wow64 && status == 0), "NtClose(%p) \
returned status %08x\n", handle, status); +    ok(invalid_handle_exceptions == \
numexc, "NtClose generated %d exceptions, expected %d\n", +       \
invalid_handle_exceptions, numexc); +
+    pRtlRemoveVectoredExceptionHandler(vectored_handler);
+}
+
 static void test_vectored_continue_handler(void)
 {
     PVOID handler1, handler2;
@@ -2949,6 +3008,7 @@ START_TEST(exception)
     pNtGetContextThread  = (void *)GetProcAddress( hntdll, "NtGetContextThread" );
     pNtSetContextThread  = (void *)GetProcAddress( hntdll, "NtSetContextThread" );
     pNtReadVirtualMemory = (void *)GetProcAddress( hntdll, "NtReadVirtualMemory" );
+    pNtClose             = (void *)GetProcAddress( hntdll, "NtClose" );
     pRtlUnwind           = (void *)GetProcAddress( hntdll, "RtlUnwind" );
     pRtlRaiseException   = (void *)GetProcAddress( hntdll, "RtlRaiseException" );
     pRtlCaptureContext   = (void *)GetProcAddress( hntdll, "RtlCaptureContext" );
@@ -2997,6 +3057,7 @@ START_TEST(exception)
         if (pRtlRaiseException)
         {
             test_stage = 1;
+
             run_rtlraiseexception_test(0x12345);
             run_rtlraiseexception_test(EXCEPTION_BREAKPOINT);
             run_rtlraiseexception_test(EXCEPTION_INVALID_HANDLE);
@@ -3004,6 +3065,7 @@ START_TEST(exception)
             run_rtlraiseexception_test(0x12345);
             run_rtlraiseexception_test(EXCEPTION_BREAKPOINT);
             run_rtlraiseexception_test(EXCEPTION_INVALID_HANDLE);
+
             test_stage = 3;
             test_outputdebugstring(0, FALSE);
             test_stage = 4;
@@ -3020,6 +3082,12 @@ START_TEST(exception)
             test_breakpoint(0);
             test_stage = 10;
             test_breakpoint(1);
+            test_stage = 11;
+            test_closehandle(0, (HANDLE)0xdeadbeef);
+            test_stage = 12;
+            test_closehandle(1, (HANDLE)0xdeadbeef);
+            test_stage = 13;
+            test_closehandle(0, 0); /* Special case. */
         }
         else
             skip( "RtlRaiseException not found\n" );
@@ -3036,6 +3104,7 @@ START_TEST(exception)
     test_ripevent(1);
     test_debug_service(1);
     test_breakpoint(1);
+    test_closehandle(0, (HANDLE)0xdeadbeef);
     test_vectored_continue_handler();
     test_debugger();
     test_simd_exceptions();
@@ -3043,7 +3112,6 @@ START_TEST(exception)
     test_dpe_exceptions();
     test_prot_fault();
     test_thread_context();
-
 #elif defined(__x86_64__)
     pRtlAddFunctionTable               = (void *)GetProcAddress( hntdll,
                                                                  \
"RtlAddFunctionTable" ); @@ -3069,6 +3137,7 @@ START_TEST(exception)
     test_ripevent(1);
     test_debug_service(1);
     test_breakpoint(1);
+    test_closehandle(0, (HANDLE)0xdeadbeef);
     test_vectored_continue_handler();
     test_virtual_unwind();
     test___C_specific_handler();
-- 
2.16.2


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic