diff --git a/inc/winfsp/fsctl.h b/inc/winfsp/fsctl.h index 60906990..ab80ef3d 100644 --- a/inc/winfsp/fsctl.h +++ b/inc/winfsp/fsctl.h @@ -74,7 +74,7 @@ enum FspFsctlIrpTimeoutMinimum = 60000, FspFsctlIrpTimeoutMaximum = 600000, FspFsctlIrpTimeoutDefault = 300000, - FspFsctlIrpTimeoutDebug = 42, /* special value for IRP timeout testing; debug driver only */ + FspFsctlIrpTimeoutDebug = 142, /* special value for IRP timeout testing; debug driver only */ FspFsctlIrpCapacityMinimum = 100, FspFsctlIrpCapacityMaximum = 1000, FspFsctlIrpCapacityDefault = 1000, @@ -110,6 +110,7 @@ typedef struct UINT32 FileAttributes; /* FILE_ATTRIBUTE_{NORMAL,DIRECTORY,etc.} */ FSP_FSCTL_TRANSACT_BUF SecurityDescriptor; /* security descriptor for new files */ UINT64 AllocationSize; /* initial allocation size */ + UINT64 AccessToken; /* (HANDLE); request access token; sent if NoAccessCheck is 0 */ UINT32 DesiredAccess; /* FILE_{READ_DATA,WRITE_DATA,etc.} */ UINT32 ShareAccess; /* FILE_SHARE_{READ,WRITE,DELETE} */ FSP_FSCTL_TRANSACT_BUF Ea; /* reserved; not currently implemented */ @@ -213,8 +214,6 @@ FSP_API NTSTATUS FspFsctlCreateVolume(PWSTR DevicePath, FSP_API NTSTATUS FspFsctlTransact(HANDLE VolumeHandle, PVOID ResponseBuf, SIZE_T ResponseBufSize, PVOID RequestBuf, SIZE_T *PRequestBufSize); -FSP_API NTSTATUS FspFsctlOpenAccessToken(HANDLE VolumeHandle, - UINT64 Hint, PHANDLE PAccessToken); #endif #endif diff --git a/inc/winfsp/winfsp.h b/inc/winfsp/winfsp.h index d1bb1120..bfff13cb 100644 --- a/inc/winfsp/winfsp.h +++ b/inc/winfsp/winfsp.h @@ -91,10 +91,9 @@ FSP_API NTSTATUS FspSendResponseWithStatus(FSP_FILE_SYSTEM *FileSystem, * Access Checks */ FSP_API PGENERIC_MAPPING FspGetFileGenericMapping(VOID); -FSP_API NTSTATUS FspOpenAccessToken(FSP_FILE_SYSTEM *FileSystem, - FSP_FSCTL_TRANSACT_REQ *Request, PHANDLE PAccessToken); FSP_API NTSTATUS FspAccessCheck(FSP_FILE_SYSTEM *FileSystem, - FSP_FSCTL_TRANSACT_REQ *Request, DWORD DesiredAccess, PDWORD PGrantedAccess); + FSP_FSCTL_TRANSACT_REQ *Request, BOOLEAN AllowTraverseCheck, DWORD DesiredAccess, + PDWORD PGrantedAccess); /* * Path Handling @@ -106,7 +105,6 @@ FSP_API VOID FspPathCombine(PWSTR Prefix, PWSTR Suffix); /* * Utility */ -FSP_API PGENERIC_MAPPING FspGetFileGenericMapping(VOID); FSP_API NTSTATUS FspNtStatusFromWin32(DWORD Error); FSP_API VOID FspDebugLog(const char *format, ...); diff --git a/src/dll/access.c b/src/dll/access.c index 7bc94c68..bf338a9a 100644 --- a/src/dll/access.c +++ b/src/dll/access.c @@ -19,12 +19,6 @@ FSP_API PGENERIC_MAPPING FspGetFileGenericMapping(VOID) return &FspFileGenericMapping; } -FSP_API NTSTATUS FspOpenAccessToken(FSP_FILE_SYSTEM *FileSystem, - FSP_FSCTL_TRANSACT_REQ *Request, PHANDLE PAccessToken) -{ - return FspFsctlOpenAccessToken(FileSystem->VolumeHandle, Request->Hint, PAccessToken); -} - static NTSTATUS FspGetFileSecurityDescriptor(FSP_FILE_SYSTEM *FileSystem, PWSTR FileName, PSECURITY_DESCRIPTOR *PSecurityDescriptor, SIZE_T *PSecurityDescriptorSize) { @@ -45,7 +39,8 @@ static NTSTATUS FspGetFileSecurityDescriptor(FSP_FILE_SYSTEM *FileSystem, } FSP_API NTSTATUS FspAccessCheck(FSP_FILE_SYSTEM *FileSystem, - FSP_FSCTL_TRANSACT_REQ *Request, DWORD DesiredAccess, PDWORD PGrantedAccess) + FSP_FSCTL_TRANSACT_REQ *Request, BOOLEAN AllowTraverseCheck, DWORD DesiredAccess, + PDWORD PGrantedAccess) { if (0 != FileSystem->AccessCheck) return FileSystem->AccessCheck(FileSystem, Request, DesiredAccess, PGrantedAccess); @@ -57,7 +52,6 @@ FSP_API NTSTATUS FspAccessCheck(FSP_FILE_SYSTEM *FileSystem, } NTSTATUS Result; - HANDLE AccessToken = 0; PSECURITY_DESCRIPTOR SecurityDescriptor = 0; SIZE_T SecurityDescriptorSize; DWORD PrivilegeSetLength; @@ -65,10 +59,6 @@ FSP_API NTSTATUS FspAccessCheck(FSP_FILE_SYSTEM *FileSystem, *PGrantedAccess = 0; - Result = FspOpenAccessToken(FileSystem, Request, &AccessToken); - if (!NT_SUCCESS(Result)) - goto exit; - SecurityDescriptorSize = 1024; SecurityDescriptor = MemAlloc(SecurityDescriptorSize); if (0 == SecurityDescriptor) @@ -77,7 +67,7 @@ FSP_API NTSTATUS FspAccessCheck(FSP_FILE_SYSTEM *FileSystem, goto exit; } - if (!Request->Req.Create.HasTraversePrivilege) + if (AllowTraverseCheck && !Request->Req.Create.HasTraversePrivilege) { PWSTR Path = (PWSTR)Request->Buffer, Prefix; DWORD TraverseAccess; @@ -100,7 +90,7 @@ FSP_API NTSTATUS FspAccessCheck(FSP_FILE_SYSTEM *FileSystem, if (!NT_SUCCESS(Result)) goto exit; - if (AccessCheck(SecurityDescriptor, AccessToken, FILE_TRAVERSE, + if (AccessCheck(SecurityDescriptor, (HANDLE)Request->Req.Create.AccessToken, FILE_TRAVERSE, &FspFileGenericMapping, 0, &PrivilegeSetLength, &TraverseAccess, &AccessStatus)) Result = AccessStatus ? STATUS_SUCCESS : STATUS_ACCESS_DENIED; else @@ -116,18 +106,14 @@ FSP_API NTSTATUS FspAccessCheck(FSP_FILE_SYSTEM *FileSystem, if (!NT_SUCCESS(Result)) goto exit; - if (AccessCheck(SecurityDescriptor, AccessToken, DesiredAccess, + if (AccessCheck(SecurityDescriptor, (HANDLE)Request->Req.Create.AccessToken, DesiredAccess, &FspFileGenericMapping, 0, &PrivilegeSetLength, PGrantedAccess, &AccessStatus)) Result = AccessStatus ? STATUS_SUCCESS : STATUS_ACCESS_DENIED; else Result = FspNtStatusFromWin32(GetLastError()); exit: - MemFree(SecurityDescriptor); - if (0 != AccessToken) - CloseHandle(AccessToken); - return Result; } diff --git a/src/dll/fsctl.c b/src/dll/fsctl.c index 81be2cbf..8bc56ece 100644 --- a/src/dll/fsctl.c +++ b/src/dll/fsctl.c @@ -109,11 +109,3 @@ FSP_API NTSTATUS FspFsctlTransact(HANDLE VolumeHandle, exit: return Result; } - -FSP_API NTSTATUS FspFsctlOpenAccessToken(HANDLE VolumeHandle, - UINT64 Hint, PHANDLE PAccessToken) -{ - *PAccessToken = 0; - - return STATUS_NOT_IMPLEMENTED; -} diff --git a/src/sys/create.c b/src/sys/create.c index 2cc7b336..b3d23756 100644 --- a/src/sys/create.c +++ b/src/sys/create.c @@ -34,6 +34,7 @@ enum { RequestFsContext = 0, RequestAccessToken, + RequestProcess, }; static NTSTATUS FspFsctlCreate( @@ -256,6 +257,7 @@ static NTSTATUS FspFsvolCreate( FSP_FSCTL_DEFAULT_ALIGN_UP(Request->FileName.Size); Request->Req.Create.SecurityDescriptor.Size = (UINT16)SecurityDescriptorSize; Request->Req.Create.AllocationSize = AllocationSize.QuadPart; + Request->Req.Create.AccessToken = 0; Request->Req.Create.DesiredAccess = DesiredAccess; Request->Req.Create.ShareAccess = ShareAccess; Request->Req.Create.Ea.Offset = 0; @@ -289,11 +291,11 @@ NTSTATUS FspFsvolCreatePrepare( { PAGED_CODE(); -#if 0 NTSTATUS Result; PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); PACCESS_STATE AccessState = IrpSp->Parameters.Create.SecurityContext->AccessState; HANDLE UserModeAccessToken; + PEPROCESS Process; /* get a user-mode handle to the access token */ Result = ObOpenObjectByPointer(SeQuerySubjectContextToken(&AccessState->SubjectSecurityContext), @@ -301,10 +303,14 @@ NTSTATUS FspFsvolCreatePrepare( if (!NT_SUCCESS(Result)) return Result; + /* get a pointer to the current process so that we can close the access token later */ + Process = PsGetCurrentProcess(); + ObReferenceObject(Process); + /* send the user-mode handle to the user-mode file system */ FspIopRequestContext(Request, RequestAccessToken) = UserModeAccessToken; + FspIopRequestContext(Request, RequestProcess) = Process; Request->Req.Create.AccessToken = (UINT_PTR)UserModeAccessToken; -#endif return STATUS_SUCCESS; } @@ -428,21 +434,38 @@ static VOID FspFsvolCreateRequestFini(PVOID Context[3]) PAGED_CODE(); if (0 != Context[RequestFsContext]) + { FspFileContextRelease(Context[RequestFsContext]); + Context[RequestFsContext] = 0; + } -#if 0 if (0 != Context[RequestAccessToken]) { + PEPROCESS Process = Context[RequestProcess]; + KAPC_STATE ApcState; + BOOLEAN Attach; + + ASSERT(0 != Process); + Attach = Process != PsGetCurrentProcess(); + + if (Attach) + KeStackAttachProcess(Process, &ApcState); #if DBG NTSTATUS Result0; - Result0 = ObCloseHandle(Context[RequestAccessToken], KernelMode); + Result0 = ObCloseHandle(Context[RequestAccessToken], UserMode); if (!NT_SUCCESS(Result0)) DEBUGLOG("ObCloseHandle() = %s", NtStatusSym(Result0)); #else - ObCloseHandle(Context[RequestAccessToken], KernelMode); + ObCloseHandle(Context[RequestAccessToken], UserMode); #endif + if (Attach) + KeUnstackDetachProcess(&ApcState); + + ObDereferenceObject(Process); + + Context[RequestAccessToken] = 0; + Context[RequestProcess] = 0; } -#endif } NTSTATUS FspCreate( diff --git a/tst/winfsp-tests/timeout-test.c b/tst/winfsp-tests/timeout-test.c index c9a183cd..ad2d9234 100644 --- a/tst/winfsp-tests/timeout-test.c +++ b/tst/winfsp-tests/timeout-test.c @@ -19,6 +19,21 @@ static unsigned __stdcall timeout_pending_dotest_thread(void *FilePath) return 0; } +static unsigned __stdcall timeout_pending_dotest_thread2(void *FilePath) +{ + FspDebugLog(__FUNCTION__ ": \"%S\"\n", FilePath); + + Sleep(500); + + HANDLE Handle; + Handle = CreateFileW(FilePath, + FILE_GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0); + if (INVALID_HANDLE_VALUE == Handle) + return GetLastError(); + CloseHandle(Handle); + return 0; +} + void timeout_pending_dotest(PWSTR DeviceName) { NTSTATUS Result; @@ -50,6 +65,57 @@ void timeout_pending_dotest(PWSTR DeviceName) ASSERT(ERROR_OPERATION_ABORTED == ExitCode); + Thread = (HANDLE)_beginthreadex(0, 0, timeout_pending_dotest_thread2, FilePath, 0, 0); + ASSERT(0 != Thread); + + FSP_FSCTL_DECLSPEC_ALIGN UINT8 RequestBuf[FSP_FSCTL_TRANSACT_REQ_BUFFER_SIZEMIN]; + FSP_FSCTL_DECLSPEC_ALIGN UINT8 ResponseBuf[FSP_FSCTL_TRANSACT_RSP_SIZEMAX]; + UINT8 *RequestBufEnd; + UINT8 *ResponseBufEnd = ResponseBuf + sizeof ResponseBuf; + SIZE_T RequestBufSize; + SIZE_T ResponseBufSize; + FSP_FSCTL_TRANSACT_REQ *Request = (PVOID)RequestBuf, *NextRequest; + FSP_FSCTL_TRANSACT_RSP *Response = (PVOID)ResponseBuf; + + ResponseBufSize = 0; + RequestBufSize = sizeof RequestBuf; + Result = FspFsctlTransact(VolumeHandle, 0, 0, RequestBuf, &RequestBufSize); + ASSERT(STATUS_SUCCESS == Result); + + RequestBufEnd = RequestBuf + RequestBufSize; + + NextRequest = FspFsctlTransactConsumeRequest(Request, RequestBufEnd); + ASSERT(0 != NextRequest); + + ASSERT(0 == Request->Version); + ASSERT(FSP_FSCTL_TRANSACT_REQ_SIZEMAX >= Request->Size); + ASSERT(0 != Request->Hint); + ASSERT(FspFsctlTransactCreateKind == Request->Kind); + ASSERT(FILE_CREATE == ((Request->Req.Create.CreateOptions >> 24) & 0xff)); + ASSERT(FILE_ATTRIBUTE_NORMAL == Request->Req.Create.FileAttributes); + ASSERT(0 == Request->Req.Create.SecurityDescriptor.Offset); + ASSERT(0 == Request->Req.Create.SecurityDescriptor.Size); + ASSERT(0 == Request->Req.Create.AllocationSize); + ASSERT(FILE_GENERIC_READ == Request->Req.Create.DesiredAccess); + ASSERT((FILE_SHARE_READ | FILE_SHARE_WRITE) == Request->Req.Create.ShareAccess); + ASSERT(0 == Request->Req.Create.Ea.Offset); + ASSERT(0 == Request->Req.Create.Ea.Size); + ASSERT(Request->Req.Create.UserMode); + ASSERT(Request->Req.Create.HasTraversePrivilege); + ASSERT(!Request->Req.Create.OpenTargetDirectory); + ASSERT(!Request->Req.Create.CaseSensitive); + ASSERT(0 == Request->FileName.Offset); + ASSERT((wcslen((PVOID)Request->Buffer) + 1) * sizeof(WCHAR) == Request->FileName.Size); + ASSERT( + 0 == wcscmp((PVOID)Request->Buffer, L"\\file0") || + 0 == wcscmp((PVOID)Request->Buffer, FilePath + 1)); + + WaitForSingleObject(Thread, INFINITE); + GetExitCodeThread(Thread, &ExitCode); + CloseHandle(Thread); + + ASSERT(ERROR_OPERATION_ABORTED == ExitCode); + Success = CloseHandle(VolumeHandle); ASSERT(Success); }