mirror of
https://github.com/reactos/reactos.git
synced 2025-06-04 08:50:27 +00:00
- Final fixes to ObpCreateHandle that I can think of before splitting Create/Increment (might be lacking some security checks or trace/database functionality, but I haven't found any info on the latter, while the former I will stub, but I don't have the skills to imlement (ObAssignObjectSecurity)):
* Honour ObjectType passed to the function and fail if it doesn't match. * Use table-based logic instead of process-based logic for Kernel vs User-mode handles (same change that's been done all over the place, since it requires only one dereference of the process object). * Do the GENERIC/MAXIMUM_ALLOWED logic directly inside the ACCESS_STATE structure. * This is where we should call the OpenProcedure (acc. to Gl00my), but this kills win32k -- investigate, #ifed out for now. * Increase the object type's number of handles as well. * Set the handle table entry's ObAttributes correctly; the old code seems to have been messing that up. * Honour the AdditionalReferences parameter and do referencing bias if requested. * Honour the ReturnedObject parameter to return the object pointer back to the caller. * Add OBTRACEing to the function. * If we failed because a handle couldn't be allocated, use the distinguied STATUS_INSUFFICIENT_RESOURCES error code instead of the generic STATUS_UNSCUCESFFUL, and backout all the changes we made by calling ObpDecrementHandleCount. svn path=/trunk/; revision=22267
This commit is contained in:
parent
39bf2b48c2
commit
da2029d89e
1 changed files with 124 additions and 54 deletions
|
@ -359,7 +359,7 @@ ObpCreateHandle(IN OB_OPEN_REASON OpenReason, // Gloomy says this is "enables Se
|
|||
// ObOpenHandle == 1, I'm guessing this is actually the
|
||||
// OpenReason. Also makes sense since this function is shared
|
||||
// by Duplication, Creation and Opening.
|
||||
IN PVOID ObjectBody,
|
||||
IN PVOID Object,
|
||||
IN POBJECT_TYPE Type OPTIONAL,
|
||||
IN PACCESS_STATE AccessState,
|
||||
IN ULONG AdditionalReferences,
|
||||
|
@ -369,92 +369,162 @@ ObpCreateHandle(IN OB_OPEN_REASON OpenReason, // Gloomy says this is "enables Se
|
|||
OUT PHANDLE ReturnedHandle)
|
||||
{
|
||||
HANDLE_TABLE_ENTRY NewEntry;
|
||||
PEPROCESS Process, CurrentProcess;
|
||||
PVOID HandleTable;
|
||||
POBJECT_HEADER ObjectHeader;
|
||||
POBJECT_TYPE ObjectType;
|
||||
HANDLE Handle;
|
||||
KAPC_STATE ApcState;
|
||||
BOOLEAN AttachedToProcess = FALSE;
|
||||
ACCESS_MASK GrantedAccess;
|
||||
|
||||
PAGED_CODE();
|
||||
/* Get the object header and type */
|
||||
ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
|
||||
ObjectType = ObjectHeader->Type;
|
||||
OBTRACE("OBTRACE - %s - Creating handle for: %p. Reason: %lx. HC LC %lx %lx\n",
|
||||
__FUNCTION__,
|
||||
Object,
|
||||
OpenReason,
|
||||
ObjectHeader->HandleCount,
|
||||
ObjectHeader->PointerCount);
|
||||
|
||||
DPRINT("ObpCreateHandle(obj %p)\n",ObjectBody);
|
||||
|
||||
ASSERT(ObjectBody);
|
||||
|
||||
CurrentProcess = PsGetCurrentProcess();
|
||||
|
||||
ObjectHeader = OBJECT_TO_OBJECT_HEADER(ObjectBody);
|
||||
|
||||
/* check that this is a valid kernel pointer */
|
||||
ASSERT((ULONG_PTR)ObjectHeader & EX_HANDLE_ENTRY_LOCKED);
|
||||
|
||||
GrantedAccess = AccessState->RemainingDesiredAccess |
|
||||
AccessState->PreviouslyGrantedAccess;
|
||||
if (GrantedAccess & MAXIMUM_ALLOWED)
|
||||
/* Check if the types match */
|
||||
if ((Type) && (ObjectType != Type))
|
||||
{
|
||||
GrantedAccess &= ~MAXIMUM_ALLOWED;
|
||||
GrantedAccess |= GENERIC_ALL;
|
||||
/* They don't; fail */
|
||||
DPRINT1("Type mismatch: %wZ, %wZ\n", &ObjectType->Name, &Type->Name);
|
||||
return STATUS_OBJECT_TYPE_MISMATCH;
|
||||
}
|
||||
|
||||
if (GrantedAccess & GENERIC_ACCESS)
|
||||
/* Check if this is a kernel handle */
|
||||
if ((HandleAttributes & OBJ_KERNEL_HANDLE) && (AccessMode == KernelMode))
|
||||
{
|
||||
RtlMapGenericMask(&GrantedAccess,
|
||||
&ObjectHeader->Type->TypeInfo.GenericMapping);
|
||||
}
|
||||
/* Set the handle table */
|
||||
HandleTable = ObpKernelHandleTable;
|
||||
|
||||
NewEntry.Object = ObjectHeader;
|
||||
if(HandleAttributes & OBJ_INHERIT)
|
||||
NewEntry.ObAttributes |= EX_HANDLE_ENTRY_INHERITABLE;
|
||||
else
|
||||
NewEntry.ObAttributes &= ~EX_HANDLE_ENTRY_INHERITABLE;
|
||||
NewEntry.GrantedAccess = GrantedAccess;
|
||||
|
||||
if ((HandleAttributes & OBJ_KERNEL_HANDLE) &&
|
||||
ExGetPreviousMode == KernelMode)
|
||||
{
|
||||
Process = PsInitialSystemProcess;
|
||||
if (Process != CurrentProcess)
|
||||
/* Check if we're not in the system process */
|
||||
if (PsGetCurrentProcess() != PsInitialSystemProcess)
|
||||
{
|
||||
KeStackAttachProcess(&Process->Pcb,
|
||||
&ApcState);
|
||||
/* Attach to the system process */
|
||||
KeStackAttachProcess(&PsInitialSystemProcess->Pcb, &ApcState);
|
||||
AttachedToProcess = TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Process = CurrentProcess;
|
||||
/* mask out the OBJ_KERNEL_HANDLE attribute */
|
||||
HandleAttributes &= ~OBJ_KERNEL_HANDLE;
|
||||
/* Get the current handle table */
|
||||
HandleTable = PsGetCurrentProcess()->ObjectTable;
|
||||
}
|
||||
|
||||
Handle = ExCreateHandle(Process->ObjectTable,
|
||||
&NewEntry);
|
||||
|
||||
if (AttachedToProcess)
|
||||
/* Convert MAXIMUM_ALLOWED to GENERIC_ALL */
|
||||
if (AccessState->RemainingDesiredAccess & MAXIMUM_ALLOWED)
|
||||
{
|
||||
KeUnstackDetachProcess(&ApcState);
|
||||
/* Mask out MAXIMUM_ALLOWED and stick GENERIC_ALL instead */
|
||||
AccessState->RemainingDesiredAccess &= ~MAXIMUM_ALLOWED;
|
||||
AccessState->RemainingDesiredAccess |= GENERIC_ALL;
|
||||
}
|
||||
|
||||
if(Handle != NULL)
|
||||
/* Check if we have to map the GENERIC mask */
|
||||
if (AccessState->RemainingDesiredAccess & GENERIC_ACCESS)
|
||||
{
|
||||
/* Map it to the correct access masks */
|
||||
RtlMapGenericMask(&AccessState->RemainingDesiredAccess,
|
||||
&ObjectType->TypeInfo.GenericMapping);
|
||||
}
|
||||
|
||||
/* Increase the handle count */
|
||||
if(InterlockedIncrement(&ObjectHeader->HandleCount) == 1)
|
||||
{
|
||||
/*
|
||||
* FIXME: Is really needed? Perhaps we should instead take
|
||||
* advantage of the AddtionalReferences parameter to add the
|
||||
* bias when required. This might be the source of the mysterious
|
||||
* ReactOS bug where ObInsertObject *requires* an immediate dereference
|
||||
* even in a success case.
|
||||
* Whill have to think more about this when doing the Increment/Create
|
||||
* split later.
|
||||
*/
|
||||
ObReferenceObject(Object);
|
||||
}
|
||||
|
||||
/* Check if we have an open procedure */
|
||||
#if 0
|
||||
if (ObjectType->TypeInfo.OpenProcedure)
|
||||
{
|
||||
/* Call it */
|
||||
ObjectType->TypeInfo.OpenProcedure(OpenReason,
|
||||
PsGetCurrentProcess(),
|
||||
Object,
|
||||
AccessState->
|
||||
PreviouslyGrantedAccess,
|
||||
0);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Increase total number of handles */
|
||||
ObjectType->TotalNumberOfHandles++;
|
||||
|
||||
/* Save the object header (assert its validity too) */
|
||||
ASSERT((ULONG_PTR)ObjectHeader & EX_HANDLE_ENTRY_LOCKED);
|
||||
NewEntry.Object = ObjectHeader;
|
||||
|
||||
/* Mask out the internal attributes */
|
||||
NewEntry.ObAttributes |= HandleAttributes &
|
||||
(EX_HANDLE_ENTRY_PROTECTFROMCLOSE |
|
||||
EX_HANDLE_ENTRY_INHERITABLE |
|
||||
EX_HANDLE_ENTRY_AUDITONCLOSE);
|
||||
|
||||
/* Save the access mask */
|
||||
NewEntry.GrantedAccess = AccessState->RemainingDesiredAccess |
|
||||
AccessState->PreviouslyGrantedAccess;
|
||||
|
||||
/*
|
||||
* Create the actual handle. We'll need to do this *after* calling
|
||||
* ObpIncrementHandleCount to make sure that Object Security is valid
|
||||
* (specified in Gl00my documentation on Ob)
|
||||
*/
|
||||
OBTRACE("OBTRACE - %s - Handle Properties: [%p-%lx-%lx]\n",
|
||||
__FUNCTION__,
|
||||
NewEntry.Object, NewEntry.ObAttributes & 3, NewEntry.GrantedAccess);
|
||||
Handle = ExCreateHandle(HandleTable, &NewEntry);
|
||||
|
||||
/* Detach it needed */
|
||||
if (AttachedToProcess) KeUnstackDetachProcess(&ApcState);
|
||||
|
||||
/* Check if we got a handle */
|
||||
if(Handle)
|
||||
{
|
||||
/* Handle extra references */
|
||||
while (AdditionalReferences--)
|
||||
{
|
||||
/* Increment the count */
|
||||
InterlockedIncrement(&ObjectHeader->PointerCount);
|
||||
}
|
||||
|
||||
/* Check if this was a kernel handle */
|
||||
if (HandleAttributes & OBJ_KERNEL_HANDLE)
|
||||
{
|
||||
/* mark the handle value */
|
||||
/* Set the kernel handle bit */
|
||||
Handle = ObMarkHandleAsKernelHandle(Handle);
|
||||
}
|
||||
|
||||
if(InterlockedIncrement(&ObjectHeader->HandleCount) == 1)
|
||||
{
|
||||
ObReferenceObject(ObjectBody);
|
||||
}
|
||||
|
||||
/* Return handle and object */
|
||||
*ReturnedHandle = Handle;
|
||||
if (ReturnedObject) *ReturnedObject = Object;
|
||||
|
||||
/* Return success */
|
||||
OBTRACE("OBTRACE - %s - Incremented count for: %p. Reason: %lx HC LC %lx %lx\n",
|
||||
__FUNCTION__,
|
||||
Object,
|
||||
OpenReason,
|
||||
ObjectHeader->HandleCount,
|
||||
ObjectHeader->PointerCount);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
/* Decrement the handle count and fail */
|
||||
ObpDecrementHandleCount(&ObjectHeader->Body,
|
||||
PsGetCurrentProcess(),
|
||||
NewEntry.GrantedAccess);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
/*++
|
||||
|
|
Loading…
Reference in a new issue