Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2021-08-19 17:42:23 +0300
committerCorinna Vinschen <corinna@vinschen.de>2021-08-19 17:42:23 +0300
commit2f05de4dbf9c04008175679a7a7b9e0cf422a2fa (patch)
tree76a971f413da5a522818a6103d1b3feccbe8970f /winsup/cygwin/flock.cc
parentad35bfbb0f527c6217b7cd6070d62785fb7f0025 (diff)
Cygwin: fix all usages of NtQueryDirectoryObject
Due to reports on the Cygwin mailing list[1][2], it was uncovered that a NtOpenDirectoryObject/NtQueryDirectoryObject/NtClose sequence with NtQueryDirectoryObject iterating over the directory entries, one entry per invocation, is not running atomically. If new entries are inserted into the queried directory, other entries may be moved around and then accidentally show up twice while iterating. Change (almost) all NtQueryDirectoryObject invocations so that it gets a really big buffer (64K) and ideally fetches all entries at once. This appears to work atomically. "Almost" all, because fhandler_procsys::readdir can't be easily changed. [1] https://cygwin.com/pipermail/cygwin/2021-July/248998.html [2] https://cygwin.com/pipermail/cygwin/2021-August/249124.html Fixes: e9c8cb31930bd ("(format_proc_partitions): Revamp loop over existing harddisks by scanning the NT native \Device object directory and looking for Harddisk entries.") Fixes: a998dd7055766 ("Implement advisory file locking.") Fixes: 3b7cd74bfdf56 ("(winpids::enum_processes): Fetch Cygwin processes from listing of shared cygwin object dir in the native NT namespace.") Fixes: 0d6f2b0117aa7 ("syscalls.cc (sync_worker): Rewrite using native NT functions.") Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
Diffstat (limited to 'winsup/cygwin/flock.cc')
-rw-r--r--winsup/cygwin/flock.cc52
1 files changed, 32 insertions, 20 deletions
diff --git a/winsup/cygwin/flock.cc b/winsup/cygwin/flock.cc
index ecd2293fa..bd7a16d91 100644
--- a/winsup/cygwin/flock.cc
+++ b/winsup/cygwin/flock.cc
@@ -596,34 +596,46 @@ lockf_t::from_obj_name (inode_t *node, lockf_t **head, const wchar_t *name)
lockf_t *
inode_t::get_all_locks_list ()
{
- struct fdbi
- {
- DIRECTORY_BASIC_INFORMATION dbi;
- WCHAR buf[2][NAME_MAX + 1];
- } f;
+ tmp_pathbuf tp;
ULONG context;
NTSTATUS status;
+ BOOLEAN restart = TRUE;
+ bool last_run = false;
lockf_t newlock, *lock = i_all_lf;
- for (BOOLEAN restart = TRUE;
- NT_SUCCESS (status = NtQueryDirectoryObject (i_dir, &f, sizeof f, TRUE,
- restart, &context, NULL));
- restart = FALSE)
+ PDIRECTORY_BASIC_INFORMATION dbi_buf = (PDIRECTORY_BASIC_INFORMATION)
+ tp.w_get ();
+ while (!last_run)
{
- if (f.dbi.ObjectName.Length != LOCK_OBJ_NAME_LEN * sizeof (WCHAR))
- continue;
- f.dbi.ObjectName.Buffer[LOCK_OBJ_NAME_LEN] = L'\0';
- if (!newlock.from_obj_name (this, &i_all_lf, f.dbi.ObjectName.Buffer))
- continue;
- if (lock - i_all_lf >= MAX_LOCKF_CNT)
+ status = NtQueryDirectoryObject (i_dir, dbi_buf, 65536, FALSE, restart,
+ &context, NULL);
+ if (!NT_SUCCESS (status))
{
- system_printf ("Warning, can't handle more than %d locks per file.",
- MAX_LOCKF_CNT);
+ debug_printf ("NtQueryDirectoryObject, status %y", status);
break;
}
- if (lock > i_all_lf)
- lock[-1].lf_next = lock;
- new (lock++) lockf_t (newlock);
+ if (status != STATUS_MORE_ENTRIES)
+ last_run = true;
+ restart = FALSE;
+ for (PDIRECTORY_BASIC_INFORMATION dbi = dbi_buf;
+ dbi->ObjectName.Length > 0;
+ dbi++)
+ {
+ if (dbi->ObjectName.Length != LOCK_OBJ_NAME_LEN * sizeof (WCHAR))
+ continue;
+ dbi->ObjectName.Buffer[LOCK_OBJ_NAME_LEN] = L'\0';
+ if (!newlock.from_obj_name (this, &i_all_lf, dbi->ObjectName.Buffer))
+ continue;
+ if (lock - i_all_lf >= MAX_LOCKF_CNT)
+ {
+ system_printf ("Warning, can't handle more than %d locks per file.",
+ MAX_LOCKF_CNT);
+ break;
+ }
+ if (lock > i_all_lf)
+ lock[-1].lf_next = lock;
+ new (lock++) lockf_t (newlock);
+ }
}
/* If no lock has been found, return NULL. */
if (lock == i_all_lf)