From 27b841faf8421590677b2a4d02a10163437c147a Mon Sep 17 00:00:00 2001 From: Bill Zissimopoulos Date: Wed, 5 Oct 2016 14:55:37 -0700 Subject: [PATCH] sys: FspFileNodeOpen: refine main file vs stream sharing violations --- src/sys/file.c | 41 +++++++++++++---- tst/winfsp-tests/stream-tests.c | 80 +++++++++++++++++++++++++++++++++ 2 files changed, 113 insertions(+), 8 deletions(-) diff --git a/src/sys/file.c b/src/sys/file.c index 52bf81f0..97cb10c9 100644 --- a/src/sys/file.c +++ b/src/sys/file.c @@ -479,9 +479,15 @@ FSP_FILE_NODE *FspFileNodeOpen(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject, goto exit; } + /* + * Sharing violations between main file and streams were determined + * through experimentation with NTFS. They may be wrong! + */ if (0 < FileNode->MainFileNode->MainFileDenyDeleteCount) { - if (FlagOn(GrantedAccess, DELETE)) + if (!FlagOn(ShareAccess, FILE_SHARE_DELETE) && + FlagOn(GrantedAccess, + FILE_EXECUTE | FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA | DELETE)) { Result = STATUS_SHARING_VIOLATION; goto exit; @@ -522,7 +528,10 @@ FSP_FILE_NODE *FspFileNodeOpen(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject, goto exit; } - /* if this is a main file check whether there is a named stream that denies delete */ + /* + * Sharing violations between main file and streams were determined + * through experimentation with NTFS. They may be wrong! + */ if (0 < OpenedFileNode->StreamDenyDeleteCount) { /* we must be the main file! */ @@ -565,11 +574,19 @@ FSP_FILE_NODE *FspFileNodeOpen(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject, * We also updated OpenedFileNode->ShareAccess in IoSetShareAccess/IoCheckShareAccess. */ - if (FileObject->DeleteAccess && !FileObject->SharedDelete) + /* + * Sharing violations between main file and streams were determined + * through experimentation with NTFS. They may be wrong! + */ + if (0 == OpenedFileNode->MainFileNode) { - if (0 == OpenedFileNode->MainFileNode) + if (FileObject->DeleteAccess) OpenedFileNode->MainFileDenyDeleteCount++; - else + } + else + { + if ((FileObject->ReadAccess || FileObject->WriteAccess || FileObject->DeleteAccess) && + !FileObject->SharedDelete) OpenedFileNode->MainFileNode->StreamDenyDeleteCount++; } @@ -651,11 +668,19 @@ VOID FspFileNodeCleanupComplete(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject FspFsvolDeviceLockContextTable(FsvolDeviceObject); - if (FileObject->DeleteAccess && !FileObject->SharedDelete) + /* + * Sharing violations between main file and streams were determined + * through experimentation with NTFS. They may be wrong! + */ + if (0 == FileNode->MainFileNode) { - if (0 == FileNode->MainFileNode) + if (FileObject->DeleteAccess) FileNode->MainFileDenyDeleteCount--; - else + } + else + { + if ((FileObject->ReadAccess || FileObject->WriteAccess || FileObject->DeleteAccess) && + !FileObject->SharedDelete) FileNode->MainFileNode->StreamDenyDeleteCount--; } diff --git a/tst/winfsp-tests/stream-tests.c b/tst/winfsp-tests/stream-tests.c index f64e59c4..d9fa2443 100644 --- a/tst/winfsp-tests/stream-tests.c +++ b/tst/winfsp-tests/stream-tests.c @@ -486,6 +486,16 @@ static void stream_create_share_dotest(ULONG Flags, PWSTR Prefix) StringCbPrintfW(FilePath, sizeof FilePath, L"%s%s\\file0:foo", Prefix ? L"" : L"\\\\?\\GLOBALROOT", Prefix ? Prefix : memfs_volumename(memfs)); + Handle2 = CreateFileW(FilePath, + FILE_READ_DATA, FILE_SHARE_DELETE, 0, OPEN_EXISTING, 0, 0); + ASSERT(INVALID_HANDLE_VALUE != Handle2); + CloseHandle(Handle2); + + Handle2 = CreateFileW(FilePath, + FILE_WRITE_DATA, FILE_SHARE_DELETE, 0, OPEN_EXISTING, 0, 0); + ASSERT(INVALID_HANDLE_VALUE != Handle2); + CloseHandle(Handle2); + Handle2 = CreateFileW(FilePath, DELETE, FILE_SHARE_DELETE, 0, OPEN_EXISTING, 0, 0); ASSERT(INVALID_HANDLE_VALUE != Handle2); @@ -505,6 +515,16 @@ static void stream_create_share_dotest(ULONG Flags, PWSTR Prefix) StringCbPrintfW(FilePath, sizeof FilePath, L"%s%s\\file0:foo", Prefix ? L"" : L"\\\\?\\GLOBALROOT", Prefix ? Prefix : memfs_volumename(memfs)); + Handle2 = CreateFileW(FilePath, + FILE_READ_DATA, FILE_SHARE_DELETE, 0, OPEN_EXISTING, 0, 0); + ASSERT(INVALID_HANDLE_VALUE != Handle2); + CloseHandle(Handle2); + + Handle2 = CreateFileW(FilePath, + FILE_WRITE_DATA, FILE_SHARE_DELETE, 0, OPEN_EXISTING, 0, 0); + ASSERT(INVALID_HANDLE_VALUE != Handle2); + CloseHandle(Handle2); + Handle2 = CreateFileW(FilePath, DELETE, FILE_SHARE_DELETE, 0, OPEN_EXISTING, 0, 0); ASSERT(INVALID_HANDLE_VALUE != Handle2); @@ -524,6 +544,16 @@ static void stream_create_share_dotest(ULONG Flags, PWSTR Prefix) StringCbPrintfW(FilePath, sizeof FilePath, L"%s%s\\file0:foo", Prefix ? L"" : L"\\\\?\\GLOBALROOT", Prefix ? Prefix : memfs_volumename(memfs)); + Handle2 = CreateFileW(FilePath, + FILE_READ_DATA, 0, 0, OPEN_EXISTING, 0, 0); + ASSERT(INVALID_HANDLE_VALUE == Handle2); + ASSERT(ERROR_SHARING_VIOLATION == GetLastError()); + + Handle2 = CreateFileW(FilePath, + FILE_WRITE_DATA, 0, 0, OPEN_EXISTING, 0, 0); + ASSERT(INVALID_HANDLE_VALUE == Handle2); + ASSERT(ERROR_SHARING_VIOLATION == GetLastError()); + Handle2 = CreateFileW(FilePath, DELETE, 0, 0, OPEN_EXISTING, 0, 0); ASSERT(INVALID_HANDLE_VALUE == Handle2); @@ -543,6 +573,16 @@ static void stream_create_share_dotest(ULONG Flags, PWSTR Prefix) StringCbPrintfW(FilePath, sizeof FilePath, L"%s%s\\file0:foo", Prefix ? L"" : L"\\\\?\\GLOBALROOT", Prefix ? Prefix : memfs_volumename(memfs)); + Handle2 = CreateFileW(FilePath, + FILE_READ_DATA, 0, 0, OPEN_EXISTING, 0, 0); + ASSERT(INVALID_HANDLE_VALUE == Handle2); + ASSERT(ERROR_SHARING_VIOLATION == GetLastError()); + + Handle2 = CreateFileW(FilePath, + FILE_WRITE_DATA, 0, 0, OPEN_EXISTING, 0, 0); + ASSERT(INVALID_HANDLE_VALUE == Handle2); + ASSERT(ERROR_SHARING_VIOLATION == GetLastError()); + Handle2 = CreateFileW(FilePath, DELETE, 0, 0, OPEN_EXISTING, 0, 0); ASSERT(INVALID_HANDLE_VALUE == Handle2); @@ -564,6 +604,16 @@ static void stream_create_share_dotest(ULONG Flags, PWSTR Prefix) StringCbPrintfW(FilePath, sizeof FilePath, L"%s%s\\file0", Prefix ? L"" : L"\\\\?\\GLOBALROOT", Prefix ? Prefix : memfs_volumename(memfs)); + Handle2 = CreateFileW(FilePath, + FILE_READ_DATA, FILE_SHARE_DELETE, 0, OPEN_EXISTING, 0, 0); + ASSERT(INVALID_HANDLE_VALUE != Handle2); + CloseHandle(Handle2); + + Handle2 = CreateFileW(FilePath, + FILE_WRITE_DATA, FILE_SHARE_DELETE, 0, OPEN_EXISTING, 0, 0); + ASSERT(INVALID_HANDLE_VALUE != Handle2); + CloseHandle(Handle2); + Handle2 = CreateFileW(FilePath, DELETE, FILE_SHARE_DELETE, 0, OPEN_EXISTING, 0, 0); ASSERT(INVALID_HANDLE_VALUE != Handle2); @@ -583,6 +633,16 @@ static void stream_create_share_dotest(ULONG Flags, PWSTR Prefix) StringCbPrintfW(FilePath, sizeof FilePath, L"%s%s\\file0", Prefix ? L"" : L"\\\\?\\GLOBALROOT", Prefix ? Prefix : memfs_volumename(memfs)); + Handle2 = CreateFileW(FilePath, + FILE_READ_DATA, 0, 0, OPEN_EXISTING, 0, 0); + ASSERT(INVALID_HANDLE_VALUE != Handle2); + CloseHandle(Handle2); + + Handle2 = CreateFileW(FilePath, + FILE_WRITE_DATA, 0, 0, OPEN_EXISTING, 0, 0); + ASSERT(INVALID_HANDLE_VALUE != Handle2); + CloseHandle(Handle2); + Handle2 = CreateFileW(FilePath, DELETE, 0, 0, OPEN_EXISTING, 0, 0); ASSERT(INVALID_HANDLE_VALUE != Handle2); @@ -602,6 +662,16 @@ static void stream_create_share_dotest(ULONG Flags, PWSTR Prefix) StringCbPrintfW(FilePath, sizeof FilePath, L"%s%s\\file0", Prefix ? L"" : L"\\\\?\\GLOBALROOT", Prefix ? Prefix : memfs_volumename(memfs)); + Handle2 = CreateFileW(FilePath, + FILE_READ_DATA, FILE_SHARE_DELETE, 0, OPEN_EXISTING, 0, 0); + ASSERT(INVALID_HANDLE_VALUE != Handle2); + CloseHandle(Handle2); + + Handle2 = CreateFileW(FilePath, + FILE_WRITE_DATA, FILE_SHARE_DELETE, 0, OPEN_EXISTING, 0, 0); + ASSERT(INVALID_HANDLE_VALUE != Handle2); + CloseHandle(Handle2); + Handle2 = CreateFileW(FilePath, DELETE, FILE_SHARE_DELETE, 0, OPEN_EXISTING, 0, 0); ASSERT(INVALID_HANDLE_VALUE == Handle2); @@ -621,6 +691,16 @@ static void stream_create_share_dotest(ULONG Flags, PWSTR Prefix) StringCbPrintfW(FilePath, sizeof FilePath, L"%s%s\\file0", Prefix ? L"" : L"\\\\?\\GLOBALROOT", Prefix ? Prefix : memfs_volumename(memfs)); + Handle2 = CreateFileW(FilePath, + FILE_READ_DATA, 0, 0, OPEN_EXISTING, 0, 0); + ASSERT(INVALID_HANDLE_VALUE != Handle2); + CloseHandle(Handle2); + + Handle2 = CreateFileW(FilePath, + FILE_WRITE_DATA, 0, 0, OPEN_EXISTING, 0, 0); + ASSERT(INVALID_HANDLE_VALUE != Handle2); + CloseHandle(Handle2); + Handle2 = CreateFileW(FilePath, DELETE, 0, 0, OPEN_EXISTING, 0, 0); ASSERT(INVALID_HANDLE_VALUE == Handle2);