mirror of
				https://github.com/winfsp/winfsp.git
				synced 2025-10-29 19:18:39 -05:00 
			
		
		
		
	sys: create: open UserMode AccessToken handle in FspFsvolCreatePrepare and close it properly in FspFsvolCreateRequestFini
This commit is contained in:
		| @@ -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 | ||||
|   | ||||
| @@ -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, ...); | ||||
|  | ||||
|   | ||||
| @@ -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; | ||||
| } | ||||
|   | ||||
| @@ -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; | ||||
| } | ||||
|   | ||||
| @@ -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( | ||||
|   | ||||
| @@ -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); | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user