From 4d49039abef8e0c06d967db95978ccd54f559cc3 Mon Sep 17 00:00:00 2001 From: Bill Zissimopoulos Date: Thu, 4 Oct 2018 13:21:29 -0700 Subject: [PATCH] sys: FspFastIoQueryOpen: access control Extend the WinFsp kernel-user mode protocol to allow passing security descriptors that can then be used for access control during FastIoQueryOpen. --- inc/winfsp/fsctl.h | 5 ++- src/dll/fsop.c | 80 ++++++++++++++++++++++++++++++++++++++-------- src/sys/create.c | 45 ++++++++++++++++++++++---- src/sys/driver.h | 8 +++-- src/sys/file.c | 68 ++++++++++++++++++++++++++++++++++----- src/sys/fileinfo.c | 2 +- 6 files changed, 175 insertions(+), 33 deletions(-) diff --git a/inc/winfsp/fsctl.h b/inc/winfsp/fsctl.h index 69926f9e..e601dfff 100644 --- a/inc/winfsp/fsctl.h +++ b/inc/winfsp/fsctl.h @@ -269,7 +269,8 @@ typedef struct UINT32 OpenTargetDirectory:1; /* open target dir and report FILE_{EXISTS,DOES_NOT_EXIST} */ UINT32 CaseSensitive:1; /* FileName comparisons should be case-sensitive */ UINT32 HasTrailingBackslash:1; /* FileName had trailing backslash */ - UINT32 ReservedFlags:25; + UINT32 AcceptsSecurityDescriptor:1; + UINT32 ReservedFlags:24; UINT16 NamedStream; /* request targets named stream; colon offset in FileName */ } Create; struct @@ -440,9 +441,11 @@ typedef struct UINT64 UserContext; /* user context associated with file node */ UINT64 UserContext2; /* user context associated with file descriptor (handle) */ UINT32 GrantedAccess; /* FILE_{READ_DATA,WRITE_DATA,etc.} */ + FSP_FSCTL_TRANSACT_BUF SecurityDescriptor; FSP_FSCTL_FILE_INFO FileInfo; FSP_FSCTL_TRANSACT_BUF FileName; UINT32 DisableCache:1; + UINT32 HasSecurityDescriptor:1; } Opened; /* IoStatus.Status == STATUS_REPARSE */ struct diff --git a/src/dll/fsop.c b/src/dll/fsop.c index 0d3c21df..03526194 100644 --- a/src/dll/fsop.c +++ b/src/dll/fsop.c @@ -242,7 +242,8 @@ NTSTATUS FspFileSystemCreateCheck(FSP_FILE_SYSTEM *FileSystem, static inline NTSTATUS FspFileSystemOpenCheck(FSP_FILE_SYSTEM *FileSystem, FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response, - BOOLEAN AllowTraverseCheck, PUINT32 PGrantedAccess) + BOOLEAN AllowTraverseCheck, PUINT32 PGrantedAccess, + PSECURITY_DESCRIPTOR *PSecurityDescriptor) { NTSTATUS Result; UINT32 GrantedAccess; @@ -257,10 +258,11 @@ NTSTATUS FspFileSystemOpenCheck(FSP_FILE_SYSTEM *FileSystem, * requested in DesiredAccess. */ - Result = FspAccessCheck(FileSystem, Request, FALSE, AllowTraverseCheck, + Result = FspAccessCheckEx(FileSystem, Request, FALSE, AllowTraverseCheck, Request->Req.Create.DesiredAccess | ((Request->Req.Create.CreateOptions & FILE_DELETE_ON_CLOSE) ? DELETE : 0), - &GrantedAccess); + &GrantedAccess, + Request->Req.Create.AcceptsSecurityDescriptor ? PSecurityDescriptor : 0); if (STATUS_REPARSE == Result) Result = FspFileSystemCallResolveReparsePoints(FileSystem, Request, Response, GrantedAccess); else if (NT_SUCCESS(Result)) @@ -391,21 +393,40 @@ NTSTATUS FspFileSystemRenameCheck(FSP_FILE_SYSTEM *FileSystem, return Result; } +static inline +VOID FspFileSystemOpCreate_SetOpenDescriptor(FSP_FSCTL_TRANSACT_RSP *Response, + PSECURITY_DESCRIPTOR OpenDescriptor) +{ + FSP_FSCTL_TRANSACT_BUF Buf; + Buf.Offset = FSP_FSCTL_DEFAULT_ALIGN_UP(Response->Rsp.Create.Opened.FileName.Size); + Buf.Size = (UINT16)GetSecurityDescriptorLength(OpenDescriptor); + + if (FSP_FSCTL_TRANSACT_RSP_BUFFER_SIZEMAX >= Buf.Offset + Buf.Size) + { + Response->Size += Buf.Offset + Buf.Size; + Response->Rsp.Create.Opened.SecurityDescriptor.Offset = Buf.Offset; + Response->Rsp.Create.Opened.SecurityDescriptor.Size = Buf.Size; + Response->Rsp.Create.Opened.HasSecurityDescriptor = 1; + memcpy(Response->Buffer + Buf.Offset, OpenDescriptor, Buf.Size); + } +} + static NTSTATUS FspFileSystemOpCreate_FileCreate(FSP_FILE_SYSTEM *FileSystem, FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response) { NTSTATUS Result; UINT32 GrantedAccess; - PSECURITY_DESCRIPTOR ParentDescriptor, ObjectDescriptor; + PSECURITY_DESCRIPTOR ParentDescriptor; FSP_FSCTL_TRANSACT_FULL_CONTEXT FullContext; FSP_FSCTL_OPEN_FILE_INFO OpenFileInfo; + PSECURITY_DESCRIPTOR OpenDescriptor = 0; Result = FspFileSystemCreateCheck(FileSystem, Request, Response, TRUE, &GrantedAccess, &ParentDescriptor); if (!NT_SUCCESS(Result) || STATUS_REPARSE == Result) return Result; - Result = FspCreateSecurityDescriptor(FileSystem, Request, ParentDescriptor, &ObjectDescriptor); + Result = FspCreateSecurityDescriptor(FileSystem, Request, ParentDescriptor, &OpenDescriptor); FspDeleteSecurityDescriptor(ParentDescriptor, FspAccessCheckEx); if (!NT_SUCCESS(Result)) return Result; @@ -417,11 +438,13 @@ static NTSTATUS FspFileSystemOpCreate_FileCreate(FSP_FILE_SYSTEM *FileSystem, OpenFileInfo.NormalizedNameSize = FSP_FSCTL_TRANSACT_RSP_BUFFER_SIZEMAX; Result = FileSystem->Interface->Create(FileSystem, (PWSTR)Request->Buffer, Request->Req.Create.CreateOptions, GrantedAccess, - Request->Req.Create.FileAttributes, ObjectDescriptor, Request->Req.Create.AllocationSize, + Request->Req.Create.FileAttributes, OpenDescriptor, Request->Req.Create.AllocationSize, AddrOfFileContext(FullContext), &OpenFileInfo.FileInfo); - FspDeleteSecurityDescriptor(ObjectDescriptor, FspCreateSecurityDescriptor); if (!NT_SUCCESS(Result)) + { + FspDeleteSecurityDescriptor(OpenDescriptor, FspCreateSecurityDescriptor); return Result; + } if (FSP_FSCTL_TRANSACT_PATH_SIZEMAX >= OpenFileInfo.NormalizedNameSize) { @@ -430,6 +453,12 @@ static NTSTATUS FspFileSystemOpCreate_FileCreate(FSP_FILE_SYSTEM *FileSystem, Response->Rsp.Create.Opened.FileName.Size = (UINT16)OpenFileInfo.NormalizedNameSize; } + if (0 != OpenDescriptor) + { + FspFileSystemOpCreate_SetOpenDescriptor(Response, OpenDescriptor); + FspDeleteSecurityDescriptor(OpenDescriptor, FspCreateSecurityDescriptor); + } + Response->IoStatus.Information = FILE_CREATED; SetFileContext(Response->Rsp.Create.Opened, FullContext); Response->Rsp.Create.Opened.GrantedAccess = GrantedAccess; @@ -445,8 +474,10 @@ static NTSTATUS FspFileSystemOpCreate_FileOpen(FSP_FILE_SYSTEM *FileSystem, UINT32 GrantedAccess; FSP_FSCTL_TRANSACT_FULL_CONTEXT FullContext; FSP_FSCTL_OPEN_FILE_INFO OpenFileInfo; + PSECURITY_DESCRIPTOR OpenDescriptor = 0; - Result = FspFileSystemOpenCheck(FileSystem, Request, Response, TRUE, &GrantedAccess); + Result = FspFileSystemOpenCheck(FileSystem, Request, Response, TRUE, &GrantedAccess, + &OpenDescriptor); if (!NT_SUCCESS(Result) || STATUS_REPARSE == Result) return Result; @@ -459,7 +490,10 @@ static NTSTATUS FspFileSystemOpCreate_FileOpen(FSP_FILE_SYSTEM *FileSystem, (PWSTR)Request->Buffer, Request->Req.Create.CreateOptions, GrantedAccess, AddrOfFileContext(FullContext), &OpenFileInfo.FileInfo); if (!NT_SUCCESS(Result)) + { + FspDeleteSecurityDescriptor(OpenDescriptor, FspAccessCheckEx); return Result; + } if (FSP_FSCTL_TRANSACT_PATH_SIZEMAX >= OpenFileInfo.NormalizedNameSize) { @@ -468,6 +502,12 @@ static NTSTATUS FspFileSystemOpCreate_FileOpen(FSP_FILE_SYSTEM *FileSystem, Response->Rsp.Create.Opened.FileName.Size = (UINT16)OpenFileInfo.NormalizedNameSize; } + if (0 != OpenDescriptor) + { + FspFileSystemOpCreate_SetOpenDescriptor(Response, OpenDescriptor); + FspDeleteSecurityDescriptor(OpenDescriptor, FspAccessCheckEx); + } + Response->IoStatus.Information = FILE_OPENED; SetFileContext(Response->Rsp.Create.Opened, FullContext); Response->Rsp.Create.Opened.GrantedAccess = GrantedAccess; @@ -481,12 +521,14 @@ static NTSTATUS FspFileSystemOpCreate_FileOpenIf(FSP_FILE_SYSTEM *FileSystem, { NTSTATUS Result; UINT32 GrantedAccess; - PSECURITY_DESCRIPTOR ParentDescriptor, ObjectDescriptor; + PSECURITY_DESCRIPTOR ParentDescriptor; FSP_FSCTL_TRANSACT_FULL_CONTEXT FullContext; FSP_FSCTL_OPEN_FILE_INFO OpenFileInfo; + PSECURITY_DESCRIPTOR OpenDescriptor = 0; BOOLEAN Create = FALSE; - Result = FspFileSystemOpenCheck(FileSystem, Request, Response, TRUE, &GrantedAccess); + Result = FspFileSystemOpenCheck(FileSystem, Request, Response, TRUE, &GrantedAccess, + &OpenDescriptor); if (!NT_SUCCESS(Result) || STATUS_REPARSE == Result) { if (STATUS_OBJECT_NAME_NOT_FOUND != Result) @@ -506,6 +548,9 @@ static NTSTATUS FspFileSystemOpCreate_FileOpenIf(FSP_FILE_SYSTEM *FileSystem, AddrOfFileContext(FullContext), &OpenFileInfo.FileInfo); if (!NT_SUCCESS(Result)) { + FspDeleteSecurityDescriptor(OpenDescriptor, FspAccessCheckEx); + OpenDescriptor = 0; + if (STATUS_OBJECT_NAME_NOT_FOUND != Result) return Result; Create = TRUE; @@ -519,7 +564,7 @@ static NTSTATUS FspFileSystemOpCreate_FileOpenIf(FSP_FILE_SYSTEM *FileSystem, if (!NT_SUCCESS(Result) || STATUS_REPARSE == Result) return Result; - Result = FspCreateSecurityDescriptor(FileSystem, Request, ParentDescriptor, &ObjectDescriptor); + Result = FspCreateSecurityDescriptor(FileSystem, Request, ParentDescriptor, &OpenDescriptor); FspDeleteSecurityDescriptor(ParentDescriptor, FspAccessCheckEx); if (!NT_SUCCESS(Result)) return Result; @@ -531,11 +576,13 @@ static NTSTATUS FspFileSystemOpCreate_FileOpenIf(FSP_FILE_SYSTEM *FileSystem, OpenFileInfo.NormalizedNameSize = FSP_FSCTL_TRANSACT_RSP_BUFFER_SIZEMAX; Result = FileSystem->Interface->Create(FileSystem, (PWSTR)Request->Buffer, Request->Req.Create.CreateOptions, GrantedAccess, - Request->Req.Create.FileAttributes, ObjectDescriptor, Request->Req.Create.AllocationSize, + Request->Req.Create.FileAttributes, OpenDescriptor, Request->Req.Create.AllocationSize, AddrOfFileContext(FullContext), &OpenFileInfo.FileInfo); - FspDeleteSecurityDescriptor(ObjectDescriptor, FspCreateSecurityDescriptor); if (!NT_SUCCESS(Result)) + { + FspDeleteSecurityDescriptor(OpenDescriptor, FspCreateSecurityDescriptor); return Result; + } } if (FSP_FSCTL_TRANSACT_PATH_SIZEMAX >= OpenFileInfo.NormalizedNameSize) @@ -545,6 +592,13 @@ static NTSTATUS FspFileSystemOpCreate_FileOpenIf(FSP_FILE_SYSTEM *FileSystem, Response->Rsp.Create.Opened.FileName.Size = (UINT16)OpenFileInfo.NormalizedNameSize; } + if (0 != OpenDescriptor) + { + FspFileSystemOpCreate_SetOpenDescriptor(Response, OpenDescriptor); + FspDeleteSecurityDescriptor(OpenDescriptor, Create ? + (NTSTATUS (*)())FspCreateSecurityDescriptor : (NTSTATUS (*)())FspAccessCheckEx); + } + Response->IoStatus.Information = Create ? FILE_CREATED : FILE_OPENED; SetFileContext(Response->Rsp.Create.Opened, FullContext); Response->Rsp.Create.Opened.GrantedAccess = GrantedAccess; diff --git a/src/sys/create.c b/src/sys/create.c index d30592ee..c0780ded 100644 --- a/src/sys/create.c +++ b/src/sys/create.c @@ -96,7 +96,11 @@ enum RequestFileObject = 2, RequestState = 3, - /* RequestState */ + /* TryOpen RequestState */ + RequestFlushImage = 1, + RequestAcceptsSecurityDescriptor = 2, + + /* Overwrite RequestState */ RequestPending = 0, RequestProcessing = 1, }; @@ -602,6 +606,9 @@ static NTSTATUS FspFsvolCreateNoLock( Request->Req.Create.HasTrailingBackslash = HasTrailingBackslash; Request->Req.Create.NamedStream = MainFileName.Length; + Request->Req.Create.AcceptsSecurityDescriptor = 0 == Request->Req.Create.NamedStream && + !!FsvolDeviceExtension->VolumeParams.AllowOpenInKernelMode; + ASSERT( 0 == StreamPart.Length && 0 == MainFileName.Length || 0 != StreamPart.Length && 0 != MainFileName.Length); @@ -1110,7 +1117,8 @@ NTSTATUS FspFsvolCreateComplete( * A Reserved request is a special request used when retrying a file open. */ - BOOLEAN FlushImage = 0 != FspIopRequestContext(Request, RequestState); + BOOLEAN FlushImage = + 0 != (RequestFlushImage & (UINT_PTR)FspIopRequestContext(Request, RequestState)); Result = FspFsvolCreateTryOpen(Irp, Response, FileNode, FileDesc, FileObject, FlushImage); } @@ -1178,7 +1186,9 @@ static NTSTATUS FspFsvolCreateTryOpen(PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Re FspIopRequestContext(Request, RequestDeviceObject) = RequestDeviceObjectValue; FspIopRequestContext(Request, RequestFileDesc) = FileDesc; FspIopRequestContext(Request, RequestFileObject) = FileObject; - FspIopRequestContext(Request, RequestState) = (PVOID)(UINT_PTR)FlushImage; + FspIopRequestContext(Request, RequestState) = (PVOID)(UINT_PTR)( + (FlushImage ? RequestFlushImage : 0) | + (Request->Req.Create.AcceptsSecurityDescriptor ? RequestAcceptsSecurityDescriptor : 0)); } Result = STATUS_SUCCESS; @@ -1199,8 +1209,28 @@ static NTSTATUS FspFsvolCreateTryOpen(PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Re return Result; } + PSECURITY_DESCRIPTOR OpenDescriptor = 0; + ULONG OpenDescriptorSize = 0; + if (0 != (RequestAcceptsSecurityDescriptor & + (UINT_PTR)FspIopRequestContext(Request, RequestState)) && + Response->Rsp.Create.Opened.HasSecurityDescriptor && + 0 < Response->Rsp.Create.Opened.SecurityDescriptor.Size && + Response->Buffer + + Response->Rsp.Create.Opened.SecurityDescriptor.Offset + + Response->Rsp.Create.Opened.SecurityDescriptor.Size <= + (PUINT8)Response + Response->Size && + RtlValidRelativeSecurityDescriptor( + (PUINT8)Response->Buffer + + Response->Rsp.Create.Opened.SecurityDescriptor.Offset, + Response->Rsp.Create.Opened.SecurityDescriptor.Size, 0)) + { + OpenDescriptor = (PSECURITY_DESCRIPTOR)(Response->Buffer + + Response->Rsp.Create.Opened.SecurityDescriptor.Offset); + OpenDescriptorSize = Response->Rsp.Create.Opened.SecurityDescriptor.Size; + } + /* - * FspFileNodeTrySetFileInfoOnOpen sets the FileNode's metadata to values reported + * FspFileNodeTrySetFileInfoAndSecurityOnOpen sets the FileNode's metadata to values reported * by the user mode file system. It does so only if the file is not already open; the * reason is that there is a subtle race condition otherwise. * @@ -1231,12 +1261,13 @@ static NTSTATUS FspFsvolCreateTryOpen(PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Re * example, Explorer often opens files to get information about them and may inappropriately * update the FSD view of the file size during WRITE's. * - * FspFileNodeTrySetFileInfoOnOpen attempts to mitigate this problem by only updating the - * FileInfo if the file is not already open. This avoids placing stale information in the + * FspFileNodeTrySetFileInfoAndSecurityOnOpen attempts to mitigate this problem by only updating + * the FileInfo if the file is not already open. This avoids placing stale information in the * FileNode. */ - FspFileNodeTrySetFileInfoOnOpen(FileNode, FileObject, &Response->Rsp.Create.Opened.FileInfo, + FspFileNodeTrySetFileInfoAndSecurityOnOpen(FileNode, FileObject, + &Response->Rsp.Create.Opened.FileInfo, OpenDescriptor, OpenDescriptorSize, FILE_CREATED == Response->IoStatus.Information); if (FlushImage) diff --git a/src/sys/driver.h b/src/sys/driver.h index 6335270d..9f9d56d5 100644 --- a/src/sys/driver.h +++ b/src/sys/driver.h @@ -1386,12 +1386,14 @@ NTSTATUS FspFileNodeRenameCheck(PDEVICE_OBJECT FsvolDeviceObject, PIRP OplockIrp VOID FspFileNodeRename(FSP_FILE_NODE *FileNode, PUNICODE_STRING NewFileName); VOID FspFileNodeGetFileInfo(FSP_FILE_NODE *FileNode, FSP_FSCTL_FILE_INFO *FileInfo); BOOLEAN FspFileNodeTryGetFileInfo(FSP_FILE_NODE *FileNode, FSP_FSCTL_FILE_INFO *FileInfo); -BOOLEAN FspFileNodeTryGetFileInfoByName(PDEVICE_OBJECT FsvolDeviceObject, +BOOLEAN FspFileNodeTryGetFileInfoByName(PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PUNICODE_STRING FileName, FSP_FSCTL_FILE_INFO *FileInfo); VOID FspFileNodeSetFileInfo(FSP_FILE_NODE *FileNode, PFILE_OBJECT CcFileObject, const FSP_FSCTL_FILE_INFO *FileInfo, BOOLEAN TruncateOnClose); -BOOLEAN FspFileNodeTrySetFileInfoOnOpen(FSP_FILE_NODE *FileNode, PFILE_OBJECT CcFileObject, - const FSP_FSCTL_FILE_INFO *FileInfo, BOOLEAN TruncateOnClose); +BOOLEAN FspFileNodeTrySetFileInfoAndSecurityOnOpen(FSP_FILE_NODE *FileNode, PFILE_OBJECT CcFileObject, + const FSP_FSCTL_FILE_INFO *FileInfo, + const PSECURITY_DESCRIPTOR SecurityDescriptor, ULONG SecurityDescriptorSize, + BOOLEAN TruncateOnClose); BOOLEAN FspFileNodeTrySetFileInfo(FSP_FILE_NODE *FileNode, PFILE_OBJECT CcFileObject, const FSP_FSCTL_FILE_INFO *FileInfo, ULONG InfoChangeNumber); VOID FspFileNodeInvalidateFileInfo(FSP_FILE_NODE *FileNode); diff --git a/src/sys/file.c b/src/sys/file.c index ffed3cff..d03bf84f 100644 --- a/src/sys/file.c +++ b/src/sys/file.c @@ -61,12 +61,14 @@ NTSTATUS FspFileNodeRenameCheck(PDEVICE_OBJECT FsvolDeviceObject, PIRP OplockIrp VOID FspFileNodeRename(FSP_FILE_NODE *FileNode, PUNICODE_STRING NewFileName); VOID FspFileNodeGetFileInfo(FSP_FILE_NODE *FileNode, FSP_FSCTL_FILE_INFO *FileInfo); BOOLEAN FspFileNodeTryGetFileInfo(FSP_FILE_NODE *FileNode, FSP_FSCTL_FILE_INFO *FileInfo); -BOOLEAN FspFileNodeTryGetFileInfoByName(PDEVICE_OBJECT FsvolDeviceObject, +BOOLEAN FspFileNodeTryGetFileInfoByName(PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PUNICODE_STRING FileName, FSP_FSCTL_FILE_INFO *FileInfo); VOID FspFileNodeSetFileInfo(FSP_FILE_NODE *FileNode, PFILE_OBJECT CcFileObject, const FSP_FSCTL_FILE_INFO *FileInfo, BOOLEAN TruncateOnClose); -BOOLEAN FspFileNodeTrySetFileInfoOnOpen(FSP_FILE_NODE *FileNode, PFILE_OBJECT CcFileObject, - const FSP_FSCTL_FILE_INFO *FileInfo, BOOLEAN TruncateOnClose); +BOOLEAN FspFileNodeTrySetFileInfoAndSecurityOnOpen(FSP_FILE_NODE *FileNode, PFILE_OBJECT CcFileObject, + const FSP_FSCTL_FILE_INFO *FileInfo, + const PSECURITY_DESCRIPTOR SecurityDescriptor, ULONG SecurityDescriptorSize, + BOOLEAN TruncateOnClose); BOOLEAN FspFileNodeTrySetFileInfo(FSP_FILE_NODE *FileNode, PFILE_OBJECT CcFileObject, const FSP_FSCTL_FILE_INFO *FileInfo, ULONG InfoChangeNumber); VOID FspFileNodeInvalidateFileInfo(FSP_FILE_NODE *FileNode); @@ -140,7 +142,7 @@ VOID FspFileNodeOplockComplete(PVOID Context, PIRP Irp); #pragma alloc_text(PAGE, FspFileNodeTryGetFileInfo) #pragma alloc_text(PAGE, FspFileNodeTryGetFileInfoByName) #pragma alloc_text(PAGE, FspFileNodeSetFileInfo) -#pragma alloc_text(PAGE, FspFileNodeTrySetFileInfoOnOpen) +#pragma alloc_text(PAGE, FspFileNodeTrySetFileInfoAndSecurityOnOpen) #pragma alloc_text(PAGE, FspFileNodeTrySetFileInfo) #pragma alloc_text(PAGE, FspFileNodeInvalidateFileInfo) #pragma alloc_text(PAGE, FspFileNodeReferenceSecurity) @@ -1643,14 +1645,33 @@ BOOLEAN FspFileNodeTryGetFileInfo(FSP_FILE_NODE *FileNode, FSP_FSCTL_FILE_INFO * return TRUE; } -BOOLEAN FspFileNodeTryGetFileInfoByName(PDEVICE_OBJECT FsvolDeviceObject, +BOOLEAN FspFileNodeTryGetFileInfoByName(PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PUNICODE_STRING FileName, FSP_FSCTL_FILE_INFO *FileInfo) { PAGED_CODE(); + PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); + PACCESS_STATE AccessState = IrpSp->Parameters.Create.SecurityContext->AccessState; + ACCESS_MASK DesiredAccess = AccessState->RemainingDesiredAccess; + ACCESS_MASK GrantedAccess = AccessState->PreviouslyGrantedAccess; + KPROCESSOR_MODE RequestorMode = + FlagOn(IrpSp->Flags, SL_FORCE_ACCESS_CHECK) ? UserMode : Irp->RequestorMode; + BOOLEAN HasTraversePrivilege = + BooleanFlagOn(AccessState->Flags, TOKEN_HAS_TRAVERSE_PRIVILEGE); FSP_FILE_NODE *FileNode; + PVOID SecurityBuffer; BOOLEAN Result; + if (UserMode == RequestorMode) + { + /* user mode: allow only FILE_READ_ATTRIBUTES with traverse privilege */ + if (FILE_READ_ATTRIBUTES != DesiredAccess || !HasTraversePrivilege) + return FALSE; + } + else + /* kernel mode: anything goes! */ + DesiredAccess = 0; + FspFsvolDeviceLockContextTable(FsvolDeviceObject); FileNode = FspFsvolDeviceLookupContextByName(FsvolDeviceObject, FileName); if (0 != FileNode) @@ -1661,7 +1682,34 @@ BOOLEAN FspFileNodeTryGetFileInfoByName(PDEVICE_OBJECT FsvolDeviceObject, if (0 != FileNode) { FspFileNodeAcquireShared(FileNode, Main); - Result = FspFileNodeTryGetFileInfo(FileNode, FileInfo); + + if (0 != DesiredAccess) + { + ASSERT(FILE_READ_ATTRIBUTES == DesiredAccess); + + if (FspFileNodeReferenceSecurity(FileNode, &SecurityBuffer, 0)) + { + NTSTATUS AccessStatus; + Result = SeAccessCheck( + SecurityBuffer, + &AccessState->SubjectSecurityContext, + TRUE, + DesiredAccess, + GrantedAccess, + 0, + IoGetFileObjectGenericMapping(), + RequestorMode, + &GrantedAccess, + &AccessStatus); + + FspFileNodeDereferenceSecurity(SecurityBuffer); + + Result = Result && FspFileNodeTryGetFileInfo(FileNode, FileInfo); + } + } + else + Result = FspFileNodeTryGetFileInfo(FileNode, FileInfo); + FspFileNodeRelease(FileNode, Main); FspFileNodeDereference(FileNode); } @@ -1779,8 +1827,10 @@ VOID FspFileNodeSetFileInfo(FSP_FILE_NODE *FileNode, PFILE_OBJECT CcFileObject, } } -BOOLEAN FspFileNodeTrySetFileInfoOnOpen(FSP_FILE_NODE *FileNode, PFILE_OBJECT CcFileObject, - const FSP_FSCTL_FILE_INFO *FileInfo, BOOLEAN TruncateOnClose) +BOOLEAN FspFileNodeTrySetFileInfoAndSecurityOnOpen(FSP_FILE_NODE *FileNode, PFILE_OBJECT CcFileObject, + const FSP_FSCTL_FILE_INFO *FileInfo, + const PSECURITY_DESCRIPTOR SecurityDescriptor, ULONG SecurityDescriptorSize, + BOOLEAN TruncateOnClose) { PAGED_CODE(); @@ -1813,6 +1863,8 @@ BOOLEAN FspFileNodeTrySetFileInfoOnOpen(FSP_FILE_NODE *FileNode, PFILE_OBJECT Cc } FspFileNodeSetFileInfo(FileNode, CcFileObject, FileInfo, TruncateOnClose); + if (0 != SecurityDescriptor) + FspFileNodeSetSecurity(FileNode, SecurityDescriptor, SecurityDescriptorSize); return TRUE; } diff --git a/src/sys/fileinfo.c b/src/sys/fileinfo.c index 9835755a..44f1319c 100644 --- a/src/sys/fileinfo.c +++ b/src/sys/fileinfo.c @@ -1910,7 +1910,7 @@ BOOLEAN FspFastIoQueryOpen( if (0 != FileObject->RelatedFileObject) FSP_RETURN(Result = FALSE); - Result = FspFileNodeTryGetFileInfoByName(DeviceObject, &FileObject->FileName, &FileInfoBuf); + Result = FspFileNodeTryGetFileInfoByName(DeviceObject, Irp, &FileObject->FileName, &FileInfoBuf); if (Result) { PVOID Buffer = Info;