Skip to content

Commit f85d881

Browse files
committed
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: 41de4b6 ("Cygwin: fix up cached DOS file attributes after file creation") Signed-off-by: Corinna Vinschen <[email protected]> (cherry picked from commit 2d81f6e)
1 parent d9ebf01 commit f85d881

File tree

2 files changed

+30
-9
lines changed

2 files changed

+30
-9
lines changed

winsup/cygwin/fhandler/base.cc

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -526,8 +526,9 @@ fhandler_base::open (int flags, mode_t mode)
526526
ULONG file_attributes = 0;
527527
ULONG shared = (get_major () == DEV_TAPE_MAJOR ? 0 : FILE_SHARE_VALID_FLAGS);
528528
ULONG create_disposition;
529+
FILE_BASIC_INFORMATION fbi;
529530
OBJECT_ATTRIBUTES attr;
530-
IO_STATUS_BLOCK io;
531+
IO_STATUS_BLOCK io, io_bi;
531532
NTSTATUS status;
532533
PFILE_FULL_EA_INFORMATION p = NULL;
533534
ULONG plen = 0;
@@ -719,16 +720,32 @@ fhandler_base::open (int flags, mode_t mode)
719720
goto done;
720721
}
721722

722-
if (io.Information == FILE_CREATED)
723-
{
724-
/* Correct file attributes are needed for later use in, e.g. fchmod. */
725-
FILE_BASIC_INFORMATION fbi;
723+
/* Fix up file attributes, they are desperately needed later.
724+
725+
Originally we only did that in the FILE_CREATED case below, but that's
726+
insufficient:
726727
727-
if (!NT_SUCCESS (NtQueryInformationFile (fh, &io, &fbi, sizeof fbi,
728-
FileBasicInformation)))
729-
fbi.FileAttributes = file_attributes | FILE_ATTRIBUTE_ARCHIVE;
730-
pc.file_attributes (fbi.FileAttributes);
728+
If two threads try to create the same file at the same time, it's
729+
possible that path_conv::check returns the file as non-existant, i. e.,
730+
pc.file_attributes () returns INVALID_FILE_ATTRIBUTES, 0xffffffff.
731+
However, one of the NtCreateFile will beat the other, so only one of
732+
them returns with FILE_CREATED.
731733
734+
The other fhandler_base::open() will instead run into the O_TRUNC
735+
conditional (further below), blindly check for the SPARSE attribute
736+
and remove that bit. The result is that the attributes will be
737+
0xfffffdff, i.e., everything but SPARSE. Most annoying is that
738+
pc.isdir() will return TRUE. Hilarity ensues.
739+
740+
Note that we use a different IO_STATUS_BLOCK, so as not to overwrite
741+
io.Information... */
742+
if (!NT_SUCCESS (NtQueryInformationFile (fh, &io_bi, &fbi, sizeof fbi,
743+
FileBasicInformation)))
744+
fbi.FileAttributes = file_attributes | FILE_ATTRIBUTE_ARCHIVE;
745+
pc.file_attributes (fbi.FileAttributes);
746+
747+
if (io.Information == FILE_CREATED)
748+
{
732749
/* Always create files using a NULL SD. Create correct permission bits
733750
afterwards, maintaining the owner and group information just like
734751
chmod. This is done for two reasons.

winsup/cygwin/release/3.6.1

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,7 @@ Fixes:
4141
Addresses: https://cygwin.com/pipermail/cygwin/2025-April/257862.html
4242

4343
- Fix tcsetattr() for console which has been broken sinse cygwin 3.5.5.
44+
45+
- Fix up cached DOS attributes when trying to create the same file in
46+
two (or more) threads/processes concurrently.
47+
Addresses: https://cygwin.com/pipermail/cygwin/2025-April/257871.html

0 commit comments

Comments
 (0)