diff --git a/inc/winfsp/fsctl.h b/inc/winfsp/fsctl.h index c5336cc1..677ce3f3 100644 --- a/inc/winfsp/fsctl.h +++ b/inc/winfsp/fsctl.h @@ -153,7 +153,7 @@ typedef struct UINT32 FileAttributes; /* file attributes for new files */ 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 */ + UINT64 AccessToken; /* request access token (HANDLE) */ UINT32 DesiredAccess; /* FILE_{READ_DATA,WRITE_DATA,etc.} */ UINT32 ShareAccess; /* FILE_SHARE_{READ,WRITE,DELETE} */ FSP_FSCTL_TRANSACT_BUF Ea; /* reserved; not currently implemented */ @@ -240,6 +240,7 @@ typedef struct UINT64 UserContext; UINT64 UserContext2; UINT32 SecurityInformation; + UINT64 AccessToken; /* request access token (HANDLE) */ FSP_FSCTL_TRANSACT_BUF SecurityDescriptor; } SetSecurity; } Req; diff --git a/inc/winfsp/winfsp.h b/inc/winfsp/winfsp.h index 9920e37a..dbad3ed1 100644 --- a/inc/winfsp/winfsp.h +++ b/inc/winfsp/winfsp.h @@ -95,7 +95,7 @@ typedef struct _FSP_FILE_SYSTEM_INTERFACE NTSTATUS (*SetSecurity)(FSP_FILE_SYSTEM *FileSystem, FSP_FSCTL_TRANSACT_REQ *Request, PVOID FileNode, - PSECURITY_DESCRIPTOR SecurityDescriptor); + SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR SecurityDescriptor); } FSP_FILE_SYSTEM_INTERFACE; typedef struct _FSP_FILE_SYSTEM { @@ -196,10 +196,14 @@ FSP_API NTSTATUS FspAccessCheckEx(FSP_FILE_SYSTEM *FileSystem, BOOLEAN CheckParentDirectory, BOOLEAN AllowTraverseCheck, UINT32 DesiredAccess, PUINT32 PGrantedAccess, PSECURITY_DESCRIPTOR *PSecurityDescriptor); -FSP_API NTSTATUS FspAssignSecurity(FSP_FILE_SYSTEM *FileSystem, +FSP_API NTSTATUS FspCreateSecurityDescriptor(FSP_FILE_SYSTEM *FileSystem, FSP_FSCTL_TRANSACT_REQ *Request, PSECURITY_DESCRIPTOR ParentDescriptor, PSECURITY_DESCRIPTOR *PSecurityDescriptor); +FSP_API NTSTATUS FspSetSecurityDescriptor(FSP_FILE_SYSTEM *FileSystem, + FSP_FSCTL_TRANSACT_REQ *Request, + PSECURITY_DESCRIPTOR InputDescriptor, + PSECURITY_DESCRIPTOR *PSecurityDescriptor); FSP_API VOID FspDeleteSecurityDescriptor(PSECURITY_DESCRIPTOR SecurityDescriptor, NTSTATUS (*CreateFunc)()); static inline diff --git a/src/dll/access.c b/src/dll/access.c index a2b73537..f6d024e6 100644 --- a/src/dll/access.c +++ b/src/dll/access.c @@ -47,6 +47,9 @@ FSP_API NTSTATUS FspAccessCheckEx(FSP_FILE_SYSTEM *FileSystem, if (0 != PSecurityDescriptor) *PSecurityDescriptor = 0; + if (FspFsctlTransactCreateKind != Request->Kind) + return STATUS_INVALID_PARAMETER; + if (0 == FileSystem->Interface->GetSecurityByName || (!Request->Req.Create.UserMode && 0 == PSecurityDescriptor)) { @@ -202,13 +205,16 @@ exit: return Result; } -FSP_API NTSTATUS FspAssignSecurity(FSP_FILE_SYSTEM *FileSystem, +FSP_API NTSTATUS FspCreateSecurityDescriptor(FSP_FILE_SYSTEM *FileSystem, FSP_FSCTL_TRANSACT_REQ *Request, PSECURITY_DESCRIPTOR ParentDescriptor, PSECURITY_DESCRIPTOR *PSecurityDescriptor) { *PSecurityDescriptor = 0; + if (FspFsctlTransactCreateKind != Request->Kind) + return STATUS_INVALID_PARAMETER; + if (!CreatePrivateObjectSecurity( ParentDescriptor, 0 != Request->Req.Create.SecurityDescriptor.Offset ? @@ -224,11 +230,75 @@ FSP_API NTSTATUS FspAssignSecurity(FSP_FILE_SYSTEM *FileSystem, return STATUS_SUCCESS; } +FSP_API NTSTATUS FspSetSecurityDescriptor(FSP_FILE_SYSTEM *FileSystem, + FSP_FSCTL_TRANSACT_REQ *Request, + PSECURITY_DESCRIPTOR InputDescriptor, + PSECURITY_DESCRIPTOR *PSecurityDescriptor) +{ + *PSecurityDescriptor = 0; + + if (FspFsctlTransactSetSecurityKind != Request->Kind) + return STATUS_INVALID_PARAMETER; + + if (0 == InputDescriptor) + return STATUS_NO_SECURITY_ON_OBJECT; + + /* + * SetPrivateObjectSecurity is a broken API. It assumes that the passed + * descriptor resides on memory allocated by CreatePrivateObjectSecurity + * or SetPrivateObjectSecurity and frees the descriptor on success. + * + * In our case the security descriptor comes from the user mode file system, + * which may conjure it any way it sees fit. So we have to somehow make a copy + * of the InputDescriptor and place it in memory that SetPrivateObjectSecurity + * can then free. To complicate matters there is no API that can be used for + * this purpose. What a PITA! + */ + /* !!!: HACK! HACK! HACK! + * + * Turns out that SetPrivateObjectSecurity and friends really use RtlProcessHeap + * internally, which is just another name for GetProcessHeap(). + * + * I wish there was a cleaner way to do this! + */ + + HANDLE ProcessHeap = GetProcessHeap(); + DWORD InputDescriptorSize = GetSecurityDescriptorLength(InputDescriptor); + PSECURITY_DESCRIPTOR CopiedDescriptor; + + CopiedDescriptor = HeapAlloc(ProcessHeap, 0, InputDescriptorSize); + if (0 == CopiedDescriptor) + return STATUS_INSUFFICIENT_RESOURCES; + memcpy(CopiedDescriptor, InputDescriptor, InputDescriptorSize); + InputDescriptor = CopiedDescriptor; + + if (!SetPrivateObjectSecurity( + Request->Req.SetSecurity.SecurityInformation, + (PVOID)Request->Buffer, + &InputDescriptor, + &FspFileGenericMapping, + (HANDLE)Request->Req.SetSecurity.AccessToken)) + { + HeapFree(ProcessHeap, 0, CopiedDescriptor); + return FspNtStatusFromWin32(GetLastError()); + } + + /* CopiedDescriptor has been freed by SetPrivateObjectSecurity! */ + + *PSecurityDescriptor = InputDescriptor; + + DEBUGLOGSD("SDDL=%s", *PSecurityDescriptor); + + return STATUS_SUCCESS; +} + FSP_API VOID FspDeleteSecurityDescriptor(PSECURITY_DESCRIPTOR SecurityDescriptor, - NTSTATUS(*CreateFunc)()) + NTSTATUS (*CreateFunc)()) { if ((NTSTATUS (*)())FspAccessCheckEx == CreateFunc) MemFree(SecurityDescriptor); - else if ((NTSTATUS (*)())FspAssignSecurity == CreateFunc) + else + if ((NTSTATUS (*)())FspCreateSecurityDescriptor == CreateFunc || + (NTSTATUS (*)())FspSetSecurityDescriptor == CreateFunc) DestroyPrivateObjectSecurity(&SecurityDescriptor); } diff --git a/src/dll/fsop.c b/src/dll/fsop.c index 303e29e2..48d9eccd 100644 --- a/src/dll/fsop.c +++ b/src/dll/fsop.c @@ -83,7 +83,7 @@ static NTSTATUS FspFileSystemOpCreate_FileCreate(FSP_FILE_SYSTEM *FileSystem, if (!NT_SUCCESS(Result)) return Result; - Result = FspAssignSecurity(FileSystem, Request, ParentDescriptor, &ObjectDescriptor); + Result = FspCreateSecurityDescriptor(FileSystem, Request, ParentDescriptor, &ObjectDescriptor); FspDeleteSecurityDescriptor(ParentDescriptor, FspAccessCheckEx); if (!NT_SUCCESS(Result)) return Result; @@ -94,7 +94,7 @@ static NTSTATUS FspFileSystemOpCreate_FileCreate(FSP_FILE_SYSTEM *FileSystem, (PWSTR)Request->Buffer, Request->Req.Create.CaseSensitive, Request->Req.Create.CreateOptions, Request->Req.Create.FileAttributes, ObjectDescriptor, Request->Req.Create.AllocationSize, &FileNode, &FileInfo); - FspDeleteSecurityDescriptor(ObjectDescriptor, FspAssignSecurity); + FspDeleteSecurityDescriptor(ObjectDescriptor, FspCreateSecurityDescriptor); if (!NT_SUCCESS(Result)) return Result; @@ -171,7 +171,7 @@ static NTSTATUS FspFileSystemOpCreate_FileOpenIf(FSP_FILE_SYSTEM *FileSystem, if (!NT_SUCCESS(Result)) return Result; - Result = FspAssignSecurity(FileSystem, Request, ParentDescriptor, &ObjectDescriptor); + Result = FspCreateSecurityDescriptor(FileSystem, Request, ParentDescriptor, &ObjectDescriptor); FspDeleteSecurityDescriptor(ParentDescriptor, FspAccessCheckEx); if (!NT_SUCCESS(Result)) return Result; @@ -182,7 +182,7 @@ static NTSTATUS FspFileSystemOpCreate_FileOpenIf(FSP_FILE_SYSTEM *FileSystem, (PWSTR)Request->Buffer, Request->Req.Create.CaseSensitive, Request->Req.Create.CreateOptions, Request->Req.Create.FileAttributes, ObjectDescriptor, Request->Req.Create.AllocationSize, &FileNode, &FileInfo); - FspDeleteSecurityDescriptor(ObjectDescriptor, FspAssignSecurity); + FspDeleteSecurityDescriptor(ObjectDescriptor, FspCreateSecurityDescriptor); if (!NT_SUCCESS(Result)) return Result; } @@ -261,7 +261,7 @@ static NTSTATUS FspFileSystemOpCreate_FileOverwriteIf(FSP_FILE_SYSTEM *FileSyste if (!NT_SUCCESS(Result)) return Result; - Result = FspAssignSecurity(FileSystem, Request, ParentDescriptor, &ObjectDescriptor); + Result = FspCreateSecurityDescriptor(FileSystem, Request, ParentDescriptor, &ObjectDescriptor); FspDeleteSecurityDescriptor(ParentDescriptor, FspAccessCheckEx); if (!NT_SUCCESS(Result)) return Result; @@ -272,7 +272,7 @@ static NTSTATUS FspFileSystemOpCreate_FileOverwriteIf(FSP_FILE_SYSTEM *FileSyste (PWSTR)Request->Buffer, Request->Req.Create.CaseSensitive, Request->Req.Create.CreateOptions, Request->Req.Create.FileAttributes, ObjectDescriptor, Request->Req.Create.AllocationSize, &FileNode, &FileInfo); - FspDeleteSecurityDescriptor(ObjectDescriptor, FspAssignSecurity); + FspDeleteSecurityDescriptor(ObjectDescriptor, FspCreateSecurityDescriptor); if (!NT_SUCCESS(Result)) return Result; } @@ -544,22 +544,32 @@ FSP_API NTSTATUS FspFileSystemOpQuerySecurity(FSP_FILE_SYSTEM *FileSystem, FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response) { NTSTATUS Result; + SIZE_T SecurityDescriptorSize; if (0 == FileSystem->Interface->GetSecurity) return STATUS_INVALID_DEVICE_REQUEST; - (VOID)Result; - return STATUS_INVALID_DEVICE_REQUEST; + SecurityDescriptorSize = FSP_FSCTL_TRANSACT_RSP_SIZEMAX - sizeof *Response; + Result = FileSystem->Interface->GetSecurity(FileSystem, Request, + (PVOID)Request->Req.QuerySecurity.UserContext, + Response->Buffer, &SecurityDescriptorSize); + if (!NT_SUCCESS(Result)) + return STATUS_BUFFER_OVERFLOW != Result ? Result : STATUS_INVALID_SECURITY_DESCR; + + Response->Size = (UINT16)(sizeof *Response + SecurityDescriptorSize); + Response->Rsp.QuerySecurity.SecurityDescriptor.Offset = 0; + Response->Rsp.QuerySecurity.SecurityDescriptor.Size = (UINT16)SecurityDescriptorSize; + return STATUS_SUCCESS; } FSP_API NTSTATUS FspFileSystemOpSetSecurity(FSP_FILE_SYSTEM *FileSystem, FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response) { - NTSTATUS Result; - if (0 == FileSystem->Interface->SetSecurity) return STATUS_INVALID_DEVICE_REQUEST; - (VOID)Result; - return STATUS_INVALID_DEVICE_REQUEST; + return FileSystem->Interface->SetSecurity(FileSystem, Request, + (PVOID)Request->Req.SetSecurity.UserContext, + Request->Req.SetSecurity.SecurityInformation, + (PSECURITY_DESCRIPTOR)Request->Buffer); } diff --git a/src/sys/driver.c b/src/sys/driver.c index e465798d..adefa090 100644 --- a/src/sys/driver.c +++ b/src/sys/driver.c @@ -86,6 +86,7 @@ NTSTATUS DriverEntry( FspIopCompleteFunction[IRP_MJ_LOCK_CONTROL] = FspFsvolLockControlComplete; FspIopCompleteFunction[IRP_MJ_CLEANUP] = FspFsvolCleanupComplete; FspIopCompleteFunction[IRP_MJ_QUERY_SECURITY] = FspFsvolQuerySecurityComplete; + FspIopPrepareFunction[IRP_MJ_SET_SECURITY] = FspFsvolSetSecurityPrepare; FspIopCompleteFunction[IRP_MJ_SET_SECURITY] = FspFsvolSetSecurityComplete; /* setup fast I/O and resource acquisition */ diff --git a/src/sys/driver.h b/src/sys/driver.h index 17db4c85..31ce764a 100644 --- a/src/sys/driver.h +++ b/src/sys/driver.h @@ -258,6 +258,7 @@ FSP_IOCMPL_DISPATCH FspFsvolQueryVolumeInformationComplete; FSP_IOCMPL_DISPATCH FspFsvolReadComplete; FSP_IOCMPL_DISPATCH FspFsvolSetEaComplete; FSP_IOCMPL_DISPATCH FspFsvolSetInformationComplete; +FSP_IOPREP_DISPATCH FspFsvolSetSecurityPrepare; FSP_IOCMPL_DISPATCH FspFsvolSetSecurityComplete; FSP_IOCMPL_DISPATCH FspFsvolSetVolumeInformationComplete; FSP_IOCMPL_DISPATCH FspFsvolShutdownComplete; diff --git a/src/sys/security.c b/src/sys/security.c index 2cbd22c1..b465d1de 100644 --- a/src/sys/security.c +++ b/src/sys/security.c @@ -9,19 +9,23 @@ static NTSTATUS FspFsvolQuerySecurity( PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp); FSP_IOCMPL_DISPATCH FspFsvolQuerySecurityComplete; +static FSP_IOP_REQUEST_FINI FspFsvolQuerySecurityRequestFini; static NTSTATUS FspFsvolSetSecurity( PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp); +FSP_IOPREP_DISPATCH FspFsvolSetSecurityPrepare; FSP_IOCMPL_DISPATCH FspFsvolSetSecurityComplete; -static FSP_IOP_REQUEST_FINI FspFsvolSecurityRequestFini; +static FSP_IOP_REQUEST_FINI FspFsvolSetSecurityRequestFini; FSP_DRIVER_DISPATCH FspQuerySecurity; FSP_DRIVER_DISPATCH FspSetSecurity; #ifdef ALLOC_PRAGMA #pragma alloc_text(PAGE, FspFsvolQuerySecurity) #pragma alloc_text(PAGE, FspFsvolQuerySecurityComplete) +#pragma alloc_text(PAGE, FspFsvolQuerySecurityRequestFini) #pragma alloc_text(PAGE, FspFsvolSetSecurity) +#pragma alloc_text(PAGE, FspFsvolSetSecurityPrepare) #pragma alloc_text(PAGE, FspFsvolSetSecurityComplete) -#pragma alloc_text(PAGE, FspFsvolSecurityRequestFini) +#pragma alloc_text(PAGE, FspFsvolSetSecurityRequestFini) #pragma alloc_text(PAGE, FspQuerySecurity) #pragma alloc_text(PAGE, FspSetSecurity) #endif @@ -34,6 +38,8 @@ enum /* SetSecurity */ //RequestFileNode = 0, + RequestAccessToken = 2, + RequestProcess = 3, }; static NTSTATUS FspFsvolQuerySecurity( @@ -72,7 +78,7 @@ static NTSTATUS FspFsvolQuerySecurity( FSP_FSCTL_TRANSACT_REQ *Request; - Result = FspIopCreateRequestEx(Irp, 0, 0, FspFsvolSecurityRequestFini, &Request); + Result = FspIopCreateRequestEx(Irp, 0, 0, FspFsvolQuerySecurityRequestFini, &Request); if (!NT_SUCCESS(Result)) { FspFileNodeRelease(FileNode, Full); @@ -158,6 +164,16 @@ NTSTATUS FspFsvolQuerySecurityComplete( IrpSp->FileObject, IrpSp->Parameters.QuerySecurity.SecurityInformation); } +static VOID FspFsvolQuerySecurityRequestFini(FSP_FSCTL_TRANSACT_REQ *Request, PVOID Context[4]) +{ + PAGED_CODE(); + + FSP_FILE_NODE *FileNode = Context[RequestFileNode]; + + if (0 != FileNode) + FspFileNodeReleaseOwner(FileNode, Full, Request); +} + static NTSTATUS FspFsvolSetSecurity( PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp) { @@ -188,7 +204,7 @@ static NTSTATUS FspFsvolSetSecurity( FSP_FSCTL_TRANSACT_REQ *Request; - Result = FspIopCreateRequestEx(Irp, 0, SecurityDescriptorSize, FspFsvolSecurityRequestFini, + Result = FspIopCreateRequestEx(Irp, 0, SecurityDescriptorSize, FspFsvolSetSecurityRequestFini, &Request); if (!NT_SUCCESS(Result)) { @@ -210,6 +226,53 @@ static NTSTATUS FspFsvolSetSecurity( return FSP_STATUS_IOQ_POST; } +NTSTATUS FspFsvolSetSecurityPrepare( + PIRP Irp, FSP_FSCTL_TRANSACT_REQ *Request) +{ + PAGED_CODE(); + + NTSTATUS Result; + SECURITY_SUBJECT_CONTEXT SecuritySubjectContext; + SECURITY_QUALITY_OF_SERVICE SecurityQualityOfService; + SECURITY_CLIENT_CONTEXT SecurityClientContext; + HANDLE UserModeAccessToken; + PEPROCESS Process; + + /* duplicate the subject context access token into an impersonation token */ + SecurityQualityOfService.Length = sizeof SecurityQualityOfService; + SecurityQualityOfService.ImpersonationLevel = SecurityIdentification; + SecurityQualityOfService.ContextTrackingMode = SECURITY_STATIC_TRACKING; + SecurityQualityOfService.EffectiveOnly = FALSE; + SeCaptureSubjectContext(&SecuritySubjectContext); + SeLockSubjectContext(&SecuritySubjectContext); + Result = SeCreateClientSecurityFromSubjectContext(&SecuritySubjectContext, + &SecurityQualityOfService, FALSE, &SecurityClientContext); + SeUnlockSubjectContext(&SecuritySubjectContext); + SeReleaseSubjectContext(&SecuritySubjectContext); + if (!NT_SUCCESS(Result)) + return Result; + + ASSERT(TokenImpersonation == SeTokenType(SecurityClientContext.ClientToken)); + + /* get a user-mode handle to the impersonation token */ + Result = ObOpenObjectByPointer(SecurityClientContext.ClientToken, + 0, 0, TOKEN_QUERY, *SeTokenObjectType, UserMode, &UserModeAccessToken); + SeDeleteClientSecurity(&SecurityClientContext); + if (!NT_SUCCESS(Result)) + return Result; + + /* get a pointer to the current process so that we can close the impersonation 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.SetSecurity.AccessToken = (UINT_PTR)UserModeAccessToken; + + return STATUS_SUCCESS; +} + NTSTATUS FspFsvolSetSecurityComplete( PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response) { @@ -252,14 +315,40 @@ NTSTATUS FspFsvolSetSecurityComplete( IrpSp->FileObject, IrpSp->Parameters.SetSecurity.SecurityInformation); } -static VOID FspFsvolSecurityRequestFini(FSP_FSCTL_TRANSACT_REQ *Request, PVOID Context[4]) +static VOID FspFsvolSetSecurityRequestFini(FSP_FSCTL_TRANSACT_REQ *Request, PVOID Context[4]) { PAGED_CODE(); FSP_FILE_NODE *FileNode = Context[RequestFileNode]; + HANDLE AccessToken = Context[RequestAccessToken]; + PEPROCESS Process = Context[RequestProcess]; if (0 != FileNode) FspFileNodeReleaseOwner(FileNode, Full, Request); + + if (0 != AccessToken) + { + KAPC_STATE ApcState; + BOOLEAN Attach; + + ASSERT(0 != Process); + Attach = Process != PsGetCurrentProcess(); + + if (Attach) + KeStackAttachProcess(Process, &ApcState); +#if DBG + NTSTATUS Result0; + Result0 = ObCloseHandle(AccessToken, UserMode); + if (!NT_SUCCESS(Result0)) + DEBUGLOG("ObCloseHandle() = %s", NtStatusSym(Result0)); +#else + ObCloseHandle(AccessToken, UserMode); +#endif + if (Attach) + KeUnstackDetachProcess(&ApcState); + + ObDereferenceObject(Process); + } } NTSTATUS FspQuerySecurity( diff --git a/tst/winfsp-tests/memfs.cpp b/tst/winfsp-tests/memfs.cpp index a6b2c249..7ac683a0 100644 --- a/tst/winfsp-tests/memfs.cpp +++ b/tst/winfsp-tests/memfs.cpp @@ -553,6 +553,57 @@ NTSTATUS Rename(FSP_FILE_SYSTEM *FileSystem, return STATUS_SUCCESS; } +static NTSTATUS GetSecurity(FSP_FILE_SYSTEM *FileSystem, + FSP_FSCTL_TRANSACT_REQ *Request, + PVOID FileNode0, + PSECURITY_DESCRIPTOR SecurityDescriptor, SIZE_T *PSecurityDescriptorSize) +{ + MEMFS_FILE_NODE *FileNode = (MEMFS_FILE_NODE *)FileNode0; + + if (FileNode->FileSecuritySize > *PSecurityDescriptorSize) + { + *PSecurityDescriptorSize = FileNode->FileSecuritySize; + return STATUS_BUFFER_OVERFLOW; + } + + *PSecurityDescriptorSize = FileNode->FileSecuritySize; + if (0 != SecurityDescriptor) + memcpy(SecurityDescriptor, FileNode->FileSecurity, FileNode->FileSecuritySize); + + return STATUS_SUCCESS; +} + +static NTSTATUS SetSecurity(FSP_FILE_SYSTEM *FileSystem, + FSP_FSCTL_TRANSACT_REQ *Request, + PVOID FileNode0, + SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR SecurityDescriptor) +{ + MEMFS_FILE_NODE *FileNode = (MEMFS_FILE_NODE *)FileNode0; + PSECURITY_DESCRIPTOR NewSecurityDescriptor, FileSecurity; + SIZE_T FileSecuritySize; + NTSTATUS Result; + + Result = FspSetSecurityDescriptor(FileSystem, Request, FileNode->FileSecurity, + &NewSecurityDescriptor); + if (!NT_SUCCESS(Result)) + return Result; + + FileSecuritySize = GetSecurityDescriptorLength(NewSecurityDescriptor); + FileSecurity = (PSECURITY_DESCRIPTOR)malloc(FileSecuritySize); + if (0 == FileSecurity) + { + FspDeleteSecurityDescriptor(NewSecurityDescriptor, (NTSTATUS (*)())FspSetSecurityDescriptor); + return STATUS_INSUFFICIENT_RESOURCES; + } + memcpy(FileSecurity, SecurityDescriptor, FileSecuritySize); + FspDeleteSecurityDescriptor(NewSecurityDescriptor, (NTSTATUS (*)())FspSetSecurityDescriptor); + + FileNode->FileSecuritySize = FileSecuritySize; + FileNode->FileSecurity = FileSecurity; + + return STATUS_SUCCESS; +} + static FSP_FILE_SYSTEM_INTERFACE MemfsInterface = { GetVolumeInfo, @@ -569,6 +620,8 @@ static FSP_FILE_SYSTEM_INTERFACE MemfsInterface = SetFileSize, CanDelete, Rename, + GetSecurity, + SetSecurity, }; static VOID MemfsEnterOperation(FSP_FILE_SYSTEM *FileSystem,