Compare commits

...
11 Commits
Author SHA1 Message Date
Bill Zissimopoulos fde790d8ea build: version 2026 Beta4 2026-08-03 16:59:55 +03:00
Bill Zissimopoulos f97012ec46 update changelog for 2026 Beta4 2026-08-03 16:58:21 +03:00
Bill Zissimopoulos 43b9a6e222 Merge branch 'pvt-fix674' 2026-07-29 14:54:07 +03:00
Bill Zissimopoulos f41f3afa07 Merge branch 'pvt-ads-fix' 2026-07-28 22:18:06 +03:00
Bill Zissimopoulos d0bd2170bd dll: FspCreateDirectoryFileW: handle trailing backslash
Fixes #674
2026-07-28 19:02:09 +03:00
Bill Zissimopoulos 57e0a24dd0 Merge branch 'pvt-voldelete-fix' 2026-07-28 16:43:54 +03:00
Bill Zissimopoulos 5b53285545 sys: FspMainFileClose: fix issue #680
Instead of closing the main file handle in the dispatcher thread,
close it in a system thread and wait for that close to complete
in an alertable manner. This avoids a deadlock due to the file
system process being forcibly terminated via NtTerminateProcess.
2026-07-28 15:36:48 +03:00
Bill Zissimopoulos 7ee0873f4b sys: FspVolumeDelete: move FspIoqStop prior to VolumeDeleteResource acquisition 2026-07-27 18:40:57 +03:00
Bill Zissimopoulos 97e6d92b5b sys: FspFsvolQueryDirectoryCopy
Correct bounds checking on FSP_FSCTL_DIR_INFO records.
2026-07-27 16:23:45 +03:00
Bill Zissimopoulos a744d6f24c sys: FspFsvolQueryStreamInformationCopy: fix vulnerability reported by Abhinav Agarwal (GitHub @abhinavagarwal07)
Correct bounds checking on FSP_FSCTL_STREAM_INFO records.
2026-07-27 16:19:10 +03:00
Bill Zissimopoulos 1916d9bf06 sys: FspVolumeNotifyWork: fix vulnerability reported by Wencheng Xue (GitHub @panwnvda)
Correct bounds checking on FSP_FSCTL_NOTIFY_INFO records.
2026-07-27 16:16:41 +03:00
9 changed files with 133 additions and 19 deletions
+29
View File
@@ -1,6 +1,35 @@
# Changelog
## v2.2B4 (2026 Beta4)
- [FIX] Fixes vulnerability CVE-2026-3006 reported by Tay Kiat Loong (GitHub: @Owl4444).
- [FIX] Fixes vulnerability CVE-2026-7162 reported by Tay Kiat Loong (GitHub: @Owl4444) and uhg (GitHub: @UltimateHG).
- [FIX] Fixes vulnerability reported by Wencheng Xue (GitHub @panwnvda).
- [FIX] Fixes vulnerability reported by Abhinav Agarwal (GitHub @abhinavagarwal07).
- [FIX] Fixes deadlock during cached writes under memory pressure. See PR #677 for discussion.
- [FIX] Fixes deadlock in the file system notification mechanism with concurrent renames. See fix PR #669 by @yeonsh and test PR #672 by @Maksim-Isakau.
- [FIX] Fixes deadlock when closing named streams while the file system is being forcibly terminated. See issue #680.
- [FIX] Fixes another complicated deadlock when the file system is being forcibly terminated. See issue #682.
- [FIX] The WinFsp Network Provider provides improved shell support for network file systems not managed by the Launcher. See commit f021496.
- [FIX] Fixes a problem with mounting on a directory with a trailing backslash. See issue #674.
- [FUSE] Add FUSE option `FlushOnCleanup`. See PR #614 by @chenjie4255.
- [FUSE] FUSE now respects the `direct_io` flag. See PR #646 by @chenjie4255.
- [FUSE] Add FUSE option `AddWriteEaAccess`. See PR #648 by @chenjie4255.
## v2.2B3 (2026 Beta3)
- [FIX] Fixes vulnerability CVE-2026-3006 discovered by Tay Kiat Loong (GitHub: @Owl4444).
+1 -1
View File
@@ -20,7 +20,7 @@
<MyCanonicalVersion>2.2</MyCanonicalVersion>
<MyProductVersion>2026 Beta3</MyProductVersion>
<MyProductVersion>2026 Beta4</MyProductVersion>
<MyProductStage>Beta</MyProductStage>
<MyCrossCert>CrossCert.cer</MyCrossCert>
+5
View File
@@ -127,6 +127,11 @@ HANDLE FspCreateDirectoryFileW(
Length = GetFullPathNameW(FileName, Length + 1, FullFileName, &FilePart);
if (0 == Length)
goto exit;
if (0 == FilePart)
{
SetLastError(ERROR_INVALID_NAME);
goto exit;
}
FilePartChar = *FilePart;
*FilePart = L'\0';
+2 -1
View File
@@ -179,7 +179,8 @@ static NTSTATUS FspFsvolQueryDirectoryCopy(
{
DirInfoSize = DirInfo->Size;
if (sizeof(FSP_FSCTL_DIR_INFO) > DirInfoSize)
if (sizeof(FSP_FSCTL_DIR_INFO) > DirInfoSize ||
(SIZE_T)(DirInfoEnd - (PUINT8)DirInfo) < DirInfoSize)
{
if (0 == *PDestLen)
return STATUS_NO_MORE_FILES;
+6 -2
View File
@@ -698,14 +698,18 @@ NTSTATUS FspOplockFsctrl(
/* utility: synchronous work queue */
typedef struct
{
KEVENT Event;
LONG RefCount;
PWORKER_THREAD_ROUTINE Routine;
PVOID Context;
KEVENT Event;
WORK_QUEUE_ITEM WorkQueueItem;
} FSP_SYNCHRONOUS_WORK_ITEM;
FSP_SYNCHRONOUS_WORK_ITEM *FspAllocateSynchronousWorkItem(
PWORKER_THREAD_ROUTINE Routine, PVOID Context);
VOID FspInitializeSynchronousWorkItem(FSP_SYNCHRONOUS_WORK_ITEM *SynchronousWorkItem,
PWORKER_THREAD_ROUTINE Routine, PVOID Context);
VOID FspExecuteSynchronousWorkItem(FSP_SYNCHRONOUS_WORK_ITEM *SynchronousWorkItem);
NTSTATUS FspExecuteSynchronousWorkItem(FSP_SYNCHRONOUS_WORK_ITEM *SynchronousWorkItem,
BOOLEAN Alertable);
/* utility: delayed work queue */
typedef struct
+33 -3
View File
@@ -121,6 +121,7 @@ NTSTATUS FspMainFileOpen(
NTSTATUS FspMainFileClose(
HANDLE MainFileHandle,
PFILE_OBJECT MainFileObject);
static WORKER_THREAD_ROUTINE FspMainFileCloseSynchronousWork;
VOID FspFileNodeOplockPrepare(PVOID Context, PIRP Irp);
VOID FspFileNodeOplockComplete(PVOID Context, PIRP Irp);
@@ -183,6 +184,7 @@ VOID FspFileNodeOplockComplete(PVOID Context, PIRP Irp);
#pragma alloc_text(PAGE, FspFileDescSetDirectoryMarker)
#pragma alloc_text(PAGE, FspMainFileOpen)
#pragma alloc_text(PAGE, FspMainFileClose)
#pragma alloc_text(PAGE, FspMainFileCloseSynchronousWork)
#pragma alloc_text(PAGE, FspFileNodeOplockPrepare)
#pragma alloc_text(PAGE, FspFileNodeOplockComplete)
#endif
@@ -2803,14 +2805,42 @@ NTSTATUS FspMainFileClose(
if (0 != MainFileHandle)
{
Result = ObCloseHandle(MainFileHandle, KernelMode);
if (!NT_SUCCESS(Result))
DEBUGLOG("ObCloseHandle() = %s", NtStatusSym(Result));
FSP_SYNCHRONOUS_WORK_ITEM *WorkItem;
WorkItem = DEBUGTEST(90) ?
FspAllocateSynchronousWorkItem(FspMainFileCloseSynchronousWork, MainFileHandle) :
0;
if (0 != WorkItem)
/*
* Fix issue #680:
* Instead of closing the main file handle in this thread, close it in a system thread
* and wait for that close to complete in an alertable manner. This avoids a deadlock
* due to the file system process being forcibly terminated via NtTerminateProcess.
*/
Result = FspExecuteSynchronousWorkItem(WorkItem, TRUE);
else
/*
* Best effort: Close the main file handle in this thread.
* Small chance of deadlock if someone is killing our file system.
*/
FspMainFileCloseSynchronousWork(MainFileHandle);
}
return Result;
}
static VOID FspMainFileCloseSynchronousWork(PVOID Context)
{
PAGED_CODE();
HANDLE MainFileHandle = Context;
NTSTATUS Result;
Result = ObCloseHandle(MainFileHandle, KernelMode);
if (!NT_SUCCESS(Result))
DEBUGLOG("ObCloseHandle() = %s", NtStatusSym(Result));
}
VOID FspFileNodeOplockPrepare(PVOID Context, PIRP Irp)
{
PAGED_CODE();
+2 -1
View File
@@ -669,7 +669,8 @@ static NTSTATUS FspFsvolQueryStreamInformationCopy(
{
StreamInfoSize = StreamInfo->Size;
if (sizeof(FSP_FSCTL_STREAM_INFO) > StreamInfoSize)
if (sizeof(FSP_FSCTL_STREAM_INFO) > StreamInfoSize ||
(SIZE_T)(StreamInfoEnd - (PUINT8)StreamInfo) < StreamInfoSize)
break;
StreamNameLength = StreamInfoSize - sizeof(FSP_FSCTL_STREAM_INFO) + STREAM_EXTRA_LENGTH;
+47 -7
View File
@@ -115,9 +115,12 @@ NTSTATUS FspOplockFsctrl(
POPLOCK Oplock,
PIRP Irp,
ULONG OpenCount);
FSP_SYNCHRONOUS_WORK_ITEM *FspAllocateSynchronousWorkItem(
PWORKER_THREAD_ROUTINE Routine, PVOID Context);
VOID FspInitializeSynchronousWorkItem(FSP_SYNCHRONOUS_WORK_ITEM *SynchronousWorkItem,
PWORKER_THREAD_ROUTINE Routine, PVOID Context);
VOID FspExecuteSynchronousWorkItem(FSP_SYNCHRONOUS_WORK_ITEM *SynchronousWorkItem);
NTSTATUS FspExecuteSynchronousWorkItem(FSP_SYNCHRONOUS_WORK_ITEM *SynchronousWorkItem,
BOOLEAN Alertable);
static WORKER_THREAD_ROUTINE FspExecuteSynchronousWorkItemRoutine;
VOID FspInitializeDelayedWorkItem(FSP_DELAYED_WORK_ITEM *DelayedWorkItem,
PWORKER_THREAD_ROUTINE Routine, PVOID Context);
@@ -167,6 +170,7 @@ LONG FspCompareUnicodeString(
#pragma alloc_text(PAGE, FspCheckOplock)
#pragma alloc_text(PAGE, FspCheckOplockEx)
#pragma alloc_text(PAGE, FspOplockFsctrl)
#pragma alloc_text(PAGE, FspAllocateSynchronousWorkItem)
#pragma alloc_text(PAGE, FspInitializeSynchronousWorkItem)
#pragma alloc_text(PAGE, FspExecuteSynchronousWorkItem)
#pragma alloc_text(PAGE, FspExecuteSynchronousWorkItemRoutine)
@@ -1123,27 +1127,56 @@ NTSTATUS FspOplockFsctrl(
return Result;
}
FSP_SYNCHRONOUS_WORK_ITEM *FspAllocateSynchronousWorkItem(
PWORKER_THREAD_ROUTINE Routine, PVOID Context)
{
PAGED_CODE();
FSP_SYNCHRONOUS_WORK_ITEM *SynchronousWorkItem;
SynchronousWorkItem = FspAllocNonPaged(sizeof *SynchronousWorkItem);
if (0 != SynchronousWorkItem)
{
FspInitializeSynchronousWorkItem(SynchronousWorkItem, Routine, Context);
SynchronousWorkItem->RefCount = 2; /* make it refcounted */
}
return SynchronousWorkItem;
}
VOID FspInitializeSynchronousWorkItem(FSP_SYNCHRONOUS_WORK_ITEM *SynchronousWorkItem,
PWORKER_THREAD_ROUTINE Routine, PVOID Context)
{
PAGED_CODE();
KeInitializeEvent(&SynchronousWorkItem->Event, NotificationEvent, FALSE);
SynchronousWorkItem->RefCount = 0; /* initialize as non-refcounted */
SynchronousWorkItem->Routine = Routine;
SynchronousWorkItem->Context = Context;
KeInitializeEvent(&SynchronousWorkItem->Event, NotificationEvent, FALSE);
ExInitializeWorkItem(&SynchronousWorkItem->WorkQueueItem,
FspExecuteSynchronousWorkItemRoutine, SynchronousWorkItem);
}
VOID FspExecuteSynchronousWorkItem(FSP_SYNCHRONOUS_WORK_ITEM *SynchronousWorkItem)
NTSTATUS FspExecuteSynchronousWorkItem(FSP_SYNCHRONOUS_WORK_ITEM *SynchronousWorkItem,
BOOLEAN Alertable)
{
PAGED_CODE();
ExQueueWorkItem(&SynchronousWorkItem->WorkQueueItem, CriticalWorkQueue);
NTSTATUS Result;
Result = KeWaitForSingleObject(&SynchronousWorkItem->Event, Executive, KernelMode, FALSE, 0);
ASSERT(STATUS_SUCCESS == Result);
/* Alertable=TRUE requires item allocated by FspAllocateSynchronousWorkItem */
ASSERT(!Alertable || 0 < SynchronousWorkItem->RefCount);
ExQueueWorkItem(&SynchronousWorkItem->WorkQueueItem, CriticalWorkQueue);
Result = KeWaitForSingleObject(&SynchronousWorkItem->Event, Executive, KernelMode, Alertable, 0);
if (0 < SynchronousWorkItem->RefCount)
{
if (0 == InterlockedDecrement(&SynchronousWorkItem->RefCount))
FspFree(SynchronousWorkItem);
}
return Result;
}
static VOID FspExecuteSynchronousWorkItemRoutine(PVOID Context)
@@ -1151,8 +1184,15 @@ static VOID FspExecuteSynchronousWorkItemRoutine(PVOID Context)
PAGED_CODE();
FSP_SYNCHRONOUS_WORK_ITEM *SynchronousWorkItem = Context;
SynchronousWorkItem->Routine(SynchronousWorkItem->Context);
KeSetEvent(&SynchronousWorkItem->Event, 1, FALSE);
if (0 < SynchronousWorkItem->RefCount)
{
if (0 == InterlockedDecrement(&SynchronousWorkItem->RefCount))
FspFree(SynchronousWorkItem);
}
}
VOID FspInitializeDelayedWorkItem(FSP_DELAYED_WORK_ITEM *DelayedWorkItem,
+8 -4
View File
@@ -432,6 +432,9 @@ VOID FspVolumeDelete(
ULONG FileNodeCount, Index;
NTSTATUS Result;
/* stop the I/O queue */
FspIoqStop(FsvolDeviceExtension->Ioq, TRUE);
FspFsvolDeviceVolumeDeleteAcquireExclusive(FsvolDeviceObject);
FsvolDeviceExtension->VolumeDeleted = TRUE;
@@ -486,9 +489,6 @@ static VOID FspVolumeDeleteNoLock(
PDEVICE_OBJECT FsvolDeviceObject = IrpSp->FileObject->FsContext2;
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
/* stop the I/O queue */
FspIoqStop(FsvolDeviceExtension->Ioq, TRUE);
/* do we have a virtual disk device or are we registered with fsmup? */
if (0 != FsvolDeviceExtension->FsvrtDeviceObject)
{
@@ -1381,6 +1381,7 @@ NTSTATUS FspVolumeNotify(
ASSERT(0 != IrpSp->FileObject->FsContext2);
PDEVICE_OBJECT FsvolDeviceObject = IrpSp->FileObject->FsContext2;
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
PVOID InputBuffer = IrpSp->Parameters.FileSystemControl.Type3InputBuffer;
ULONG InputBufferLength = IrpSp->Parameters.FileSystemControl.InputBufferLength;
FSP_VOLUME_NOTIFY_WORK_ITEM *NotifyWorkItem = 0;
@@ -1396,7 +1397,8 @@ NTSTATUS FspVolumeNotify(
return STATUS_CANCELLED;
FspFsvolDeviceVolumeDeleteAcquireShared(FsvolDeviceObject);
if (FspFsvolDeviceExtension(FsvolDeviceObject)->VolumeDeleted)
if (FsvolDeviceExtension->VolumeDeleted ||
FspIoqStopped(FsvolDeviceExtension->Ioq))
{
Result = STATUS_CANCELLED;
goto fail;
@@ -1523,6 +1525,8 @@ static VOID FspVolumeNotifyWork(PVOID NotifyWorkItem0)
Unlock = TRUE;
break;
}
if ((SIZE_T)(NotifyInfoEnd - (PUINT8)NotifyInfo) < NotifyInfoSize)
break;
FileName.Length =
FileName.MaximumLength = (USHORT)(NotifyInfoSize - sizeof(FSP_FSCTL_NOTIFY_INFO));