From 8dee07a1f12682307be07e12a7fd8d5c8ecc1e2b Mon Sep 17 00:00:00 2001 From: Takashi Yano Date: Fri, 15 Nov 2024 21:58:22 +0900 Subject: [PATCH] Cygwin: flock: Fix overlap handling in lf_setlock() and lf_clearlock() Currently, create_lock_obj() can create multiple locks with the same lock range that have different version number. However, lf_setlock() and lf_clearlock() cannot handle this case appropriately. With this patch, make lf_setlock() and lf_clearlock() find overlap again even when ovcase = 1 (lock and overlap have the same lock range). Addresses: https://cygwin.com/pipermail/cygwin/2024-November/256750.html Fixes: 2e560a092c1c ("* flock.cc (LOCK_OBJ_NAME_LEN): Change to accommodate extra lf_ver field.") Reported-by: Sebastian Feld Reviewed-by: Corinna Vinschen Signed-off-by: Takashi Yano --- winsup/cygwin/flock.cc | 31 ++++++++++++++++++------------- winsup/cygwin/release/3.5.5 | 3 +++ 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/winsup/cygwin/flock.cc b/winsup/cygwin/flock.cc index 794e66bd7..b41cba5c7 100644 --- a/winsup/cygwin/flock.cc +++ b/winsup/cygwin/flock.cc @@ -1410,12 +1410,16 @@ lf_setlock (lockf_t *lock, inode_t *node, lockf_t **clean, HANDLE fhdl) */ if (lock_cnt > MAX_LOCKF_CNT - room_for_clearlock) return ENOLCK; + /* Do not create a lock here. It should be done after all + overlaps have been removed. */ lf_wakelock (overlap, fhdl); - overlap->lf_type = lock->lf_type; - overlap->create_lock_obj (); - lock->lf_next = *clean; - *clean = lock; - break; + *prev = overlap->lf_next; + overlap->lf_next = *clean; + *clean = overlap; + /* We may have multiple versions (lf_ver) having same lock range. + Therefore, we need to find overlap repeatedly. (originally, + just 'break' here. */ + continue; case 2: /* overlap contains lock */ /* @@ -1563,10 +1567,16 @@ lf_clearlock (lockf_t *unlock, lockf_t **clean, HANDLE fhdl) switch (ovcase) { case 1: /* overlap == lock */ + case 3: /* lock contains overlap */ *prev = overlap->lf_next; + lf = overlap->lf_next; overlap->lf_next = *clean; *clean = overlap; - break; + first_loop = false; + /* We may have multiple versions (lf_ver) having same lock range. + Therefore, we need to find overlap repeatedly. (originally, + just 'break' here. */ + continue; case 2: /* overlap contains lock: split it */ if (overlap->lf_start == unlock->lf_start) @@ -1582,13 +1592,8 @@ lf_clearlock (lockf_t *unlock, lockf_t **clean, HANDLE fhdl) overlap->lf_next->create_lock_obj (); break; - case 3: /* lock contains overlap */ - *prev = overlap->lf_next; - lf = overlap->lf_next; - overlap->lf_next = *clean; - *clean = overlap; - first_loop = false; - continue; + /* case 3: */ /* lock contains overlap */ + /* Merged into case 1 */ case 4: /* overlap starts before lock */ overlap->lf_end = unlock->lf_start - 1; diff --git a/winsup/cygwin/release/3.5.5 b/winsup/cygwin/release/3.5.5 index 13982632b..b70b91ed8 100644 --- a/winsup/cygwin/release/3.5.5 +++ b/winsup/cygwin/release/3.5.5 @@ -39,3 +39,6 @@ Fixes: - Fix access violation in lf_clearlock() called from flock(). Addresses: https://cygwin.com/pipermail/cygwin/2024-November/256750.html + +- Fix NtCreateEvent() error in create_lock_ob() called from flock(). + Addresses: https://cygwin.com/pipermail/cygwin/2024-November/256750.html -- 2.11.4.GIT