https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=80d7b4f2f8353911c6f96dc8559cf8694ad3913f

commit 80d7b4f2f8353911c6f96dc8559cf8694ad3913f
Author: Takashi Yano <[email protected]>
Date:   Sat Jan 3 21:53:36 2026 +0900

    Cygwin: flock: Do not lock fdtab in create_lock_in_parent()
    
    Otherwise, a deadlock can occur if the child process attempts to
    lock a file while the parent process is closing the same file, which
    is already locked. The deadlock mechanism is as follows.
    
    When the child process attempts to lock a file, it notifies the parent
    process by calling CreateRemoteThread(), which creates a remote thread
    in the parent. That thread checks whether the file being locked is
    currently opened in the parent. During the operation, cygheap->fdtab
    is temporarily locked in order to enumerate the file descriptors.
    
    However, if the parent process is closing the same file at that moment,
    it also locks fdtab via cygheap_fdget cfd(fd, true) in __close().
    If the parent acquires th fdtab lock first, it proceeds to call
    del_my_locks(), which attempts to lock the inode in inode_t:get().
    
    At this point, the inode is already locked in the child,
    so the parent waits for the child to release the inode. Meanwhile,
    the child is waiting to acquire the fdtab lock, which is still held
    by the parent. As a result, the parent and child become deadlocked.
    
    There are two options to fix the deadlock: eather avoid locking fdtab
    in __close(), or avoid locking fdtab in create_lock_in_parent().
    The latter is safer than the former because __close() calls release(),
    which modifies the fdtab contents, while cygheap_fdenum only reads
    them. Therefore, to resolve the issue, this patch removes the fdtab
    lock from create_lock_in_parent().
    
    Addresses: https://cygwin.com/pipermail/cygwin/2025-December/259187.html
    Fixes: dbf576fd8614 ("(create_lock_in_parent): New thread function to 
create lockf_t structure in parent process.")
    Reported-by: Nahor <[email protected]>
    Reviewed-by: Corinna Vinschen <[email protected]>
    Signed-off-by: Takashi Yano <[email protected]>

Diff:
---
 winsup/cygwin/flock.cc | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/winsup/cygwin/flock.cc b/winsup/cygwin/flock.cc
index ee79af3c9..221501d65 100644
--- a/winsup/cygwin/flock.cc
+++ b/winsup/cygwin/flock.cc
@@ -692,7 +692,7 @@ create_lock_in_parent (PVOID param)
   /* Check if we have an open file handle with the same unique id. */
   {
     cnt = 0;
-    cygheap_fdenum cfd (true);
+    cygheap_fdenum cfd (false);
     while (cfd.next () >= 0)
       if (cfd->get_unique_id () == newlock.lf_id && ++cnt > 0)
        break;

Reply via email to