From 259db9be4728bed61bb52d42731dc56ffbc32b39 Mon Sep 17 00:00:00 2001 From: Alex Ionescu Date: Sun, 11 Jun 2006 06:52:56 +0000 Subject: [PATCH] - Fix definitions of OB_QUERYNAME_METHOD and OB_OKAYTOCLOSE_METHOD. Add fixme for OB_SECURITY_METHOD, will change it later. - Simplified NtDuplicateObject to a simple stub around ObDuplicateObject, there is no need to have lengthy hacks for NtCurrentProcess/NtCurrentThread(). - Cleanup ObDuplicateObject to use normal Ob routines instead of grovelling through handle table structures and manually touching the handle count: It now calls ObpIncrementHandleCount and all the underlying operations are done on the duplicated handle. Also access state creation is done if the duplicated handle has different desired access. svn path=/trunk/; revision=22303 --- reactos/include/ndk/obtypes.h | 8 +- reactos/ntoskrnl/cm/cm.h | 3 +- reactos/ntoskrnl/cm/regobj.c | 3 +- reactos/ntoskrnl/include/internal/io.h | 3 +- reactos/ntoskrnl/include/internal/ob.h | 12 - reactos/ntoskrnl/io/file.c | 3 +- reactos/ntoskrnl/ob/obhandle.c | 494 ++++++++++++------------- reactos/ntoskrnl/ob/obname.c | 5 +- 8 files changed, 252 insertions(+), 279 deletions(-) diff --git a/reactos/include/ndk/obtypes.h b/reactos/include/ndk/obtypes.h index 152919070b9..41da1e25cc3 100644 --- a/reactos/include/ndk/obtypes.h +++ b/reactos/include/ndk/obtypes.h @@ -215,7 +215,7 @@ typedef NTSTATUS (NTAPI *OB_SECURITY_METHOD)( IN PVOID Object, IN SECURITY_OPERATION_CODE OperationType, - IN SECURITY_INFORMATION SecurityInformation, + IN SECURITY_INFORMATION SecurityInformation, // FIXME: <= should be a pointer IN PSECURITY_DESCRIPTOR SecurityDescriptor, IN OUT PULONG CapturedLength, IN OUT PSECURITY_DESCRIPTOR *ObjectSecurityDescriptor, @@ -229,14 +229,16 @@ typedef NTSTATUS IN BOOLEAN HasObjectName, OUT POBJECT_NAME_INFORMATION ObjectNameInfo, IN ULONG Length, - OUT PULONG ReturnLength + OUT PULONG ReturnLength, + IN KPROCESSOR_MODE AccessMode ); typedef NTSTATUS (NTAPI *OB_OKAYTOCLOSE_METHOD)( IN PEPROCESS Process OPTIONAL, IN PVOID Object, - IN HANDLE Handle + IN HANDLE Handle, + IN KPROCESSOR_MODE AccessMode ); #else diff --git a/reactos/ntoskrnl/cm/cm.h b/reactos/ntoskrnl/cm/cm.h index 54120aa2d84..6d32f401835 100644 --- a/reactos/ntoskrnl/cm/cm.h +++ b/reactos/ntoskrnl/cm/cm.h @@ -467,7 +467,8 @@ CmiObjectQueryName (PVOID ObjectBody, IN BOOLEAN HasObjectName, POBJECT_NAME_INFORMATION ObjectNameInfo, ULONG Length, - PULONG ReturnLength); + PULONG ReturnLength, + IN KPROCESSOR_MODE PreviousMode); NTSTATUS CmiImportHiveBins(PREGISTRY_HIVE Hive, diff --git a/reactos/ntoskrnl/cm/regobj.c b/reactos/ntoskrnl/cm/regobj.c index ac8c8352ca5..c853d690ec3 100644 --- a/reactos/ntoskrnl/cm/regobj.c +++ b/reactos/ntoskrnl/cm/regobj.c @@ -691,7 +691,8 @@ CmiObjectQueryName (PVOID ObjectBody, IN BOOLEAN HasName, POBJECT_NAME_INFORMATION ObjectNameInfo, ULONG Length, - PULONG ReturnLength) + PULONG ReturnLength, + IN KPROCESSOR_MODE PreviousMode) { PKEY_OBJECT KeyObject; NTSTATUS Status; diff --git a/reactos/ntoskrnl/include/internal/io.h b/reactos/ntoskrnl/include/internal/io.h index 3852dffad39..dcff15126a2 100644 --- a/reactos/ntoskrnl/include/internal/io.h +++ b/reactos/ntoskrnl/include/internal/io.h @@ -518,7 +518,8 @@ IopQueryNameFile( IN BOOLEAN HasName, POBJECT_NAME_INFORMATION ObjectNameInfo, ULONG Length, - PULONG ReturnLength + PULONG ReturnLength, + IN KPROCESSOR_MODE PreviousMode ); VOID diff --git a/reactos/ntoskrnl/include/internal/ob.h b/reactos/ntoskrnl/include/internal/ob.h index 6dd1d263b4e..251148f08d5 100644 --- a/reactos/ntoskrnl/include/internal/ob.h +++ b/reactos/ntoskrnl/include/internal/ob.h @@ -121,18 +121,6 @@ ObpDeleteNameCheck( IN PVOID Object ); -NTSTATUS -NTAPI -ObDuplicateObject( - PEPROCESS SourceProcess, - PEPROCESS TargetProcess, - HANDLE SourceHandle, - PHANDLE TargetHandle, - ACCESS_MASK DesiredAccess, - ULONG HandleAttributes, - ULONG Options -); - VOID NTAPI ObQueryDeviceMapInformation( diff --git a/reactos/ntoskrnl/io/file.c b/reactos/ntoskrnl/io/file.c index 389e3a697bc..1b2e0aeed72 100644 --- a/reactos/ntoskrnl/io/file.c +++ b/reactos/ntoskrnl/io/file.c @@ -411,7 +411,8 @@ IopQueryNameFile(PVOID ObjectBody, IN BOOLEAN HasName, POBJECT_NAME_INFORMATION ObjectNameInfo, ULONG Length, - PULONG ReturnLength) + PULONG ReturnLength, + IN KPROCESSOR_MODE PreviousMode) { POBJECT_NAME_INFORMATION LocalInfo; PFILE_OBJECT FileObject; diff --git a/reactos/ntoskrnl/ob/obhandle.c b/reactos/ntoskrnl/ob/obhandle.c index c02c0316821..1c9d672f7ee 100644 --- a/reactos/ntoskrnl/ob/obhandle.c +++ b/reactos/ntoskrnl/ob/obhandle.c @@ -196,7 +196,8 @@ ObpCloseHandleTableEntry(IN PHANDLE_TABLE HandleTable, /* Call it and check if it's not letting us close it */ if (!ObjectType->TypeInfo.OkayToCloseProcedure(PsGetCurrentProcess(), Body, - Handle)) + Handle, + AccessMode)) { /* Fail */ ExUnlockHandleTableEntry(HandleTable, HandleEntry); @@ -1188,158 +1189,201 @@ ObKillProcess(IN PEPROCESS Process) NTSTATUS NTAPI -ObDuplicateObject(PEPROCESS SourceProcess, - PEPROCESS TargetProcess, - HANDLE SourceHandle, - PHANDLE TargetHandle, - ACCESS_MASK DesiredAccess, - ULONG HandleAttributes, - ULONG Options) +ObDuplicateObject(IN PEPROCESS SourceProcess, + IN HANDLE SourceHandle, + IN PEPROCESS TargetProcess OPTIONAL, + IN PHANDLE TargetHandle OPTIONAL, + IN ACCESS_MASK DesiredAccess, + IN ULONG HandleAttributes, + IN ULONG Options, + IN KPROCESSOR_MODE PreviousMode) { - PHANDLE_TABLE_ENTRY SourceHandleEntry; HANDLE_TABLE_ENTRY NewHandleEntry; BOOLEAN AttachedToProcess = FALSE; - PVOID ObjectBody; + PVOID SourceObject; POBJECT_HEADER ObjectHeader; - ULONG NewHandleCount; - HANDLE NewTargetHandle; - PEPROCESS CurrentProcess; + POBJECT_TYPE ObjectType; + HANDLE NewHandle; KAPC_STATE ApcState; NTSTATUS Status = STATUS_SUCCESS; - + ACCESS_MASK TargetAccess, SourceAccess; + ACCESS_STATE AccessState; + PACCESS_STATE PassedAccessState = NULL; + AUX_DATA AuxData; + PHANDLE_TABLE HandleTable = NULL; + OBJECT_HANDLE_INFORMATION HandleInformation; PAGED_CODE(); + OBTRACE("OBTRACE - %s - Duplicating handle: %lx for %p into %p\n", + __FUNCTION__, + SourceHandle, + SourceProcess, + TargetProcess); - if(SourceProcess == NULL || - ObIsKernelHandle(SourceHandle, ExGetPreviousMode())) + /* Check if we're not in the source process */ + if (SourceProcess != PsGetCurrentProcess()) { - SourceProcess = PsInitialSystemProcess; - SourceHandle = ObKernelHandleToHandle(SourceHandle); - } - - CurrentProcess = PsGetCurrentProcess(); - - KeEnterCriticalRegion(); - - if (SourceProcess != CurrentProcess) - { - KeStackAttachProcess(&SourceProcess->Pcb, - &ApcState); + /* Attach to it */ + KeStackAttachProcess(&SourceProcess->Pcb, &ApcState); AttachedToProcess = TRUE; } - SourceHandleEntry = ExMapHandleToPointer(SourceProcess->ObjectTable, - SourceHandle); - if (SourceHandleEntry == NULL) - { - if (AttachedToProcess) - { - KeUnstackDetachProcess(&ApcState); - } - KeLeaveCriticalRegion(); - return STATUS_INVALID_HANDLE; - } - - ObjectHeader = EX_HTE_TO_HDR(SourceHandleEntry); - ObjectBody = &ObjectHeader->Body; - - NewHandleEntry.Object = SourceHandleEntry->Object; - if(HandleAttributes & OBJ_INHERIT) - NewHandleEntry.ObAttributes |= EX_HANDLE_ENTRY_INHERITABLE; - else - NewHandleEntry.ObAttributes &= ~EX_HANDLE_ENTRY_INHERITABLE; - NewHandleEntry.GrantedAccess = ((Options & DUPLICATE_SAME_ACCESS) ? - SourceHandleEntry->GrantedAccess : - DesiredAccess); - if (Options & DUPLICATE_SAME_ACCESS) - { - NewHandleEntry.GrantedAccess = SourceHandleEntry->GrantedAccess; - } - else - { - if (DesiredAccess & GENERIC_ACCESS) - { - RtlMapGenericMask(&DesiredAccess, - &ObjectHeader->Type->TypeInfo.GenericMapping); - } - NewHandleEntry.GrantedAccess = DesiredAccess; - } - - /* reference the object so it doesn't get deleted after releasing the lock - and before creating a new handle for it */ - ObReferenceObject(ObjectBody); - - /* increment the handle count of the object, it should always be >= 2 because - we're holding a handle lock to this object! if the new handle count was - 1 here, we're in big trouble... it would've been safe to increment and - check the handle count without using interlocked functions because the - entry is locked, which means the handle count can't change. */ - NewHandleCount = InterlockedIncrement(&ObjectHeader->HandleCount); - ASSERT(NewHandleCount >= 2); - - ExUnlockHandleTableEntry(SourceProcess->ObjectTable, - SourceHandleEntry); + /* Now reference the source handle */ + Status = ObReferenceObjectByHandle(SourceHandle, + 0, + NULL, + PreviousMode, + (PVOID*)&SourceObject, + &HandleInformation); + /* Check if we were attached */ if (AttachedToProcess) { + /* We can safely detach now */ KeUnstackDetachProcess(&ApcState); AttachedToProcess = FALSE; } - if (TargetProcess != CurrentProcess) + /* Fail if we couldn't reference it */ + if (!NT_SUCCESS(Status)) return Status; + + /* Get the source access */ + SourceAccess = HandleInformation.GrantedAccess; + + /* Check if we're not in the target process */ + if (TargetProcess != PsGetCurrentProcess()) { - KeStackAttachProcess(&TargetProcess->Pcb, - &ApcState); + /* Attach to it */ + KeStackAttachProcess(&TargetProcess->Pcb, &ApcState); AttachedToProcess = TRUE; } - /* attempt to create the new handle */ - NewTargetHandle = ExCreateHandle(TargetProcess->ObjectTable, - &NewHandleEntry); + /* Check if we're duplicating the attributes */ + if (Options & DUPLICATE_SAME_ATTRIBUTES) + { + /* Duplicate them */ + HandleAttributes = HandleInformation.HandleAttributes; + } + + /* Check if we're duplicating the access */ + if (Options & DUPLICATE_SAME_ACCESS) DesiredAccess = SourceAccess; + + /* Get object data */ + ObjectHeader = OBJECT_TO_OBJECT_HEADER(SourceObject); + ObjectType = ObjectHeader->Type; + + /* Fill out the entry */ + NewHandleEntry.Object = ObjectHeader; + NewHandleEntry.ObAttributes |= HandleAttributes & + (EX_HANDLE_ENTRY_PROTECTFROMCLOSE | + EX_HANDLE_ENTRY_INHERITABLE | + EX_HANDLE_ENTRY_AUDITONCLOSE); + + /* Check if we're using a generic mask */ + if (DesiredAccess & GENERIC_ACCESS) + { + /* Map it */ + RtlMapGenericMask(&DesiredAccess, &ObjectType->TypeInfo.GenericMapping); + } + + /* Set the target access */ + TargetAccess = DesiredAccess; + NewHandleEntry.GrantedAccess = TargetAccess; + + /* Check if we're asking for new access */ + if (TargetAccess & ~SourceAccess) + { + /* We are. We need the security procedure to validate this */ + if (ObjectType->TypeInfo.SecurityProcedure == SeDefaultObjectMethod) + { + /* Use our built-in access state */ + PassedAccessState = &AccessState; + Status = SeCreateAccessState(&AccessState, + &AuxData, + TargetAccess, + &ObjectType->TypeInfo.GenericMapping); + } + else + { + /* Otherwise we can't allow this privilege elevation */ + Status = STATUS_ACCESS_DENIED; + } + } + else + { + /* We don't need an access state */ + Status = STATUS_SUCCESS; + } + + /* Make sure the access state was created OK */ + if (NT_SUCCESS(Status)) + { + /* Add a new handle */ + Status = ObpIncrementHandleCount(SourceObject, + PassedAccessState, + PreviousMode, + HandleAttributes, + PsGetCurrentProcess(), + ObDuplicateHandle); + + /* Set the handle table, now that we know this handle was added */ + HandleTable = PsGetCurrentProcess()->ObjectTable; + } + + /* Check if we were attached */ if (AttachedToProcess) { + /* We can safely detach now */ KeUnstackDetachProcess(&ApcState); AttachedToProcess = FALSE; } - if (NewTargetHandle != NULL) + /* Check if we have to close the source handle */ + if (Options & DUPLICATE_CLOSE_SOURCE) { - if (Options & DUPLICATE_CLOSE_SOURCE) - { - if (SourceProcess != CurrentProcess) - { - KeStackAttachProcess(&SourceProcess->Pcb, - &ApcState); - AttachedToProcess = TRUE; - } - - /* delete the source handle */ - NtClose(SourceHandle); - - if (AttachedToProcess) - { - KeUnstackDetachProcess(&ApcState); - } - } - - ObDereferenceObject(ObjectBody); - - *TargetHandle = NewTargetHandle; - } - else - { - /* decrement the handle count we previously incremented, but don't call the - closing procedure because we're not closing a handle! */ - if(InterlockedDecrement(&ObjectHeader->HandleCount) == 0) - { - ObDereferenceObject(ObjectBody); - } - - ObDereferenceObject(ObjectBody); - Status = STATUS_UNSUCCESSFUL; + /* Attach and close */ + KeStackAttachProcess(&SourceProcess->Pcb, &ApcState); + NtClose(SourceHandle); + KeUnstackDetachProcess(&ApcState); } - KeLeaveCriticalRegion(); + /* Check if we had an access state */ + if (PassedAccessState) SeDeleteAccessState(PassedAccessState); + /* Now check if incrementing actually failed */ + if (!NT_SUCCESS(Status)) + { + /* Dereference the source object */ + ObDereferenceObject(SourceObject); + return Status; + } + + /* Now create the handle */ + ObDereferenceObject(SourceObject); + NewHandle = ExCreateHandle(HandleTable, &NewHandleEntry); + if (!NewHandle) + { + /* Undo the increment */ + ObpDecrementHandleCount(SourceObject, + TargetProcess, + TargetAccess); + + /* Deference the object and set failure status */ + ObDereferenceObject(SourceObject); + Status = STATUS_INSUFFICIENT_RESOURCES; + } + + /* Return the handle */ + if (TargetHandle) *TargetHandle = NewHandle; + + /* Return status */ + OBTRACE("OBTRACE - %s - Duplicated handle: %lx for %p into %p. Source: %p HC PC %lx %lx\n", + __FUNCTION__, + NewHandle, + SourceProcess, + TargetProcess, + SourceObject, + ObjectHeader->PointerCount, + ObjectHeader->HandleCount); return Status; } @@ -1934,184 +1978,118 @@ NtClose(IN HANDLE Handle) return ObpCloseHandle(Handle, ExGetPreviousMode()); } -/* -* @implemented -*/ -NTSTATUS STDCALL -NtDuplicateObject (IN HANDLE SourceProcessHandle, - IN HANDLE SourceHandle, - IN HANDLE TargetProcessHandle, - OUT PHANDLE TargetHandle OPTIONAL, - IN ACCESS_MASK DesiredAccess, - IN ULONG HandleAttributes, - IN ULONG Options) +NTSTATUS +NTAPI +NtDuplicateObject(IN HANDLE SourceProcessHandle, + IN HANDLE SourceHandle, + IN HANDLE TargetProcessHandle OPTIONAL, + OUT PHANDLE TargetHandle OPTIONAL, + IN ACCESS_MASK DesiredAccess, + IN ULONG HandleAttributes, + IN ULONG Options) { - PEPROCESS SourceProcess; - PEPROCESS TargetProcess; - PEPROCESS CurrentProcess; + PEPROCESS SourceProcess, TargetProcess, Target; HANDLE hTarget; - BOOLEAN AttachedToProcess = FALSE; - KPROCESSOR_MODE PreviousMode; - KAPC_STATE ApcState; + KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); NTSTATUS Status = STATUS_SUCCESS; - ACCESS_STATE AccessState; - AUX_DATA AuxData; - PACCESS_STATE PassedAccessState = NULL; - PAGED_CODE(); + OBTRACE("OBTRACE - %s - Duplicating handle: %lx for %lx into %lx.\n", + __FUNCTION__, + SourceHandle, + SourceProcessHandle, + TargetProcessHandle); - PreviousMode = ExGetPreviousMode(); - - if(TargetHandle != NULL && PreviousMode != KernelMode) + if((TargetHandle) && (PreviousMode != KernelMode)) { + /* Enter SEH */ _SEH_TRY { + /* Probe the handle */ ProbeForWriteHandle(TargetHandle); } _SEH_HANDLE { + /* Get the exception status */ Status = _SEH_GetExceptionCode(); } _SEH_END; - if(!NT_SUCCESS(Status)) - { - return Status; - } + /* Fail if the pointer was invalid */ + if (!NT_SUCCESS(Status)) return Status; } + /* Now reference the input handle */ Status = ObReferenceObjectByHandle(SourceProcessHandle, - PROCESS_DUP_HANDLE, - NULL, - PreviousMode, - (PVOID*)&SourceProcess, - NULL); - if (!NT_SUCCESS(Status)) + PROCESS_DUP_HANDLE, + PsProcessType, + PreviousMode, + (PVOID*)&SourceProcess, + NULL); + if (!NT_SUCCESS(Status)) return(Status); + + /* Check if got a target handle */ + if (TargetProcessHandle) { - return(Status); - } - - Status = ObReferenceObjectByHandle(TargetProcessHandle, - PROCESS_DUP_HANDLE, - NULL, - PreviousMode, - (PVOID*)&TargetProcess, - NULL); - if (!NT_SUCCESS(Status)) - { - ObDereferenceObject(SourceProcess); - return(Status); - } - - CurrentProcess = PsGetCurrentProcess(); - - /* Check for magic handle first */ - if (SourceHandle == NtCurrentThread() || - SourceHandle == NtCurrentProcess()) - { - PVOID ObjectBody; - POBJECT_TYPE ObjectType; - - ObjectType = (SourceHandle == NtCurrentThread()) ? PsThreadType : PsProcessType; - - Status = ObReferenceObjectByHandle(SourceHandle, - 0, - ObjectType, - PreviousMode, - &ObjectBody, - NULL); - if(NT_SUCCESS(Status)) + /* Now reference the output handle */ + Status = ObReferenceObjectByHandle(TargetProcessHandle, + PROCESS_DUP_HANDLE, + PsProcessType, + PreviousMode, + (PVOID*)&TargetProcess, + NULL); + if (NT_SUCCESS(Status)) { - if (Options & DUPLICATE_SAME_ACCESS) - { - /* grant all access rights */ - DesiredAccess = ((ObjectType == PsThreadType) ? THREAD_ALL_ACCESS : PROCESS_ALL_ACCESS); - } - else - { - if (DesiredAccess & GENERIC_ACCESS) - { - RtlMapGenericMask(&DesiredAccess, - &ObjectType->TypeInfo.GenericMapping); - } - } - - if (TargetProcess != CurrentProcess) - { - KeStackAttachProcess(&TargetProcess->Pcb, - &ApcState); - AttachedToProcess = TRUE; - } - - /* Use our built-in access state */ - PassedAccessState = &AccessState; - Status = SeCreateAccessState(&AccessState, - &AuxData, - DesiredAccess, - &ObjectType->TypeInfo.GenericMapping); - - /* Add a new handle */ - Status = ObpIncrementHandleCount(ObjectBody, - PassedAccessState, - PreviousMode, - HandleAttributes, - PsGetCurrentProcess(), - ObDuplicateHandle); - - if (AttachedToProcess) - { - KeUnstackDetachProcess(&ApcState); - AttachedToProcess = FALSE; - } - - ObDereferenceObject(ObjectBody); - - if (Options & DUPLICATE_CLOSE_SOURCE) - { - if (SourceProcess != CurrentProcess) - { - KeStackAttachProcess(&SourceProcess->Pcb, - &ApcState); - AttachedToProcess = TRUE; - } - - NtClose(SourceHandle); - - if (AttachedToProcess) - { - KeUnstackDetachProcess(&ApcState); - } - } + /* Use this target process */ + Target = TargetProcess; + } + else + { + /* No target process */ + Target = NULL; } } else { - Status = ObDuplicateObject(SourceProcess, - TargetProcess, - SourceHandle, - &hTarget, - DesiredAccess, - HandleAttributes, - Options); + /* No target process */ + Status = STATUS_SUCCESS; + Target = NULL; } - ObDereferenceObject(TargetProcess); - ObDereferenceObject(SourceProcess); + /* Call the internal routine */ + Status = ObDuplicateObject(SourceProcess, + SourceHandle, + Target, + &hTarget, + DesiredAccess, + HandleAttributes, + Options, + PreviousMode); - if(NT_SUCCESS(Status) && TargetHandle != NULL) + /* Check if the caller wanted the return handle */ + if (TargetHandle) { + /* Protect the write to user mode */ _SEH_TRY { + /* Write the new handle */ *TargetHandle = hTarget; } _SEH_HANDLE { + /* Otherwise, get the exception code */ Status = _SEH_GetExceptionCode(); } _SEH_END; } + /* Dereference the processes */ + OBTRACE("OBTRACE - %s - Duplicated handle: %lx into %lx S %lx\n", + __FUNCTION__, + hTarget, + TargetProcessHandle, + Status); + ObDereferenceObject(TargetProcess); + ObDereferenceObject(SourceProcess); return Status; } - /* EOF */ diff --git a/reactos/ntoskrnl/ob/obname.c b/reactos/ntoskrnl/ob/obname.c index 4d67dd10ea4..8357eb91313 100644 --- a/reactos/ntoskrnl/ob/obname.c +++ b/reactos/ntoskrnl/ob/obname.c @@ -394,7 +394,7 @@ Next: /* PUBLIC FUNCTIONS *********************************************************/ NTSTATUS -STDCALL +NTAPI ObQueryNameString(IN PVOID Object, OUT POBJECT_NAME_INFORMATION ObjectNameInfo, IN ULONG Length, @@ -418,7 +418,8 @@ ObQueryNameString(IN PVOID Object, TRUE, //fixme ObjectNameInfo, Length, - ReturnLength); + ReturnLength, + KernelMode); } /* Check if the object doesn't even have a name */