diff --git a/build/VStudio/launcher/launchctl.vcxproj b/build/VStudio/launcher/launchctl.vcxproj index f8912642..cb72c6e0 100644 --- a/build/VStudio/launcher/launchctl.vcxproj +++ b/build/VStudio/launcher/launchctl.vcxproj @@ -105,6 +105,7 @@ false Default MultiThreaded + /Gs16384 %(AdditionalOptions) Console @@ -123,6 +124,7 @@ false Default MultiThreaded + /Gs16384 %(AdditionalOptions) Console @@ -142,6 +144,7 @@ ..\..\..\src;..\..\..\inc false MultiThreaded + /Gs16384 %(AdditionalOptions) Console @@ -163,6 +166,7 @@ ..\..\..\src;..\..\..\inc false MultiThreaded + /Gs16384 %(AdditionalOptions) Console diff --git a/build/VStudio/launcher/launcher.vcxproj b/build/VStudio/launcher/launcher.vcxproj index e687d74a..af1c1e54 100644 --- a/build/VStudio/launcher/launcher.vcxproj +++ b/build/VStudio/launcher/launcher.vcxproj @@ -105,6 +105,7 @@ Default false MultiThreaded + /Gs16384 %(AdditionalOptions) Console @@ -124,6 +125,7 @@ Default false MultiThreaded + /Gs16384 %(AdditionalOptions) Console @@ -144,6 +146,7 @@ ..\..\..\src;..\..\..\inc false MultiThreaded + /Gs16384 %(AdditionalOptions) Console @@ -166,6 +169,7 @@ ..\..\..\src;..\..\..\inc false MultiThreaded + /Gs16384 %(AdditionalOptions) Console diff --git a/build/VStudio/winfsp_dll.vcxproj b/build/VStudio/winfsp_dll.vcxproj index d7e697da..8b8dc2ac 100644 --- a/build/VStudio/winfsp_dll.vcxproj +++ b/build/VStudio/winfsp_dll.vcxproj @@ -173,6 +173,7 @@ copy /b $(OutDir)fuse-$(PlatformTarget).pc + %(FullPath) $(OutDir)fuse-$(Platfor MultiThreaded Default false + /Gs16384 %(AdditionalOptions) Windows @@ -198,6 +199,7 @@ copy /b $(OutDir)fuse-$(PlatformTarget).pc + %(FullPath) $(OutDir)fuse-$(Platfor MultiThreaded Default false + /Gs16384 %(AdditionalOptions) Windows @@ -224,6 +226,7 @@ copy /b $(OutDir)fuse-$(PlatformTarget).pc + %(FullPath) $(OutDir)fuse-$(Platfor ..\..\src;..\..\inc MultiThreaded false + /Gs16384 %(AdditionalOptions) Windows @@ -252,6 +255,7 @@ copy /b $(OutDir)fuse-$(PlatformTarget).pc + %(FullPath) $(OutDir)fuse-$(Platfor ..\..\src;..\..\inc MultiThreaded false + /Gs16384 %(AdditionalOptions) Windows diff --git a/inc/winfsp/fsctl.h b/inc/winfsp/fsctl.h index 7dfbc13c..d54c7fcc 100644 --- a/inc/winfsp/fsctl.h +++ b/inc/winfsp/fsctl.h @@ -63,6 +63,7 @@ extern const __declspec(selectany) GUID FspFsvrtDeviceClassGuid = #define FSP_FSCTL_TRANSACT_REQ_SIZEMAX (4096 - 64) /* 64: size for internal request header */ #define FSP_FSCTL_TRANSACT_RSP_SIZEMAX (4096 - 64) /* symmetry! */ +#define FSP_FSCTL_TRANSACT_REQ_BUFFER_SIZEMAX (FSP_FSCTL_TRANSACT_REQ_SIZEMAX - sizeof(FSP_FSCTL_TRANSACT_REQ)) #define FSP_FSCTL_TRANSACT_RSP_BUFFER_SIZEMAX (FSP_FSCTL_TRANSACT_RSP_SIZEMAX - sizeof(FSP_FSCTL_TRANSACT_RSP)) #define FSP_FSCTL_TRANSACT_BATCH_BUFFER_SIZEMIN 16384 #define FSP_FSCTL_TRANSACT_BUFFER_SIZEMIN FSP_FSCTL_TRANSACT_REQ_SIZEMAX diff --git a/src/dll/fsop.c b/src/dll/fsop.c index ff6a09a3..f3e11cf0 100644 --- a/src/dll/fsop.c +++ b/src/dll/fsop.c @@ -1064,9 +1064,7 @@ FSP_API NTSTATUS FspFileSystemResolveReparsePoints(FSP_FILE_SYSTEM *FileSystem, union { REPARSE_DATA_BUFFER V; - UINT8 B[FIELD_OFFSET(REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) + - /* assumption: the substitute and print paths fit in the same buffer */ - FSP_FSCTL_TRANSACT_PATH_SIZEMAX]; + UINT8 B[FSP_FSCTL_TRANSACT_RSP_BUFFER_SIZEMAX]; } ReparseDataBuf; PREPARSE_DATA_BUFFER ReparseData = &ReparseDataBuf.V; SIZE_T Size, MaxTries = 32; @@ -1151,7 +1149,7 @@ FSP_API NTSTATUS FspFileSystemResolveReparsePoints(FSP_FILE_SYSTEM *FileSystem, if (IO_REPARSE_TAG_SYMLINK == ReparseData->ReparseTag) { TargetLink = ReparseData->SymbolicLinkReparseBuffer.PathBuffer + - ReparseData->SymbolicLinkReparseBuffer.SubstituteNameOffset; + ReparseData->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(WCHAR); Size = ReparseData->SymbolicLinkReparseBuffer.SubstituteNameLength; } else diff --git a/src/shared/minimal.h b/src/shared/minimal.h index 3499d4d7..d0bfdd7a 100644 --- a/src/shared/minimal.h +++ b/src/shared/minimal.h @@ -26,6 +26,7 @@ * - "C/C++ > Code Generation > Basic Runtime Checks" must be set to "Default" * - "C/C++ > Code Generation > Runtime Library" must be set to "Multi-threaded (/MT)". * - "C/C++ > Code Generation > Security Check" must be disabled (/GS-). + * - "C/C++ > Command Line > Additional Options" add "/Gs16384" to disable __chkstk probes. * - "Linker > Input > Ignore All Default Libraries" must be "Yes". * * diff --git a/src/sys/fsctl.c b/src/sys/fsctl.c index 86fe7839..62da25ec 100644 --- a/src/sys/fsctl.c +++ b/src/sys/fsctl.c @@ -118,8 +118,8 @@ static NTSTATUS FspFsvolFileSystemControlReparsePoint( if (IsWrite) { if (0 == InputBuffer || 0 == InputBufferLength || - FSP_FSCTL_TRANSACT_REQ_SIZEMAX - FIELD_OFFSET(FSP_FSCTL_TRANSACT_REQ, Buffer) - - (FileNode->FileName.Length + sizeof(WCHAR)) < InputBufferLength) + FSP_FSCTL_TRANSACT_REQ_BUFFER_SIZEMAX - (FileNode->FileName.Length + sizeof(WCHAR)) < + InputBufferLength) return STATUS_INVALID_PARAMETER; Result = FsRtlValidateReparsePointBuffer(InputBufferLength, InputBuffer); @@ -134,9 +134,9 @@ static NTSTATUS FspFsvolFileSystemControlReparsePoint( if (FsvolDeviceExtension->VolumeParams.ReparsePointsAccessCheck) { if (KernelMode != Irp->RequestorMode && - SeSinglePrivilegeCheck(RtlConvertLongToLuid(SE_CREATE_SYMBOLIC_LINK_PRIVILEGE), + !SeSinglePrivilegeCheck(RtlConvertLongToLuid(SE_CREATE_SYMBOLIC_LINK_PRIVILEGE), UserMode)) - return STATUS_ACCESS_DENIED; + return STATUS_PRIVILEGE_NOT_HELD; } /* determine if target resides on same device as link (convenience for user mode) */ diff --git a/tst/memfs/memfs.cpp b/tst/memfs/memfs.cpp index 25d6a28d..092a23f3 100644 --- a/tst/memfs/memfs.cpp +++ b/tst/memfs/memfs.cpp @@ -1153,6 +1153,7 @@ NTSTATUS MemfsCreate( VolumeParams.UnicodeOnDisk = 1; VolumeParams.PersistentAcls = 1; VolumeParams.ReparsePoints = 1; + VolumeParams.ReparsePointsAccessCheck = 1; if (0 != VolumePrefix) wcscpy_s(VolumeParams.Prefix, sizeof VolumeParams.Prefix / sizeof(WCHAR), VolumePrefix); diff --git a/tst/winfsp-tests/reparse-test.c b/tst/winfsp-tests/reparse-test.c index 1c34f16e..58eaceb1 100644 --- a/tst/winfsp-tests/reparse-test.c +++ b/tst/winfsp-tests/reparse-test.c @@ -219,8 +219,89 @@ void reparse_nfs_test(void) } } +static void reparse_symlink_dotest(ULONG Flags, PWSTR Prefix, ULONG FileInfoTimeout) +{ + void *memfs = memfs_start_ex(Flags, FileInfoTimeout); + + HANDLE Handle; + BOOL Success; + WCHAR FilePath[MAX_PATH], LinkPath[MAX_PATH]; + PUINT8 NameInfoBuf[sizeof(FILE_NAME_INFO) + MAX_PATH]; + PFILE_NAME_INFO PNameInfo = (PVOID)NameInfoBuf; + + StringCbPrintfW(FilePath, sizeof FilePath, L"%s%s\\file0", + Prefix ? L"" : L"\\\\?\\GLOBALROOT", Prefix ? Prefix : memfs_volumename(memfs)); + + StringCbPrintfW(LinkPath, sizeof LinkPath, L"%s%s\\link0", + Prefix ? L"" : L"\\\\?\\GLOBALROOT", Prefix ? Prefix : memfs_volumename(memfs)); + + Success = CreateSymbolicLinkW(LinkPath, FilePath, 0); + if (Success) + { + Handle = CreateFileW(FilePath, + FILE_WRITE_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + 0, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0); + ASSERT(INVALID_HANDLE_VALUE != Handle); + CloseHandle(Handle); + + Handle = CreateFileW(LinkPath, + FILE_WRITE_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + 0, OPEN_EXISTING, 0, 0); + ASSERT(INVALID_HANDLE_VALUE != Handle); + + Success = GetFileInformationByHandleEx(Handle, FileNameInfo, PNameInfo, sizeof NameInfoBuf); + ASSERT(Success); + if (-1 == Flags) + ASSERT(PNameInfo->FileNameLength == wcslen(FilePath + 6) * sizeof(WCHAR)); + else if (0 == Prefix) + ASSERT(PNameInfo->FileNameLength == wcslen(L"\\file0") * sizeof(WCHAR)); + else + ASSERT(PNameInfo->FileNameLength == wcslen(FilePath + 1) * sizeof(WCHAR)); + if (-1 == Flags) + ASSERT(0 == memcmp(FilePath + 6, PNameInfo->FileName, PNameInfo->FileNameLength)); + else if (0 == Prefix) + ASSERT(0 == memcmp(L"\\file0", PNameInfo->FileName, PNameInfo->FileNameLength)); + else + ASSERT(0 == memcmp(FilePath + 1, PNameInfo->FileName, PNameInfo->FileNameLength)); + + CloseHandle(Handle); + + Success = DeleteFileW(LinkPath); + ASSERT(Success); + + Success = DeleteFileW(FilePath); + ASSERT(Success); + } + else + { + ASSERT(ERROR_PRIVILEGE_NOT_HELD == GetLastError()); + FspDebugLog(__FUNCTION__ ": need SE_CREATE_SYMBOLIC_LINK_PRIVILEGE\n"); + } + + memfs_stop(memfs); +} + +void reparse_symlink_test(void) +{ + if (NtfsTests) + { + WCHAR DirBuf[MAX_PATH] = L"\\\\?\\"; + GetCurrentDirectoryW(MAX_PATH - 4, DirBuf + 4); + reparse_symlink_dotest(-1, DirBuf, 0); + } + if (WinFspDiskTests) + { + reparse_symlink_dotest(MemfsDisk, 0, 0); + } + if (WinFspNetTests) + { + reparse_symlink_dotest(MemfsNet, L"\\\\memfs\\share", 0); + } +} + void reparse_tests(void) { TEST(reparse_guid_test); TEST(reparse_nfs_test); + TEST(reparse_symlink_test); }