From 91105c791595ebb7e5e37b07053a4e1ee5b05ed4 Mon Sep 17 00:00:00 2001 From: Timo Kreuzer Date: Mon, 18 Nov 2013 14:27:01 +0000 Subject: [PATCH] [NTOSKRNL] Implement ObSetHandleAttributes. Rename the ObIsKernelHandle macro to ObpIsKernelHandle to avoid ambiguities (ObIsKernelHandle is a public Vista+ API). Check for NtCurrentProcess and NtCurrentThread in ObpIsKernelHandle, since those are always non-kernel handles. svn path=/trunk/; revision=61037 --- reactos/ntoskrnl/include/internal/ob.h | 8 ++-- reactos/ntoskrnl/ob/obhandle.c | 57 ++++++++++++++++++++++---- reactos/ntoskrnl/ob/oblife.c | 16 ++++---- reactos/ntoskrnl/ob/obsecure.c | 14 +++---- reactos/ntoskrnl/ob/obwait.c | 2 +- 5 files changed, 71 insertions(+), 26 deletions(-) diff --git a/reactos/ntoskrnl/include/internal/ob.h b/reactos/ntoskrnl/include/internal/ob.h index dd1f375598b..54c7d1de526 100644 --- a/reactos/ntoskrnl/include/internal/ob.h +++ b/reactos/ntoskrnl/include/internal/ob.h @@ -61,9 +61,11 @@ #else #define KERNEL_HANDLE_FLAG 0x80000000 #endif -#define ObIsKernelHandle(Handle, ProcessorMode) \ - (((ULONG_PTR)(Handle) & KERNEL_HANDLE_FLAG) && \ - ((ProcessorMode) == KernelMode)) +#define ObpIsKernelHandle(Handle, ProcessorMode) \ + ((((ULONG_PTR)(Handle) & KERNEL_HANDLE_FLAG) == KERNEL_HANDLE_FLAG) && \ + ((ProcessorMode) == KernelMode) && \ + ((Handle) != NtCurrentProcess()) && \ + ((Handle) != NtCurrentThread())) // // Converts to and from a Kernel Handle to a normal handle diff --git a/reactos/ntoskrnl/ob/obhandle.c b/reactos/ntoskrnl/ob/obhandle.c index 37c79b6b510..04672decff1 100644 --- a/reactos/ntoskrnl/ob/obhandle.c +++ b/reactos/ntoskrnl/ob/obhandle.c @@ -1714,7 +1714,7 @@ ObpCloseHandle(IN HANDLE Handle, return STATUS_INVALID_HANDLE; /* Check if we're dealing with a kernel handle */ - if (ObIsKernelHandle(Handle, AccessMode)) + if (ObpIsKernelHandle(Handle, AccessMode)) { /* Use the kernel table and convert the handle */ HandleTable = ObpKernelHandleTable; @@ -2490,7 +2490,7 @@ ObOpenObjectByName(IN POBJECT_ATTRIBUTES ObjectAttributes, PassedAccessState->SecurityDescriptor = TempBuffer->ObjectCreateInfo.SecurityDescriptor; } - + /* Validate the access mask */ Status = ObpValidateAccessMask(PassedAccessState); if (!NT_SUCCESS(Status)) @@ -3197,8 +3197,52 @@ ObSetHandleAttributes(IN HANDLE Handle, IN POBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleFlags, IN KPROCESSOR_MODE PreviousMode) { - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + OBP_SET_HANDLE_ATTRIBUTES_CONTEXT SetHandleAttributesContext; + BOOLEAN Result, AttachedToSystemProcess = FALSE; + PHANDLE_TABLE HandleTable; + KAPC_STATE ApcState; + PAGED_CODE(); + + /* Check if this is a kernel handle */ + if (ObpIsKernelHandle(Handle, PreviousMode)) + { + /* Use the kernel table and convert the handle */ + HandleTable = ObpKernelHandleTable; + Handle = ObKernelHandleToHandle(Handle); + + /* Check if we're not in the system process */ + if (PsGetCurrentProcess() != PsInitialSystemProcess) + { + /* Attach to the system process */ + KeStackAttachProcess(&PsInitialSystemProcess->Pcb, &ApcState); + AttachedToSystemProcess = TRUE; + } + } + else + { + /* Get the current process' handle table */ + HandleTable = PsGetCurrentProcess()->ObjectTable; + } + + /* Initialize the handle attribute context */ + SetHandleAttributesContext.PreviousMode = PreviousMode; + SetHandleAttributesContext.Information = *HandleFlags; + + /* Invoke the ObpSetHandleAttributes callback */ + Result = ExChangeHandle(HandleTable, + Handle, + ObpSetHandleAttributes, + (ULONG_PTR)&SetHandleAttributesContext); + + /* Did we attach to the system process? */ + if (AttachedToSystemProcess) + { + /* Detach from it */ + KeUnstackDetachProcess(&ApcState); + } + + /* Return the result as an NTSTATUS value */ + return Result ? STATUS_SUCCESS : STATUS_ACCESS_DENIED; } /*++ @@ -3364,13 +3408,12 @@ NtDuplicateObject(IN HANDLE SourceProcessHandle, return Status; } -#undef ObIsKernelHandle BOOLEAN NTAPI ObIsKernelHandle(IN HANDLE Handle) { - /* We know we're kernel mode, so just check for the kernel handle flag */ - return (BOOLEAN)(((ULONG_PTR)Handle & KERNEL_HANDLE_FLAG) != 0); + /* Use the inlined version. We know we are in kernel mode. */ + return ObpIsKernelHandle(Handle, KernelMode); } /* EOF */ diff --git a/reactos/ntoskrnl/ob/oblife.c b/reactos/ntoskrnl/ob/oblife.c index 99879b773e2..a2618a833ff 100644 --- a/reactos/ntoskrnl/ob/oblife.c +++ b/reactos/ntoskrnl/ob/oblife.c @@ -1675,14 +1675,14 @@ NtSetInformationObject(IN HANDLE ObjectHandle, switch (ObjectInformationClass) { case ObjectHandleFlagInformation: - + /* Validate the length */ if (Length != sizeof(OBJECT_HANDLE_ATTRIBUTE_INFORMATION)) { /* Invalid length */ return STATUS_INFO_LENGTH_MISMATCH; } - + /* Save the previous mode */ Context.PreviousMode = ExGetPreviousMode(); @@ -1714,7 +1714,7 @@ NtSetInformationObject(IN HANDLE ObjectHandle, } /* Check if this is a kernel handle */ - if (ObIsKernelHandle(ObjectHandle, Context.PreviousMode)) + if (ObpIsKernelHandle(ObjectHandle, Context.PreviousMode)) { /* Get the actual handle */ ObjectHandle = ObKernelHandleToHandle(ObjectHandle); @@ -1752,9 +1752,9 @@ NtSetInformationObject(IN HANDLE ObjectHandle, /* De-attach if we were attached, and return status */ if (AttachedToProcess) KeUnstackDetachProcess(&ApcState); break; - + case ObjectSessionInformation: - + /* Only a system process can do this */ PreviousMode = ExGetPreviousMode(); if (!SeSinglePrivilegeCheck(SeTcbPrivilege, PreviousMode)) @@ -1766,8 +1766,8 @@ NtSetInformationObject(IN HANDLE ObjectHandle, else { /* Get the object directory */ - Status = ObReferenceObjectByHandle(ObjectHandle, - 0, + Status = ObReferenceObjectByHandle(ObjectHandle, + 0, ObDirectoryType, PreviousMode, (PVOID*)&Directory, @@ -1781,7 +1781,7 @@ NtSetInformationObject(IN HANDLE ObjectHandle, } } break; - + default: /* Unsupported class */ Status = STATUS_INVALID_INFO_CLASS; diff --git a/reactos/ntoskrnl/ob/obsecure.c b/reactos/ntoskrnl/ob/obsecure.c index fbc3c8e2ebb..15395b7d9ae 100644 --- a/reactos/ntoskrnl/ob/obsecure.c +++ b/reactos/ntoskrnl/ob/obsecure.c @@ -62,17 +62,17 @@ ObDeassignSecurity(IN OUT PSECURITY_DESCRIPTOR *SecurityDescriptor) EX_FAST_REF FastRef; ULONG Count; PSECURITY_DESCRIPTOR OldSecurityDescriptor; - + /* Get the fast reference and capture it */ FastRef = *(PEX_FAST_REF)SecurityDescriptor; - + /* Don't free again later */ *SecurityDescriptor = NULL; - + /* Get the descriptor and reference count */ OldSecurityDescriptor = ExGetObjectFastReference(FastRef); Count = ExGetCountFastReference(FastRef); - + /* Dereference the descriptor */ ObDereferenceSecurityDescriptor(OldSecurityDescriptor, Count + 1); @@ -162,11 +162,11 @@ ObSetSecurityDescriptorInfo(IN PVOID Object, OldValue = ExCompareSwapFastReference(FastRef, CachedDescriptor, OldDescriptor); - + /* Get the security descriptor */ SecurityDescriptor = ExGetObjectFastReference(OldValue); Count = ExGetCountFastReference(OldValue); - + /* Make sure the swap worked */ if (SecurityDescriptor == OldDescriptor) { @@ -1010,7 +1010,7 @@ ObQueryObjectAuditingByHandle(IN HANDLE Handle, PAGED_CODE(); /* Check if we're dealing with a kernel handle */ - if (ObIsKernelHandle(Handle, ExGetPreviousMode())) + if (ObpIsKernelHandle(Handle, ExGetPreviousMode())) { /* Use the kernel table and convert the handle */ HandleTable = ObpKernelHandleTable; diff --git a/reactos/ntoskrnl/ob/obwait.c b/reactos/ntoskrnl/ob/obwait.c index 6a202183919..98b4ca8c0b8 100644 --- a/reactos/ntoskrnl/ob/obwait.c +++ b/reactos/ntoskrnl/ob/obwait.c @@ -142,7 +142,7 @@ NtWaitForMultipleObjects(IN ULONG ObjectCount, do { /* Use the right Executive Handle */ - if (ObIsKernelHandle(Handles[i], PreviousMode)) + if (ObpIsKernelHandle(Handles[i], PreviousMode)) { /* Use the System Handle Table and decode */ HandleTable = ObpKernelHandleTable;