dll: fsctl, fuse: preflight check

This commit is contained in:
Bill Zissimopoulos 2016-06-02 20:21:34 -07:00
parent 7fef1b87f6
commit 9b93c766c3
3 changed files with 103 additions and 10 deletions

View File

@ -422,6 +422,7 @@ FSP_API NTSTATUS FspFsctlTransact(HANDLE VolumeHandle,
FSP_API NTSTATUS FspFsctlStop(HANDLE VolumeHandle); FSP_API NTSTATUS FspFsctlStop(HANDLE VolumeHandle);
FSP_API NTSTATUS FspFsctlGetVolumeList(PWSTR DevicePath, FSP_API NTSTATUS FspFsctlGetVolumeList(PWSTR DevicePath,
PWCHAR VolumeListBuf, PSIZE_T PVolumeListSize); PWCHAR VolumeListBuf, PSIZE_T PVolumeListSize);
FSP_API NTSTATUS FspFsctlPreflight(PWSTR DevicePath);
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -193,6 +193,23 @@ exit:
return Result; return Result;
} }
FSP_API NTSTATUS FspFsctlPreflight(PWSTR DevicePath)
{
NTSTATUS Result;
SIZE_T VolumeListSize;
Result = FspFsctlStartService();
if (!NT_SUCCESS(Result))
return Result;
VolumeListSize = 0;
Result = FspFsctlGetVolumeList(DevicePath, 0, &VolumeListSize);
if (!NT_SUCCESS(Result) && STATUS_BUFFER_TOO_SMALL != Result)
return Result;
return STATUS_SUCCESS;
}
static NTSTATUS FspFsctlStartService(VOID) static NTSTATUS FspFsctlStartService(VOID)
{ {
PWSTR DriverName = L"" FSP_FSCTL_DRIVER_NAME; PWSTR DriverName = L"" FSP_FSCTL_DRIVER_NAME;

View File

@ -17,6 +17,9 @@
#include <dll/fuse/library.h> #include <dll/fuse/library.h>
#define FSP_FUSE_SECTORSIZE_MIN 512
#define FSP_FUSE_SECTORSIZE_MAX 4096
struct fuse_chan struct fuse_chan
{ {
PWSTR MountPoint; PWSTR MountPoint;
@ -205,6 +208,36 @@ FSP_FUSE_API int fsp_fuse_is_lib_option(struct fsp_fuse_env *env,
static void fsp_fuse_cleanup(struct fuse *f); static void fsp_fuse_cleanup(struct fuse *f);
static NTSTATUS fsp_fuse_preflight(struct fuse *f)
{
NTSTATUS Result;
Result = FspFsctlPreflight(f->VolumeParams.Prefix[0] ?
L"" FSP_FSCTL_NET_DEVICE_NAME : L"" FSP_FSCTL_DISK_DEVICE_NAME);
if (!NT_SUCCESS(Result))
return Result;
if (L'\0' != f->MountPoint)
{
if ((
(L'A' <= f->MountPoint[0] && f->MountPoint[0] <= L'Z') ||
(L'a' <= f->MountPoint[0] && f->MountPoint[0] <= L'z')
) &&
L':' == f->MountPoint[1] || L'\0' == f->MountPoint[2])
{
if (GetLogicalDrives() & (1 << (f->MountPoint[0] - 'A')))
return STATUS_OBJECT_NAME_COLLISION;
}
else
if (L'*' == f->MountPoint[0] && L'\0' == f->MountPoint[1])
;
else
return STATUS_OBJECT_NAME_INVALID;
}
return STATUS_SUCCESS;
}
static NTSTATUS fsp_fuse_svcstart(FSP_SERVICE *Service, ULONG argc, PWSTR *argv) static NTSTATUS fsp_fuse_svcstart(FSP_SERVICE *Service, ULONG argc, PWSTR *argv)
{ {
static FSP_FILE_SYSTEM_INTERFACE intf = static FSP_FILE_SYSTEM_INTERFACE intf =
@ -247,10 +280,13 @@ static NTSTATUS fsp_fuse_svcstart(FSP_SERVICE *Service, ULONG argc, PWSTR *argv)
struct fuse_statvfs stbuf; struct fuse_statvfs stbuf;
int err; int err;
memset(&stbuf, 0, sizeof stbuf);
err = f->ops.statfs("/", &stbuf); err = f->ops.statfs("/", &stbuf);
if (0 != err) if (0 != err)
goto fail; goto fail;
if (stbuf.f_bsize > FSP_FUSE_SECTORSIZE_MAX)
stbuf.f_bsize = FSP_FUSE_SECTORSIZE_MAX;
if (0 == f->VolumeParams.SectorSize) if (0 == f->VolumeParams.SectorSize)
f->VolumeParams.SectorSize = (UINT16)stbuf.f_bsize; f->VolumeParams.SectorSize = (UINT16)stbuf.f_bsize;
if (0 == f->VolumeParams.MaxComponentLength) if (0 == f->VolumeParams.MaxComponentLength)
@ -261,21 +297,30 @@ static NTSTATUS fsp_fuse_svcstart(FSP_SERVICE *Service, ULONG argc, PWSTR *argv)
struct fuse_stat stbuf; struct fuse_stat stbuf;
int err; int err;
memset(&stbuf, 0, sizeof stbuf);
err = f->ops.getattr("/", (void *)&stbuf); err = f->ops.getattr("/", (void *)&stbuf);
if (0 != err) if (0 != err)
goto fail; goto fail;
if (0 == f->VolumeParams.VolumeCreationTime) if (0 == f->VolumeParams.VolumeCreationTime)
{
if (0 != stbuf.st_birthtim.tv_sec)
f->VolumeParams.VolumeCreationTime = f->VolumeParams.VolumeCreationTime =
Int32x32To64(stbuf.st_birthtim.tv_sec, 10000000) + 116444736000000000 + Int32x32To64(stbuf.st_birthtim.tv_sec, 10000000) + 116444736000000000 +
stbuf.st_birthtim.tv_nsec / 100; stbuf.st_birthtim.tv_nsec / 100;
else
if (0 != stbuf.st_ctim.tv_sec)
f->VolumeParams.VolumeCreationTime =
Int32x32To64(stbuf.st_ctim.tv_sec, 10000000) + 116444736000000000 +
stbuf.st_ctim.tv_nsec / 100;
}
} }
/* the FSD does not currently limit these VolumeParams fields; do so here! */ /* the FSD does not currently limit these VolumeParams fields; do so here! */
if (f->VolumeParams.SectorSize < 512) if (f->VolumeParams.SectorSize < FSP_FUSE_SECTORSIZE_MIN)
f->VolumeParams.SectorSize = 512; f->VolumeParams.SectorSize = FSP_FUSE_SECTORSIZE_MIN;
if (f->VolumeParams.SectorSize < 4096) if (f->VolumeParams.SectorSize > FSP_FUSE_SECTORSIZE_MAX)
f->VolumeParams.SectorSize = 4096; f->VolumeParams.SectorSize = FSP_FUSE_SECTORSIZE_MAX;
if (f->VolumeParams.MaxComponentLength > 255) if (f->VolumeParams.MaxComponentLength > 255)
f->VolumeParams.MaxComponentLength = 255; f->VolumeParams.MaxComponentLength = 255;
@ -441,6 +486,7 @@ FSP_FUSE_API struct fuse *fsp_fuse_new(struct fsp_fuse_env *env,
struct fuse *f = 0; struct fuse *f = 0;
struct fsp_fuse_core_opt_data opt_data; struct fsp_fuse_core_opt_data opt_data;
ULONG Size; ULONG Size;
PWSTR ErrorMessage = L".";
NTSTATUS Result; NTSTATUS Result;
if (opsize > sizeof(struct fuse_operations)) if (opsize > sizeof(struct fuse_operations))
@ -485,11 +531,41 @@ FSP_FUSE_API struct fuse *fsp_fuse_new(struct fsp_fuse_env *env,
FspServiceAllowConsoleMode(f->Service); FspServiceAllowConsoleMode(f->Service);
f->Service->UserContext = f; f->Service->UserContext = f;
Result = fsp_fuse_preflight(f);
if (!NT_SUCCESS(Result))
{
switch (Result)
{
case STATUS_ACCESS_DENIED:
ErrorMessage = L": Access denied.";
break;
case STATUS_NO_SUCH_DEVICE:
ErrorMessage = L": FSD not found.";
break;
case STATUS_OBJECT_NAME_INVALID:
ErrorMessage = L": invalid mount point.";
break;
case STATUS_OBJECT_NAME_COLLISION:
ErrorMessage = L": mount point in use.";
break;
default:
ErrorMessage = L": unspecified error.";
break;
}
goto fail;
}
return f; return f;
fail: fail:
FspServiceLog(EVENTLOG_ERROR_TYPE, FspServiceLog(EVENTLOG_ERROR_TYPE,
L"Cannot create " FSP_FUSE_LIBRARY_NAME " file system."); L"Cannot create " FSP_FUSE_LIBRARY_NAME " file system%s",
ErrorMessage);
if (0 != f) if (0 != f)
fsp_fuse_destroy(env, f); fsp_fuse_destroy(env, f);
@ -500,8 +576,7 @@ fail:
FSP_FUSE_API void fsp_fuse_destroy(struct fsp_fuse_env *env, FSP_FUSE_API void fsp_fuse_destroy(struct fsp_fuse_env *env,
struct fuse *f) struct fuse *f)
{ {
if (0 != f->FileSystem) fsp_fuse_cleanup(f);
FspFileSystemDelete(f->FileSystem);
if (0 != f->Service) if (0 != f->Service)
FspServiceDelete(f->Service); FspServiceDelete(f->Service);