[newlib-cygwin/main] Cygwin: open: always fix up cached DOS file attributes after NtCreateFile
Corinna Vinschen
corinna@sourceware.org
Tue Apr 8 14:07:21 GMT 2025
https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=2d81f6ebe3dca62d594ed650a885449d66b4a7b8
commit 2d81f6ebe3dca62d594ed650a885449d66b4a7b8
Author: Corinna Vinschen <corinna@vinschen.de>
AuthorDate: Tue Apr 8 15:52:38 2025 +0200
Commit: Corinna Vinschen <corinna@vinschen.de>
CommitDate: Tue Apr 8 16:05:56 2025 +0200
Cygwin: open: always fix up cached DOS file attributes after NtCreateFile
If two threads try to create a file in parallel, only one of them
actually creates the file. So even if both threads first found the
file non-existant, fhandler_base::open will get io.Information ==
FILE_CREATED from NtCreateFile in one thread only, and the thread
just opening the just created file will continue with broken DOS file
attributes.
Make sure to fix up DOS attributes all the time, not only when the file
got created by this thread, but also when it has been just opened.
Fixes: 41de4b6fd735 ("Cygwin: fix up cached DOS file attributes after file creation")
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
Diff:
---
winsup/cygwin/fhandler/base.cc | 35 ++++++++++++++++++++++++++---------
winsup/cygwin/release/3.6.1 | 4 ++++
2 files changed, 30 insertions(+), 9 deletions(-)
diff --git a/winsup/cygwin/fhandler/base.cc b/winsup/cygwin/fhandler/base.cc
index a5d15c706b2c..36d814bf3543 100644
--- a/winsup/cygwin/fhandler/base.cc
+++ b/winsup/cygwin/fhandler/base.cc
@@ -526,8 +526,9 @@ fhandler_base::open (int flags, mode_t mode)
ULONG file_attributes = 0;
ULONG shared = (get_major () == DEV_TAPE_MAJOR ? 0 : FILE_SHARE_VALID_FLAGS);
ULONG create_disposition;
+ FILE_BASIC_INFORMATION fbi;
OBJECT_ATTRIBUTES attr;
- IO_STATUS_BLOCK io;
+ IO_STATUS_BLOCK io, io_bi;
NTSTATUS status;
PFILE_FULL_EA_INFORMATION p = NULL;
ULONG plen = 0;
@@ -719,16 +720,32 @@ fhandler_base::open (int flags, mode_t mode)
goto done;
}
- if (io.Information == FILE_CREATED)
- {
- /* Correct file attributes are needed for later use in, e.g. fchmod. */
- FILE_BASIC_INFORMATION fbi;
+ /* Fix up file attributes, they are desperately needed later.
+
+ Originally we only did that in the FILE_CREATED case below, but that's
+ insufficient:
- if (!NT_SUCCESS (NtQueryInformationFile (fh, &io, &fbi, sizeof fbi,
- FileBasicInformation)))
- fbi.FileAttributes = file_attributes | FILE_ATTRIBUTE_ARCHIVE;
- pc.file_attributes (fbi.FileAttributes);
+ If two threads try to create the same file at the same time, it's
+ possible that path_conv::check returns the file as non-existant, i. e.,
+ pc.file_attributes () returns INVALID_FILE_ATTRIBUTES, 0xffffffff.
+ However, one of the NtCreateFile will beat the other, so only one of
+ them returns with FILE_CREATED.
+ The other fhandler_base::open() will instead run into the O_TRUNC
+ conditional (further below), blindly check for the SPARSE attribute
+ and remove that bit. The result is that the attributes will be
+ 0xfffffdff, i.e., everything but SPARSE. Most annoying is that
+ pc.isdir() will return TRUE. Hilarity ensues.
+
+ Note that we use a different IO_STATUS_BLOCK, so as not to overwrite
+ io.Information... */
+ if (!NT_SUCCESS (NtQueryInformationFile (fh, &io_bi, &fbi, sizeof fbi,
+ FileBasicInformation)))
+ fbi.FileAttributes = file_attributes | FILE_ATTRIBUTE_ARCHIVE;
+ pc.file_attributes (fbi.FileAttributes);
+
+ if (io.Information == FILE_CREATED)
+ {
/* Always create files using a NULL SD. Create correct permission bits
afterwards, maintaining the owner and group information just like
chmod. This is done for two reasons.
diff --git a/winsup/cygwin/release/3.6.1 b/winsup/cygwin/release/3.6.1
index e1bdd17271a2..15eaf488421c 100644
--- a/winsup/cygwin/release/3.6.1
+++ b/winsup/cygwin/release/3.6.1
@@ -41,3 +41,7 @@ Fixes:
Addresses: https://cygwin.com/pipermail/cygwin/2025-April/257862.html
- Fix tcsetattr() for console which has been broken sinse cygwin 3.5.5.
+
+- Fix up cached DOS attributes when trying to create the same file in
+ two (or more) threads/processes concurrently.
+ Addresses: https://cygwin.com/pipermail/cygwin/2025-April/257871.html
More information about the Cygwin-cvs
mailing list