diff --git a/inc/winfsp/fsctl.h b/inc/winfsp/fsctl.h index f853000c..3a4ac340 100644 --- a/inc/winfsp/fsctl.h +++ b/inc/winfsp/fsctl.h @@ -21,13 +21,13 @@ extern const __declspec(selectany) GUID FspFsvrtDeviceClassGuid = /* fsctl device codes */ #define FSP_FSCTL_CREATE \ - CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x800 + 'C', METHOD_BUFFERED, FILE_READ_DATA | FILE_WRITE_DATA) + CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x800 + 'C', METHOD_BUFFERED, FILE_ANY_ACCESS) /* fsvrt device codes */ #define FSP_FSCTL_DELETE \ - CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x800 + 'D', METHOD_BUFFERED, FILE_READ_DATA | FILE_WRITE_DATA) + CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x800 + 'D', METHOD_BUFFERED, FILE_ANY_ACCESS) #define FSP_FSCTL_TRANSACT \ - CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x800 + 'T', METHOD_BUFFERED, FILE_READ_DATA | FILE_WRITE_DATA) + CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x800 + 'T', METHOD_BUFFERED, FILE_ANY_ACCESS) #define FSP_FSCTL_CREATE_BUFFER_SIZEMAX 64 diff --git a/src/sys/driver.h b/src/sys/driver.h index f0bcb6cd..5179bfca 100644 --- a/src/sys/driver.h +++ b/src/sys/driver.h @@ -13,10 +13,12 @@ #include #define DRIVER_NAME "WinFsp" -#define FSP_FSCTL_DEVICE_SDDL "D:P(A;;GA;;;SY)(A;;GA;;;BA)(A;;GRGW;;;WD)" - /* System:GENERIC_ALL, Administrators:GENERIC_ALL, World:GENERIC_READ|GENERIC_WRITE */ -#define FSP_FSVRT_DEVICE_SDDL "D:P(A;;GA;;;SY)(A;;GA;;;BA)(A;;GRGW;;;WD)" - /* System:GENERIC_ALL, Administrators:GENERIC_ALL, World:GENERIC_READ|GENERIC_WRITE */ + +/* IoCreateDeviceSecure default SDDL's */ +#define FSP_FSCTL_DEVICE_SDDL "D:P(A;;GA;;;SY)(A;;GA;;;BA)(A;;GR;;;WD)" + /* System:GENERIC_ALL, Administrators:GENERIC_ALL, World:GENERIC_READ */ +#define FSP_FSVRT_DEVICE_SDDL "D:P(A;;GA;;;SY)(A;;GA;;;BA)(A;;GR;;;WD)" + /* System:GENERIC_ALL, Administrators:GENERIC_ALL, World:GENERIC_READ */ /* DEBUGLOG */ #if DBG @@ -26,7 +28,7 @@ #define DEBUGLOG(fmt, ...) ((void)0) #endif -/* enter/leave*/ +/* FSP_ENTER/FSP_LEAVE */ #if DBG #define FSP_DEBUGLOG_(fmt, rfmt, ...) \ DbgPrint(AbnormalTermination() ? \ @@ -37,7 +39,7 @@ do \ { \ if (HasDbgBreakPoint(__FUNCTION__))\ - try { DbgBreakPoint(); } except(EXCEPTION_EXECUTE_HANDLER) {}\ + try { DbgBreakPoint(); } except (EXCEPTION_EXECUTE_HANDLER) {}\ } while (0,0) #else #define FSP_DEBUGLOG_(fmt, rfmt, ...) ((void)0) @@ -103,6 +105,14 @@ goto fsp_leave_label; \ } while (0,0) +/* misc macros */ +#define FSP_TAG ' psF' +#define FSP_IO_INCREMENT IO_NETWORK_INCREMENT + +/* disable warnings */ +#pragma warning(disable:4100) /* unreferenced formal parameter */ +#pragma warning(disable:4200) /* zero-sized array in struct/union */ + /* types */ enum { @@ -121,6 +131,7 @@ typedef struct typedef struct { FSP_DEVICE_EXTENSION Base; + UINT8 SecurityDescriptorBuf[]; } FSP_FSVRT_DEVICE_EXTENSION; typedef struct { @@ -195,10 +206,4 @@ const char *IoctlCodeSym(ULONG ControlCode); extern PDEVICE_OBJECT FspFsctlDiskDeviceObject; extern PDEVICE_OBJECT FspFsctlNetDeviceObject; -/* I/O increment */ -#define FSP_IO_INCREMENT IO_NETWORK_INCREMENT - -/* disable warnings */ -#pragma warning(disable:4100) /* unreferenced formal parameter */ - #endif diff --git a/src/sys/fsctl.c b/src/sys/fsctl.c index ef3b4bb8..5a46c72c 100644 --- a/src/sys/fsctl.c +++ b/src/sys/fsctl.c @@ -8,9 +8,11 @@ static NTSTATUS FspFsctlCreateVolume( PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp); -static NTSTATUS FspFsvolDeleteVolume( +static NTSTATUS FspFsvrtAccessCheck( + PSECURITY_DESCRIPTOR SecurityDescriptor, ACCESS_MASK DesiredAccess, KPROCESSOR_MODE AccessMode); +static NTSTATUS FspFsvrtDeleteVolume( PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp); -static NTSTATUS FspFsvolTransact( +static NTSTATUS FspFsvrtTransact( PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp); static NTSTATUS FspFsctlFileSystemControl( PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp); @@ -22,8 +24,9 @@ DRIVER_DISPATCH FspFileSystemControl; #ifdef ALLOC_PRAGMA #pragma alloc_text(PAGE, FspFsctlCreateVolume) -#pragma alloc_text(PAGE, FspFsvolDeleteVolume) -#pragma alloc_text(PAGE, FspFsvolTransact) +#pragma alloc_text(PAGE, FspFsvrtAccessCheck) +#pragma alloc_text(PAGE, FspFsvrtDeleteVolume) +#pragma alloc_text(PAGE, FspFsvrtTransact) #pragma alloc_text(PAGE, FspFsctlFileSystemControl) #pragma alloc_text(PAGE, FspFsvrtFileSystemControl) #pragma alloc_text(PAGE, FspFsvolFileSystemControl) @@ -33,23 +36,37 @@ DRIVER_DISPATCH FspFileSystemControl; static NTSTATUS FspFsctlCreateVolume( PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp) { - if (FSP_FSCTL_CREATE_BUFFER_SIZEMAX > IrpSp->Parameters.FileSystemControl.OutputBufferLength) + /* check parameters */ + ULONG InputBufferLength = IrpSp->Parameters.FileSystemControl.InputBufferLength; + ULONG OutputBufferLength = IrpSp->Parameters.FileSystemControl.OutputBufferLength; + PVOID SystemBuffer = Irp->AssociatedIrp.SystemBuffer; + if (0 == InputBufferLength || 0 == SystemBuffer || + !RtlValidRelativeSecurityDescriptor(SystemBuffer, InputBufferLength, + OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION)) + return STATUS_INVALID_PARAMETER; + if (FSP_FSCTL_CREATE_BUFFER_SIZEMAX > OutputBufferLength) return STATUS_BUFFER_TOO_SMALL; NTSTATUS Result; + /* create volume guid */ GUID Guid; Result = CreateGuid(&Guid); if (!NT_SUCCESS(Result)) return Result; + /* copy the security descriptor from the system buffer to a temporary one */ + PVOID SecurityDescriptor = ExAllocatePoolWithTag(PagedPool, InputBufferLength, FSP_TAG); + if (0 == SecurityDescriptor) + return STATUS_INSUFFICIENT_RESOURCES; + RtlCopyMemory(SecurityDescriptor, SystemBuffer, InputBufferLength); + /* create the virtual volume device */ PDEVICE_OBJECT FsvrtDeviceObject; UNICODE_STRING DeviceSddl; UNICODE_STRING DeviceName; RtlInitUnicodeString(&DeviceSddl, L"" FSP_FSVRT_DEVICE_SDDL); - RtlInitEmptyUnicodeString(&DeviceName, - Irp->AssociatedIrp.SystemBuffer, FSP_FSCTL_CREATE_BUFFER_SIZEMAX); + RtlInitEmptyUnicodeString(&DeviceName, SystemBuffer, FSP_FSCTL_CREATE_BUFFER_SIZEMAX); Result = RtlUnicodeStringPrintf(&DeviceName, L"\\Device\\Volume{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", Guid.Data1, Guid.Data2, Guid.Data3, @@ -57,27 +74,67 @@ static NTSTATUS FspFsctlCreateVolume( Guid.Data4[4], Guid.Data4[5], Guid.Data4[6], Guid.Data4[7]); ASSERT(NT_SUCCESS(Result)); Result = IoCreateDeviceSecure(DeviceObject->DriverObject, - sizeof(FSP_FSVRT_DEVICE_EXTENSION), &DeviceName, FILE_DEVICE_VIRTUAL_DISK, + sizeof(FSP_FSVRT_DEVICE_EXTENSION) + InputBufferLength, &DeviceName, FILE_DEVICE_VIRTUAL_DISK, FILE_DEVICE_SECURE_OPEN, FALSE, &DeviceSddl, 0, &FsvrtDeviceObject); - if (!NT_SUCCESS(Result)) - return Result; - FspDeviceExtension(FsvrtDeviceObject)->Kind = FspFsvrtDeviceExtensionKind; - Irp->IoStatus.Information = DeviceName.Length + 1; + if (NT_SUCCESS(Result)) + { + FspDeviceExtension(FsvrtDeviceObject)->Kind = FspFsvrtDeviceExtensionKind; + RtlCopyMemory(FspFsvrtDeviceExtension(FsvrtDeviceObject)->SecurityDescriptorBuf, + SecurityDescriptor, InputBufferLength); + Irp->IoStatus.Information = DeviceName.Length + 1; + } + + /* free the temporary security descriptor */ + ExFreePoolWithTag(SecurityDescriptor, FSP_TAG); return Result; } -static NTSTATUS FspFsvolDeleteVolume( +static NTSTATUS FspFsvrtAccessCheck( + PSECURITY_DESCRIPTOR SecurityDescriptor, ACCESS_MASK DesiredAccess, KPROCESSOR_MODE AccessMode) +{ + NTSTATUS Result = STATUS_ACCESS_DENIED; + SECURITY_SUBJECT_CONTEXT SecuritySubjectContext; + ACCESS_MASK GrantedAccess; + + SeCaptureSubjectContext(&SecuritySubjectContext); + if (SeAccessCheck(SecurityDescriptor, + &SecuritySubjectContext, FALSE, + DesiredAccess, 0, 0, IoGetFileObjectGenericMapping(), AccessMode, + &GrantedAccess, &Result)) + Result = STATUS_SUCCESS; + SeReleaseSubjectContext(&SecuritySubjectContext); + + return Result; +} + +static NTSTATUS FspFsvrtDeleteVolume( PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp) { + NTSTATUS Result; + + Result = FspFsvrtAccessCheck( + FspFsvrtDeviceExtension(DeviceObject)->SecurityDescriptorBuf, + FILE_WRITE_DATA, Irp->RequestorMode); + if (!NT_SUCCESS(Result)) + return Result; + return STATUS_INVALID_DEVICE_REQUEST; } -static NTSTATUS FspFsvolTransact( +static NTSTATUS FspFsvrtTransact( PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp) { + NTSTATUS Result; + + Result = FspFsvrtAccessCheck( + FspFsvrtDeviceExtension(DeviceObject)->SecurityDescriptorBuf, + FILE_WRITE_DATA, Irp->RequestorMode); + if (!NT_SUCCESS(Result)) + return Result; + return STATUS_INVALID_DEVICE_REQUEST; } @@ -108,10 +165,10 @@ static NTSTATUS FspFsvrtFileSystemControl( switch (IrpSp->Parameters.FileSystemControl.FsControlCode) { case FSP_FSCTL_DELETE: - Result = FspFsvolDeleteVolume(DeviceObject, Irp, IrpSp); + Result = FspFsvrtDeleteVolume(DeviceObject, Irp, IrpSp); break; case FSP_FSCTL_TRANSACT: - Result = FspFsvolTransact(DeviceObject, Irp, IrpSp); + Result = FspFsvrtTransact(DeviceObject, Irp, IrpSp); break; } break;