[PATCH 3/5] ntdll: Remove the source fd from the cache before calling the dup_handle request.
Zebediah Figura
z.figura12 at gmail.com
Mon Mar 22 23:04:28 CDT 2021
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>
---
This fixes the race mentioned here:
<https://www.winehq.org/pipermail/wine-devel/2021-January/179733.html>
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 )
--
2.30.2
More information about the wine-devel
mailing list