From 3b64f7f8fbbc64ada4dfdb6bdd1feff4bac10c1d Mon Sep 17 00:00:00 2001 From: Pierre Schweitzer Date: Sun, 12 Nov 2017 22:28:54 +0100 Subject: [PATCH] [NTOSKRNL] Implement (with many FIXMEs) ObReferenceFileObjectForWrite() so that it can already do the job! CORE-14003 --- ntoskrnl/include/internal/ob.h | 9 +++ ntoskrnl/ob/obref.c | 108 +++++++++++++++++++++++++++++++++ 2 files changed, 117 insertions(+) diff --git a/ntoskrnl/include/internal/ob.h b/ntoskrnl/include/internal/ob.h index a78b5ad4579..374f4a2c3e3 100644 --- a/ntoskrnl/include/internal/ob.h +++ b/ntoskrnl/include/internal/ob.h @@ -384,6 +384,15 @@ ObpDeleteObjectType( IN PVOID Object ); +NTSTATUS +NTAPI +ObReferenceFileObjectForWrite( + IN HANDLE Handle, + IN KPROCESSOR_MODE AccessMode, + OUT PFILE_OBJECT *FileObject, + OUT POBJECT_HANDLE_INFORMATION HandleInformation +); + // // DOS Devices Functions // diff --git a/ntoskrnl/ob/obref.c b/ntoskrnl/ob/obref.c index 00e21880697..2f4da201499 100644 --- a/ntoskrnl/ob/obref.c +++ b/ntoskrnl/ob/obref.c @@ -15,6 +15,8 @@ #define NDEBUG #include +extern ULONG ObpAccessProtectCloseBit; + /* PRIVATE FUNCTIONS *********************************************************/ BOOLEAN @@ -195,6 +197,112 @@ ObFastReplaceObject(IN PEX_FAST_REF FastRef, return OldObject; } +NTSTATUS +NTAPI +ObReferenceFileObjectForWrite(IN HANDLE Handle, + IN KPROCESSOR_MODE AccessMode, + OUT PFILE_OBJECT *FileObject, + OUT POBJECT_HANDLE_INFORMATION HandleInformation) +{ + NTSTATUS Status; + PHANDLE_TABLE HandleTable; + POBJECT_HEADER ObjectHeader; + PHANDLE_TABLE_ENTRY HandleEntry; + ACCESS_MASK GrantedAccess, DesiredAccess; + + /* Assume failure */ + *FileObject = NULL; + + /* Check if this is a special handle */ + if (HandleToLong(Handle) < 0) + { + /* Make sure we have a valid kernel handle */ + if (AccessMode != KernelMode || Handle == NtCurrentProcess() || Handle == NtCurrentThread()) + { + return STATUS_INVALID_HANDLE; + } + + /* Use the kernel handle table and get the actual handle value */ + Handle = ObKernelHandleToHandle(Handle); + HandleTable = ObpKernelHandleTable; + } + else + { + /* Otherwise use this process's handle table */ + HandleTable = PsGetCurrentProcess()->ObjectTable; + } + + ASSERT(HandleTable != NULL); + KeEnterCriticalRegion(); + + /* Get the handle entry */ + HandleEntry = ExMapHandleToPointer(HandleTable, Handle); + if (HandleEntry) + { + /* Get the object header and validate the type*/ + ObjectHeader = ObpGetHandleObject(HandleEntry); + + /* Get the desired access from the file object */ + if (!NT_SUCCESS(IoComputeDesiredAccessFileObject((PFILE_OBJECT)&ObjectHeader->Body, + &DesiredAccess))) + { + Status = STATUS_OBJECT_TYPE_MISMATCH; + } + else + { + /* Extract the granted access from the handle entry */ + if (BooleanFlagOn(NtGlobalFlag, FLG_KERNEL_STACK_TRACE_DB)) + { + /* FIXME: Translate granted access */ + GrantedAccess = HandleEntry->GrantedAccess; + } + else + { + GrantedAccess = HandleEntry->GrantedAccess & ~ObpAccessProtectCloseBit; + } + + /* FIXME: Get handle information for audit */ + + HandleInformation->GrantedAccess = GrantedAccess; + + /* FIXME: Get handle attributes */ + HandleInformation->HandleAttributes = 0; + + /* Do granted and desired access match? */ + if (GrantedAccess & DesiredAccess) + { + /* FIXME: Audit access if required */ + + /* Reference the object directly since we have its header */ + InterlockedIncrement(&ObjectHeader->PointerCount); + + /* Unlock the handle */ + ExUnlockHandleTableEntry(HandleTable, HandleEntry); + KeLeaveCriticalRegion(); + + *FileObject = (PFILE_OBJECT)&ObjectHeader->Body; + + /* Return success */ + ASSERT(*FileObject != NULL); + return STATUS_SUCCESS; + } + + /* No match, deny write access */ + Status = STATUS_ACCESS_DENIED; + + ExUnlockHandleTableEntry(HandleTable, HandleEntry); + } + } + else + { + Status = STATUS_INVALID_HANDLE; + } + + /* Return failure status */ + KeLeaveCriticalRegion(); + return Status; +} + /* PUBLIC FUNCTIONS *********************************************************/ LONG_PTR -- 2.17.1