diff --git a/src/sys/create.c b/src/sys/create.c index 0bc61e71..1adc18e2 100644 --- a/src/sys/create.c +++ b/src/sys/create.c @@ -1051,8 +1051,21 @@ NTSTATUS FspFsvolCreateComplete( } /* open the FileNode */ + UINT32 AdditionalGrantedAccess = 0; + switch ((IrpSp->Parameters.Create.Options >> 24) & 0xff) + { + case FILE_OVERWRITE: case FILE_OVERWRITE_IF: + /* Additional granted access for share check. Fixes GitHub issue #364. */ + AdditionalGrantedAccess = FILE_WRITE_DATA; + break; + case FILE_SUPERSEDE: + /* Additional granted access for share check. Fixes GitHub issue #364. */ + AdditionalGrantedAccess = DELETE; + break; + } Result = FspFileNodeOpen(FileNode, FileObject, - Response->Rsp.Create.Opened.GrantedAccess, IrpSp->Parameters.Create.ShareAccess, + Response->Rsp.Create.Opened.GrantedAccess, AdditionalGrantedAccess, + IrpSp->Parameters.Create.ShareAccess, &OpenedFileNode, &SharingViolationReason); if (!NT_SUCCESS(Result)) { diff --git a/src/sys/driver.h b/src/sys/driver.h index bd23ae3d..79536a0a 100644 --- a/src/sys/driver.h +++ b/src/sys/driver.h @@ -1556,7 +1556,7 @@ VOID FspFileNodeReleaseForeign(FSP_FILE_NODE *FileNode) ExReleaseResourceLite(FileNode->Header.Resource); } NTSTATUS FspFileNodeOpen(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject, - UINT32 GrantedAccess, UINT32 ShareAccess, + UINT32 GrantedAccess, UINT32 AdditionalGrantedAccess, UINT32 ShareAccess, FSP_FILE_NODE **POpenedFileNode, PULONG PSharingViolationReason); VOID FspFileNodeCleanup(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject, PULONG PCleanupFlags); VOID FspFileNodeCleanupFlush(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject); diff --git a/src/sys/file.c b/src/sys/file.c index def6c91f..f9024148 100644 --- a/src/sys/file.c +++ b/src/sys/file.c @@ -38,7 +38,7 @@ VOID FspFileNodeSetOwnerF(FSP_FILE_NODE *FileNode, ULONG Flags, PVOID Owner); VOID FspFileNodeReleaseF(FSP_FILE_NODE *FileNode, ULONG Flags); VOID FspFileNodeReleaseOwnerF(FSP_FILE_NODE *FileNode, ULONG Flags, PVOID Owner); NTSTATUS FspFileNodeOpen(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject, - UINT32 GrantedAccess, UINT32 ShareAccess, + UINT32 GrantedAccess, UINT32 AdditionalGrantedAccess, UINT32 ShareAccess, FSP_FILE_NODE **POpenedFileNode, PULONG PSharingViolationReason); VOID FspFileNodeCleanup(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject, PULONG PCleanupFlags); VOID FspFileNodeCleanupFlush(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject); @@ -588,7 +588,7 @@ VOID FspFileNodeReleaseOwnerF(FSP_FILE_NODE *FileNode, ULONG Flags, PVOID Owner) } NTSTATUS FspFileNodeOpen(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject, - UINT32 GrantedAccess, UINT32 ShareAccess, + UINT32 GrantedAccess, UINT32 AdditionalGrantedAccess, UINT32 ShareAccess, FSP_FILE_NODE **POpenedFileNode, PULONG PSharingViolationReason) { /* @@ -711,6 +711,14 @@ NTSTATUS FspFileNodeOpen(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject, } /* share access check */ + if (0 != AdditionalGrantedAccess) + { + /* Additional share check for FILE_OVERWRITE*, FILE_SUPERSEDE. Fixes GitHub issue #364. */ + Result = IoCheckShareAccess(GrantedAccess | AdditionalGrantedAccess, ShareAccess, FileObject, + &OpenedFileNode->ShareAccess, FALSE); + if (!NT_SUCCESS(Result)) + goto exit; + } Result = IoCheckShareAccess(GrantedAccess, ShareAccess, FileObject, &OpenedFileNode->ShareAccess, TRUE); if (!NT_SUCCESS(Result)) diff --git a/tst/winfsp-tests/create-test.c b/tst/winfsp-tests/create-test.c index affdbac2..109e9910 100644 --- a/tst/winfsp-tests/create-test.c +++ b/tst/winfsp-tests/create-test.c @@ -1131,6 +1131,45 @@ void create_share_dotest(ULONG Flags, PWSTR Prefix) ASSERT(ERROR_SHARING_VIOLATION == GetLastError()); CloseHandle(Handle1); + + /* GitHub issue #364 */ + Handle1 = CreateFileW(FilePath, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); + ASSERT(INVALID_HANDLE_VALUE != Handle1); + Handle2 = CreateFileW(FilePath, GENERIC_READ, FILE_SHARE_READ, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); + ASSERT(INVALID_HANDLE_VALUE == Handle2); + ASSERT(ERROR_SHARING_VIOLATION == GetLastError()); + CloseHandle(Handle1); + + /* from winfstest */ + Handle1 = CreateFileW(FilePath, GENERIC_READ, FILE_SHARE_WRITE, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); + ASSERT(INVALID_HANDLE_VALUE != Handle1); + Handle2 = CreateFileW(FilePath, GENERIC_WRITE, FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0); + ASSERT(INVALID_HANDLE_VALUE == Handle2); + ASSERT(ERROR_SHARING_VIOLATION == GetLastError()); + Handle2 = CreateFileW(FilePath, GENERIC_WRITE, FILE_SHARE_READ, 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); + ASSERT(ERROR_SHARING_VIOLATION == GetLastError()); + Handle2 = CreateFileW(FilePath, DELETE, FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0); + ASSERT(INVALID_HANDLE_VALUE == Handle2); + ASSERT(ERROR_SHARING_VIOLATION == GetLastError()); + CloseHandle(Handle1); + + /* from winfstest */ + Handle1 = CreateFileW(FilePath, DELETE, FILE_SHARE_DELETE, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); + ASSERT(INVALID_HANDLE_VALUE != Handle1); + Handle2 = CreateFileW(FilePath, GENERIC_WRITE, FILE_SHARE_DELETE, 0, OPEN_EXISTING, 0, 0); + ASSERT(INVALID_HANDLE_VALUE == Handle2); + ASSERT(ERROR_SHARING_VIOLATION == GetLastError()); + Handle2 = CreateFileW(FilePath, DELETE, FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0); + ASSERT(INVALID_HANDLE_VALUE == Handle2); + ASSERT(ERROR_SHARING_VIOLATION == GetLastError()); + Handle2 = CreateFileW(FilePath, DELETE, FILE_SHARE_DELETE, 0, OPEN_EXISTING, 0, 0); + ASSERT(INVALID_HANDLE_VALUE != Handle2); + CloseHandle(Handle2); + CloseHandle(Handle1); } Handle1 = CreateFileW(FilePath,