X-Git-Url: https://git.reactos.org/?p=reactos.git;a=blobdiff_plain;f=ntoskrnl%2Fob%2Fobhandle.c;h=057cdecd7ffa3eadfde3e7ab5138533f065e4c4d;hp=346ea5bd4b0f916647e8ffa96604b1d661d19123;hb=2c909db295f72693e481c9c1ae01ad7695aecc3b;hpb=76a461dd16c5b33a65fd027e1c699386401dd879;ds=sidebyside diff --git a/ntoskrnl/ob/obhandle.c b/ntoskrnl/ob/obhandle.c index 346ea5bd4b0..057cdecd7ff 100644 --- a/ntoskrnl/ob/obhandle.c +++ b/ntoskrnl/ob/obhandle.c @@ -118,7 +118,7 @@ ObpReferenceProcessObjectByHandle(IN HANDLE Handle, /* Reference ourselves */ ObjectHeader = OBJECT_TO_OBJECT_HEADER(Process); - InterlockedIncrement(&ObjectHeader->PointerCount); + InterlockedIncrementSizeT(&ObjectHeader->PointerCount); /* Return the pointer */ *Object = Process; @@ -135,7 +135,7 @@ ObpReferenceProcessObjectByHandle(IN HANDLE Handle, /* Reference ourselves */ ObjectHeader = OBJECT_TO_OBJECT_HEADER(Thread); - InterlockedExchangeAdd(&ObjectHeader->PointerCount, 1); + InterlockedIncrementSizeT(&ObjectHeader->PointerCount); /* No audit mask */ *AuditMask = 0; @@ -188,7 +188,7 @@ ObpReferenceProcessObjectByHandle(IN HANDLE Handle, *Object = &ObjectHeader->Body; /* Add a reference */ - InterlockedExchangeAdd(&ObjectHeader->PointerCount, 1); + InterlockedIncrementSizeT(&ObjectHeader->PointerCount); /* Unlock the handle */ ExUnlockHandleTableEntry(HandleTable, HandleEntry); @@ -484,7 +484,22 @@ NTSTATUS NTAPI ObpValidateAccessMask(IN PACCESS_STATE AccessState) { - /* TODO */ + PISECURITY_DESCRIPTOR SecurityDescriptor; + + /* We're only interested if the object for this access state has an SD */ + SecurityDescriptor = AccessState->SecurityDescriptor; + if (SecurityDescriptor) + { + /* Check if the SD has a system ACL but hasn't been granted access to get/set it */ + if ((SecurityDescriptor->Control & SE_SACL_PRESENT) && + !(AccessState->PreviouslyGrantedAccess & ACCESS_SYSTEM_SECURITY)) + { + /* We're gonna need access */ + AccessState->RemainingDesiredAccess |= ACCESS_SYSTEM_SECURITY; + } + } + + /* This can't fail */ return STATUS_SUCCESS; } @@ -541,7 +556,7 @@ ObpDecrementHandleCount(IN PVOID ObjectBody, ProcessHandleCount = 0; /* Decrement the handle count */ - NewCount = InterlockedDecrement(&ObjectHeader->HandleCount); + NewCount = InterlockedDecrementSizeT(&ObjectHeader->HandleCount); /* Check if we're out of handles and this was an exclusive object */ if (!(NewCount) && (ObjectHeader->Flags & OB_FLAG_EXCLUSIVE)) @@ -683,7 +698,7 @@ ObpCloseHandleTableEntry(IN PHANDLE_TABLE HandleTable, Body = &ObjectHeader->Body; GrantedAccess = HandleEntry->GrantedAccess; OBTRACE(OB_HANDLE_DEBUG, - "%s - Closing handle: %lx for %p. HC PC %lx %lx\n", + "%s - Closing handle: %p for %p. HC PC %lx %lx\n", __FUNCTION__, Handle, Body, @@ -753,7 +768,7 @@ ObpCloseHandleTableEntry(IN PHANDLE_TABLE HandleTable, /* Return to caller */ OBTRACE(OB_HANDLE_DEBUG, - "%s - Closed handle: %lx for %p.\n", + "%s - Closed handle: %p for %p.\n", __FUNCTION__, Handle, Body); @@ -807,6 +822,7 @@ ObpIncrementHandleCount(IN PVOID Object, KIRQL CalloutIrql; KPROCESSOR_MODE ProbeMode; ULONG Total; + POBJECT_HEADER_NAME_INFO NameInfo; PAGED_CODE(); /* Get the object header and type */ @@ -872,6 +888,16 @@ ObpIncrementHandleCount(IN PVOID Object, goto Quickie; } + /* Check for exclusive kernel object */ + NameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader); + if ((NameInfo) && (NameInfo->QueryReferences & OB_FLAG_KERNEL_EXCLUSIVE) && + (ProbeMode != KernelMode)) + { + /* Caller is not kernel, but the object is kernel exclusive */ + Status = STATUS_ACCESS_DENIED; + goto Quickie; + } + /* * Check if this is an object that went from 0 handles back to existence, * but doesn't have an open procedure, only a close procedure. This means @@ -938,7 +964,7 @@ ObpIncrementHandleCount(IN PVOID Object, } /* Increase the handle count */ - InterlockedIncrement(&ObjectHeader->HandleCount); + InterlockedIncrementSizeT(&ObjectHeader->HandleCount); ProcessHandleCount = 0; /* Check if we have a handle database */ @@ -1165,7 +1191,7 @@ ObpIncrementUnnamedHandleCount(IN PVOID Object, } /* Increase the handle count */ - InterlockedIncrement(&ObjectHeader->HandleCount); + InterlockedIncrementSizeT(&ObjectHeader->HandleCount); ProcessHandleCount = 0; /* Check if we have a handle database */ @@ -1360,8 +1386,8 @@ ObpCreateUnnamedHandle(IN PVOID Object, if (AdditionalReferences) { /* Add them to the header */ - InterlockedExchangeAdd(&ObjectHeader->PointerCount, - AdditionalReferences); + InterlockedExchangeAddSizeT(&ObjectHeader->PointerCount, + AdditionalReferences); } /* Save the access mask */ @@ -1399,7 +1425,7 @@ ObpCreateUnnamedHandle(IN PVOID Object, /* Trace and return */ OBTRACE(OB_HANDLE_DEBUG, - "%s - Returning Handle: %lx HC PC %lx %lx\n", + "%s - Returning Handle: %p HC PC %lx %lx\n", __FUNCTION__, Handle, ObjectHeader->HandleCount, @@ -1411,8 +1437,8 @@ ObpCreateUnnamedHandle(IN PVOID Object, if (AdditionalReferences) { /* Dereference it as many times as required */ - InterlockedExchangeAdd(&ObjectHeader->PointerCount, - -(LONG)AdditionalReferences); + InterlockedExchangeAddSizeT(&ObjectHeader->PointerCount, + -(LONG)AdditionalReferences); } /* Decrement the handle count and detach */ @@ -1577,7 +1603,8 @@ ObpCreateHandle(IN OB_OPEN_REASON OpenReason, if (AdditionalReferences) { /* Add them to the header */ - InterlockedExchangeAdd(&ObjectHeader->PointerCount, AdditionalReferences); + InterlockedExchangeAddSizeT(&ObjectHeader->PointerCount, + AdditionalReferences); } /* Now we can release the object */ @@ -1645,7 +1672,7 @@ ObpCreateHandle(IN OB_OPEN_REASON OpenReason, /* Trace and return */ OBTRACE(OB_HANDLE_DEBUG, - "%s - Returning Handle: %lx HC PC %lx %lx\n", + "%s - Returning Handle: %p HC PC %lx %lx\n", __FUNCTION__, Handle, ObjectHeader->HandleCount, @@ -1666,8 +1693,8 @@ ObpCreateHandle(IN OB_OPEN_REASON OpenReason, if (AdditionalReferences > 1) { /* Dereference it many times */ - InterlockedExchangeAdd(&ObjectHeader->PointerCount, - -(LONG)(AdditionalReferences - 1)); + InterlockedExchangeAddSizeT(&ObjectHeader->PointerCount, + -(LONG)(AdditionalReferences - 1)); } /* Dereference the object one last time */ @@ -1708,13 +1735,13 @@ ObpCloseHandle(IN HANDLE Handle, PEPROCESS Process = PsGetCurrentProcess(); PAGED_CODE(); OBTRACE(OB_HANDLE_DEBUG, - "%s - Closing handle: %lx\n", __FUNCTION__, Handle); + "%s - Closing handle: %p\n", __FUNCTION__, Handle); if (AccessMode == KernelMode && Handle == (HANDLE)-1) 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; @@ -1803,7 +1830,7 @@ ObpCloseHandle(IN HANDLE Handle, /* Return status */ OBTRACE(OB_HANDLE_DEBUG, - "%s - Closed handle: %lx S: %lx\n", + "%s - Closed handle: %p S: %lx\n", __FUNCTION__, Handle, Status); return Status; } @@ -1946,7 +1973,7 @@ ObpDuplicateHandleCallback(IN PEPROCESS Process, ObjectHeader = ObpGetHandleObject(HandleTableEntry); /* Increment the pointer count */ - InterlockedIncrement(&ObjectHeader->PointerCount); + InterlockedIncrementSizeT(&ObjectHeader->PointerCount); /* Release the handle lock */ ExUnlockHandleTableEntry(HandleTable, OldEntry); @@ -1978,25 +2005,79 @@ ObpDuplicateHandleCallback(IN PEPROCESS Process, return Ret; } +/*++ +* @name ObClearProcessHandleTable +* +* The ObClearProcessHandleTable routine clears the handle table +* of the given process. +* +* @param Process +* The process of which the handle table should be cleared. +* +* @return None. +* +* @remarks None. +* +*--*/ VOID NTAPI ObClearProcessHandleTable(IN PEPROCESS Process) { - /* FIXME */ + PHANDLE_TABLE HandleTable; + OBP_CLOSE_HANDLE_CONTEXT Context; + KAPC_STATE ApcState; + BOOLEAN AttachedToProcess = FALSE; + + ASSERT(Process); + + /* Ensure the handle table doesn't go away while we use it */ + HandleTable = ObReferenceProcessHandleTable(Process); + if (!HandleTable) return; + + /* Attach to the current process if needed */ + if (PsGetCurrentProcess() != Process) + { + KeStackAttachProcess(&Process->Pcb, &ApcState); + AttachedToProcess = TRUE; + } + + /* Enter a critical region */ + KeEnterCriticalRegion(); + + /* Fill out the context */ + Context.AccessMode = UserMode; + Context.HandleTable = HandleTable; + + /* Sweep the handle table to close all handles */ + ExSweepHandleTable(HandleTable, + ObpCloseHandleCallback, + &Context); + + /* Leave the critical region */ + KeLeaveCriticalRegion(); + + /* Detach if needed */ + if (AttachedToProcess) + KeUnstackDetachProcess(&ApcState); + + /* Let the handle table go */ + ObDereferenceProcessHandleTable(Process); } /*++ -* @name ObpCreateHandleTable +* @name ObInitProcess * -* The ObpCreateHandleTable routine +* The ObInitProcess routine initializes the handle table for the process +* to be initialized, by either creating a new one or duplicating it from +* the parent process. * * @param Parent -* . +* A parent process (optional). * * @param Process -* . +* The process to initialize. * -* @return . +* @return Success or failure. * * @remarks None. * @@ -2059,14 +2140,16 @@ ObInitProcess(IN PEPROCESS Parent OPTIONAL, /*++ * @name ObKillProcess * -* The ObKillProcess routine +* The ObKillProcess routine performs rundown operations on the process, +* then clears and destroys its handle table. * * @param Process -* . +* The process to be killed. * * @return None. * -* @remarks None. +* @remarks Called by the Object Manager cleanup code (kernel) +* when a process is to be destroyed. * *--*/ VOID @@ -2139,9 +2222,11 @@ ObDuplicateObject(IN PEPROCESS SourceProcess, PHANDLE_TABLE HandleTable; OBJECT_HANDLE_INFORMATION HandleInformation; ULONG AuditMask; + BOOLEAN KernelHandle = FALSE; + PAGED_CODE(); OBTRACE(OB_HANDLE_DEBUG, - "%s - Duplicating handle: %lx for %p into %p\n", + "%s - Duplicating handle: %p for %p into %p\n", __FUNCTION__, SourceHandle, SourceProcess, @@ -2211,6 +2296,14 @@ ObDuplicateObject(IN PEPROCESS SourceProcess, return Status; } + /* Create a kernel handle if asked, but only in the system process */ + if (PreviousMode == KernelMode && + HandleAttributes & OBJ_KERNEL_HANDLE && + TargetProcess == PsInitialSystemProcess) + { + KernelHandle = TRUE; + } + /* Get the target handle table */ HandleTable = ObReferenceProcessHandleTable(TargetProcess); if (!HandleTable) @@ -2365,6 +2458,12 @@ ObDuplicateObject(IN PEPROCESS SourceProcess, Status = STATUS_INSUFFICIENT_RESOURCES; } + /* Mark it as a kernel handle if requested */ + if (KernelHandle) + { + NewHandle = ObMarkHandleAsKernelHandle(NewHandle); + } + /* Return the handle */ if (TargetHandle) *TargetHandle = NewHandle; @@ -2374,7 +2473,7 @@ ObDuplicateObject(IN PEPROCESS SourceProcess, /* Return status */ OBTRACE(OB_HANDLE_DEBUG, - "%s - Duplicated handle: %lx for %p into %p. Source: %p HC PC %lx %lx\n", + "%s - Duplicated handle: %p for %p into %p. Source: %p HC PC %lx %lx\n", __FUNCTION__, NewHandle, SourceProcess, @@ -2431,7 +2530,7 @@ ObOpenObjectByName(IN POBJECT_ATTRIBUTES ObjectAttributes, { PVOID Object = NULL; UNICODE_STRING ObjectName; - NTSTATUS Status; + NTSTATUS Status, Status2; POBJECT_HEADER ObjectHeader; PGENERIC_MAPPING GenericMapping = NULL; OB_OPEN_REASON OpenReason; @@ -2456,6 +2555,7 @@ ObOpenObjectByName(IN POBJECT_ATTRIBUTES ObjectAttributes, /* Capture all the info */ Status = ObpCaptureObjectCreateInformation(ObjectAttributes, + AccessMode, AccessMode, TRUE, &TempBuffer->ObjectCreateInfo, @@ -2490,6 +2590,15 @@ ObOpenObjectByName(IN POBJECT_ATTRIBUTES ObjectAttributes, TempBuffer->ObjectCreateInfo.SecurityDescriptor; } + /* Validate the access mask */ + Status = ObpValidateAccessMask(PassedAccessState); + if (!NT_SUCCESS(Status)) + { + /* Cleanup after lookup */ + ObpReleaseLookupContext(&TempBuffer->LookupContext); + goto Cleanup; + } + /* Now do the lookup */ Status = ObpLookupObjectName(TempBuffer->ObjectCreateInfo.RootDirectory, &ObjectName, @@ -2547,17 +2656,21 @@ ObOpenObjectByName(IN POBJECT_ATTRIBUTES ObjectAttributes, else { /* Create the actual handle now */ - Status = ObpCreateHandle(OpenReason, - Object, - ObjectType, - PassedAccessState, - 0, - TempBuffer->ObjectCreateInfo.Attributes, - &TempBuffer->LookupContext, - AccessMode, - NULL, - Handle); - if (!NT_SUCCESS(Status)) ObDereferenceObject(Object); + Status2 = ObpCreateHandle(OpenReason, + Object, + ObjectType, + PassedAccessState, + 0, + TempBuffer->ObjectCreateInfo.Attributes, + &TempBuffer->LookupContext, + AccessMode, + NULL, + Handle); + if (!NT_SUCCESS(Status2)) + { + ObDereferenceObject(Object); + Status = Status2; + } } Cleanup: @@ -2841,7 +2954,7 @@ ObInsertObject(IN PVOID Object, if (!(ObjectHeader->Flags & OB_FLAG_CREATE_INFO)) { /* Display warning and break into debugger */ - DPRINT1("OB: Attempting to insert existing object %08x\n", Object); + DPRINT1("OB: Attempting to insert existing object %p\n", Object); DbgBreakPoint(); /* Allow debugger to continue */ @@ -2982,7 +3095,7 @@ ObInsertObject(IN PVOID Object, { /* Check if this was a symbolic link */ if (OBJECT_TO_OBJECT_HEADER(InsertObject)->Type == - ObSymbolicLinkType) + ObpSymbolicLinkObjectType) { /* Dereference it */ ObDereferenceObject(InsertObject); @@ -3016,7 +3129,7 @@ ObInsertObject(IN PVOID Object, else { /* Check if this is a symbolic link */ - if (ObjectType == ObSymbolicLinkType) + if (ObjectType == ObpSymbolicLinkObjectType) { /* Create the internal name */ ObpCreateSymbolicLinkName(Object); @@ -3161,6 +3274,80 @@ ObInsertObject(IN PVOID Object, return RealStatus; } +/*++ +* @name ObSetHandleAttributes +* @implemented NT5.1 +* +* The ObSetHandleAttributes routine +* +* @param Handle +* . +* +* @param HandleFlags +* . +* +* @param PreviousMode +* . +* +* @return . +* +* @remarks None. +* +*--*/ +NTSTATUS +NTAPI +ObSetHandleAttributes(IN HANDLE Handle, + IN POBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleFlags, + IN KPROCESSOR_MODE PreviousMode) +{ + 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; +} + /*++ * @name ObCloseHandle * @implemented NT5.1 @@ -3224,7 +3411,7 @@ NtDuplicateObject(IN HANDLE SourceProcessHandle, KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); NTSTATUS Status; OBTRACE(OB_HANDLE_DEBUG, - "%s - Duplicating handle: %lx for %lx into %lx.\n", + "%s - Duplicating handle: %p for %p into %p.\n", __FUNCTION__, SourceHandle, SourceProcessHandle, @@ -3255,7 +3442,7 @@ NtDuplicateObject(IN HANDLE SourceProcessHandle, PreviousMode, (PVOID*)&SourceProcess, NULL); - if (!NT_SUCCESS(Status)) return(Status); + if (!NT_SUCCESS(Status)) return Status; /* Check if got a target handle */ if (TargetProcessHandle) @@ -3314,7 +3501,7 @@ NtDuplicateObject(IN HANDLE SourceProcessHandle, /* Dereference the processes */ OBTRACE(OB_HANDLE_DEBUG, - "%s - Duplicated handle: %lx into %lx S %lx\n", + "%s - Duplicated handle: %p into %p S %lx\n", __FUNCTION__, hTarget, TargetProcessHandle, @@ -3324,13 +3511,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 */