Zebediah Figura : ntdll: Remove the source fd from the cache before calling the dup_handle request.

Alexandre Julliard julliard at winehq.org
Tue Mar 23 16:54:31 CDT 2021


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

Author: Zebediah Figura <z.figura12 at gmail.com>
Date:   Mon Mar 22 23:04:28 2021 -0500

ntdll: Remove the source fd from the cache before calling the dup_handle request.

If another thread creates and accesses a file between the dup_handle request and
the call to remove_fd_from_cache(), the file may be allocated to the same handle
number, and that thread will then receive the wrong unix fd. Avoid this race by
invalidating the cache first.

Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/ntdll/unix/server.c | 17 ++++++++++++-----
 1 file changed, 12 insertions(+), 5 deletions(-)

diff --git a/dlls/ntdll/unix/server.c b/dlls/ntdll/unix/server.c
index 1f8cf546977..506cc99e542 100644
--- a/dlls/ntdll/unix/server.c
+++ b/dlls/ntdll/unix/server.c
@@ -1693,6 +1693,7 @@ NTSTATUS WINAPI NtDuplicateObject( HANDLE source_process, HANDLE source, HANDLE
                                    ACCESS_MASK access, ULONG attributes, ULONG options )
 {
     NTSTATUS ret;
+    int fd;
 
     if ((options & DUPLICATE_CLOSE_SOURCE) && source_process != NtCurrentProcess())
     {
@@ -1715,6 +1716,14 @@ NTSTATUS WINAPI NtDuplicateObject( HANDLE source_process, HANDLE source, HANDLE
         return result.dup_handle.status;
     }
 
+    /* always remove the cached fd; if the server request fails we'll just
+     * retrieve it again */
+    if (options & DUPLICATE_CLOSE_SOURCE)
+    {
+        fd = remove_fd_from_cache( source );
+        if (fd != -1) close( fd );
+    }
+
     SERVER_START_REQ( dup_handle )
     {
         req->src_process = wine_server_obj_handle( source_process );
@@ -1726,11 +1735,6 @@ NTSTATUS WINAPI NtDuplicateObject( HANDLE source_process, HANDLE source, HANDLE
         if (!(ret = wine_server_call( req )))
         {
             if (dest) *dest = wine_server_ptr_handle( reply->handle );
-            if (reply->closed && reply->self)
-            {
-                int fd = remove_fd_from_cache( source );
-                if (fd != -1) close( fd );
-            }
         }
     }
     SERVER_END_REQ;
@@ -1745,6 +1749,9 @@ NTSTATUS WINAPI NtClose( HANDLE handle )
 {
     HANDLE port;
     NTSTATUS ret;
+
+    /* always remove the cached fd; if the server request fails we'll just
+     * retrieve it again */
     int fd = remove_fd_from_cache( handle );
 
     SERVER_START_REQ( close_handle )




More information about the wine-cvs mailing list