sys: fsctl

This commit is contained in:
Bill Zissimopoulos
2015-11-22 17:43:22 -08:00
parent cb72cad355
commit 9653cd2546
3 changed files with 93 additions and 31 deletions

View File

@ -21,13 +21,13 @@ extern const __declspec(selectany) GUID FspFsvrtDeviceClassGuid =
/* fsctl device codes */ /* fsctl device codes */
#define FSP_FSCTL_CREATE \ #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 */ /* fsvrt device codes */
#define FSP_FSCTL_DELETE \ #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 \ #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 #define FSP_FSCTL_CREATE_BUFFER_SIZEMAX 64

View File

@ -13,10 +13,12 @@
#include <winfsp/fsctl.h> #include <winfsp/fsctl.h>
#define DRIVER_NAME "WinFsp" #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 */ /* IoCreateDeviceSecure default SDDL's */
#define FSP_FSVRT_DEVICE_SDDL "D:P(A;;GA;;;SY)(A;;GA;;;BA)(A;;GRGW;;;WD)" #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|GENERIC_WRITE */ /* 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 */ /* DEBUGLOG */
#if DBG #if DBG
@ -26,7 +28,7 @@
#define DEBUGLOG(fmt, ...) ((void)0) #define DEBUGLOG(fmt, ...) ((void)0)
#endif #endif
/* enter/leave*/ /* FSP_ENTER/FSP_LEAVE */
#if DBG #if DBG
#define FSP_DEBUGLOG_(fmt, rfmt, ...) \ #define FSP_DEBUGLOG_(fmt, rfmt, ...) \
DbgPrint(AbnormalTermination() ? \ DbgPrint(AbnormalTermination() ? \
@ -37,7 +39,7 @@
do \ do \
{ \ { \
if (HasDbgBreakPoint(__FUNCTION__))\ if (HasDbgBreakPoint(__FUNCTION__))\
try { DbgBreakPoint(); } except(EXCEPTION_EXECUTE_HANDLER) {}\ try { DbgBreakPoint(); } except (EXCEPTION_EXECUTE_HANDLER) {}\
} while (0,0) } while (0,0)
#else #else
#define FSP_DEBUGLOG_(fmt, rfmt, ...) ((void)0) #define FSP_DEBUGLOG_(fmt, rfmt, ...) ((void)0)
@ -103,6 +105,14 @@
goto fsp_leave_label; \ goto fsp_leave_label; \
} while (0,0) } 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 */ /* types */
enum enum
{ {
@ -121,6 +131,7 @@ typedef struct
typedef struct typedef struct
{ {
FSP_DEVICE_EXTENSION Base; FSP_DEVICE_EXTENSION Base;
UINT8 SecurityDescriptorBuf[];
} FSP_FSVRT_DEVICE_EXTENSION; } FSP_FSVRT_DEVICE_EXTENSION;
typedef struct typedef struct
{ {
@ -195,10 +206,4 @@ const char *IoctlCodeSym(ULONG ControlCode);
extern PDEVICE_OBJECT FspFsctlDiskDeviceObject; extern PDEVICE_OBJECT FspFsctlDiskDeviceObject;
extern PDEVICE_OBJECT FspFsctlNetDeviceObject; extern PDEVICE_OBJECT FspFsctlNetDeviceObject;
/* I/O increment */
#define FSP_IO_INCREMENT IO_NETWORK_INCREMENT
/* disable warnings */
#pragma warning(disable:4100) /* unreferenced formal parameter */
#endif #endif

View File

@ -8,9 +8,11 @@
static NTSTATUS FspFsctlCreateVolume( static NTSTATUS FspFsctlCreateVolume(
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp); 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); PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
static NTSTATUS FspFsvolTransact( static NTSTATUS FspFsvrtTransact(
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp); PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
static NTSTATUS FspFsctlFileSystemControl( static NTSTATUS FspFsctlFileSystemControl(
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp); PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
@ -22,8 +24,9 @@ DRIVER_DISPATCH FspFileSystemControl;
#ifdef ALLOC_PRAGMA #ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, FspFsctlCreateVolume) #pragma alloc_text(PAGE, FspFsctlCreateVolume)
#pragma alloc_text(PAGE, FspFsvolDeleteVolume) #pragma alloc_text(PAGE, FspFsvrtAccessCheck)
#pragma alloc_text(PAGE, FspFsvolTransact) #pragma alloc_text(PAGE, FspFsvrtDeleteVolume)
#pragma alloc_text(PAGE, FspFsvrtTransact)
#pragma alloc_text(PAGE, FspFsctlFileSystemControl) #pragma alloc_text(PAGE, FspFsctlFileSystemControl)
#pragma alloc_text(PAGE, FspFsvrtFileSystemControl) #pragma alloc_text(PAGE, FspFsvrtFileSystemControl)
#pragma alloc_text(PAGE, FspFsvolFileSystemControl) #pragma alloc_text(PAGE, FspFsvolFileSystemControl)
@ -33,23 +36,37 @@ DRIVER_DISPATCH FspFileSystemControl;
static NTSTATUS FspFsctlCreateVolume( static NTSTATUS FspFsctlCreateVolume(
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp) 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; return STATUS_BUFFER_TOO_SMALL;
NTSTATUS Result; NTSTATUS Result;
/* create volume guid */
GUID Guid; GUID Guid;
Result = CreateGuid(&Guid); Result = CreateGuid(&Guid);
if (!NT_SUCCESS(Result)) if (!NT_SUCCESS(Result))
return 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 */ /* create the virtual volume device */
PDEVICE_OBJECT FsvrtDeviceObject; PDEVICE_OBJECT FsvrtDeviceObject;
UNICODE_STRING DeviceSddl; UNICODE_STRING DeviceSddl;
UNICODE_STRING DeviceName; UNICODE_STRING DeviceName;
RtlInitUnicodeString(&DeviceSddl, L"" FSP_FSVRT_DEVICE_SDDL); RtlInitUnicodeString(&DeviceSddl, L"" FSP_FSVRT_DEVICE_SDDL);
RtlInitEmptyUnicodeString(&DeviceName, RtlInitEmptyUnicodeString(&DeviceName, SystemBuffer, FSP_FSCTL_CREATE_BUFFER_SIZEMAX);
Irp->AssociatedIrp.SystemBuffer, FSP_FSCTL_CREATE_BUFFER_SIZEMAX);
Result = RtlUnicodeStringPrintf(&DeviceName, Result = RtlUnicodeStringPrintf(&DeviceName,
L"\\Device\\Volume{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", L"\\Device\\Volume{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
Guid.Data1, Guid.Data2, Guid.Data3, 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]); Guid.Data4[4], Guid.Data4[5], Guid.Data4[6], Guid.Data4[7]);
ASSERT(NT_SUCCESS(Result)); ASSERT(NT_SUCCESS(Result));
Result = IoCreateDeviceSecure(DeviceObject->DriverObject, 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, FILE_DEVICE_SECURE_OPEN, FALSE,
&DeviceSddl, 0, &DeviceSddl, 0,
&FsvrtDeviceObject); &FsvrtDeviceObject);
if (!NT_SUCCESS(Result)) if (NT_SUCCESS(Result))
return Result; {
FspDeviceExtension(FsvrtDeviceObject)->Kind = FspFsvrtDeviceExtensionKind; FspDeviceExtension(FsvrtDeviceObject)->Kind = FspFsvrtDeviceExtensionKind;
Irp->IoStatus.Information = DeviceName.Length + 1; RtlCopyMemory(FspFsvrtDeviceExtension(FsvrtDeviceObject)->SecurityDescriptorBuf,
SecurityDescriptor, InputBufferLength);
Irp->IoStatus.Information = DeviceName.Length + 1;
}
/* free the temporary security descriptor */
ExFreePoolWithTag(SecurityDescriptor, FSP_TAG);
return Result; 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) 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; return STATUS_INVALID_DEVICE_REQUEST;
} }
static NTSTATUS FspFsvolTransact( static NTSTATUS FspFsvrtTransact(
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp) 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; return STATUS_INVALID_DEVICE_REQUEST;
} }
@ -108,10 +165,10 @@ static NTSTATUS FspFsvrtFileSystemControl(
switch (IrpSp->Parameters.FileSystemControl.FsControlCode) switch (IrpSp->Parameters.FileSystemControl.FsControlCode)
{ {
case FSP_FSCTL_DELETE: case FSP_FSCTL_DELETE:
Result = FspFsvolDeleteVolume(DeviceObject, Irp, IrpSp); Result = FspFsvrtDeleteVolume(DeviceObject, Irp, IrpSp);
break; break;
case FSP_FSCTL_TRANSACT: case FSP_FSCTL_TRANSACT:
Result = FspFsvolTransact(DeviceObject, Irp, IrpSp); Result = FspFsvrtTransact(DeviceObject, Irp, IrpSp);
break; break;
} }
break; break;