Merge pull request #828 from PatrickvL/Krnl_Ob

Kernel : Place object names before OBJECT_HEADER
This commit is contained in:
Luke Usher 2018-01-04 10:45:31 +00:00 committed by GitHub
commit 6abb41304a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 111 additions and 34 deletions

View File

@ -103,6 +103,88 @@ xboxkrnl::NTSTATUS EmuObFindObjectByHandle
return Status;
}
xboxkrnl::POBJECT_HEADER
EmuObHeaderFromObject
(
IN PVOID Object
)
{
//assert(Object);
return (xboxkrnl::POBJECT_HEADER)((uintptr_t)Object - offsetof(xboxkrnl::OBJECT_HEADER, Body));
// Note : Can't use OBJECT_TO_OBJECT_HEADER, it leads to ambiguous symbol errors
}
int
EmuObStringPadding
(
IN INT NameLength
)
{
if (NameLength == 0)
return 0;
// Trailing zero, plus the number of bytes to align the next part on a 32-bit address
return 1 + sizeof(uint32_t) - ((NameLength + 1) & (sizeof(uint32_t) - 1));
}
int
EmuObNameBufferSize
(
IN INT NameLength
)
{
//assert(NameLength > 0);
return NameLength
+ EmuObStringPadding(NameLength)
+ sizeof(xboxkrnl::OBJECT_STRING);
}
xboxkrnl::POBJECT_STRING
EmuObStringFromObjectHeader
(
IN xboxkrnl::POBJECT_HEADER ObjectHeader
)
{
//assert(ObjectHeader);
if (ObjectHeader->Flags & OB_FLAG_NAMED_OBJECT)
return (xboxkrnl::POBJECT_STRING)((uintptr_t)ObjectHeader - sizeof(xboxkrnl::OBJECT_STRING));
else
return xbnullptr;
}
xboxkrnl::POBJECT_STRING
EmuObStringFromObject
(
IN PVOID Object
)
{
//assert(Object);
xboxkrnl::POBJECT_HEADER ObjectHeader = EmuObHeaderFromObject(Object);
return EmuObStringFromObjectHeader(ObjectHeader);
}
void *
EmuObjectToBasePointer
(
IN PVOID Object
)
{
//assert(Object);
xboxkrnl::POBJECT_HEADER ObjectHeader = EmuObHeaderFromObject(Object);
uintptr_t Base = (uintptr_t)ObjectHeader;
xboxkrnl::POBJECT_STRING Name = EmuObStringFromObjectHeader(ObjectHeader);
if (Name != xbnullptr) {
Base -= EmuObNameBufferSize(Name->Length);
}
return (void *)Base;
}
xboxkrnl::NTSTATUS EmuObFindObjectByName
(
IN xboxkrnl::POBJECT_STRING ObjectName,
@ -118,6 +200,7 @@ xboxkrnl::NTSTATUS EmuObFindObjectByName
LOG_UNIMPLEMENTED();
// TODO : Implement a mechanism by which all named objects can be queried. See comments in ObCreateObject
// For all visited objects, use EmuObStringFromObject to get to their name (or xbnullptr when its absent)
return Status;
}
@ -141,8 +224,7 @@ XBSYSAPI EXPORTNUM(239) xboxkrnl::NTSTATUS NTAPI xboxkrnl::ObCreateObject
LOG_FUNC_END;
NTSTATUS Status = STATUS_SUCCESS;
OBJECT_STRING TmpName = { 0 };
int NameSize = 0;
int NameBufferSize = 0;
if (ObjectAttributes != NULL && ObjectAttributes->ObjectName != NULL) {
if (ObjectAttributes->ObjectName->Length == 0) {
@ -150,52 +232,50 @@ XBSYSAPI EXPORTNUM(239) xboxkrnl::NTSTATUS NTAPI xboxkrnl::ObCreateObject
}
else {
// TODO : Split name in parts?
TmpName.Buffer = ObjectAttributes->ObjectName->Buffer;
TmpName.Length = ObjectAttributes->ObjectName->Length;
TmpName.MaximumLength = ObjectAttributes->ObjectName->Length;
NameSize = sizeof(OBJECT_STRING) + TmpName.Length + sizeof('\0'); // trailing zero
NameBufferSize = EmuObNameBufferSize(ObjectAttributes->ObjectName->Length);
}
}
if (Status == STATUS_SUCCESS) {
// Allocate the object
int ObjectSize = offsetof(OBJECT_HEADER, Body) + ObjectBodySize;
int ObjectBufferSize = NameBufferSize + offsetof(OBJECT_HEADER, Body) + ObjectBodySize;
// TODO : Is this ever something else than ExAllocatePoolWithTag ?
POBJECT_HEADER ObjectHeader = (POBJECT_HEADER)ObjectType->AllocateProcedure(ObjectSize + NameSize, ObjectType->PoolTag);
if (ObjectHeader == NULL) {
void *ObjectBuffer = ObjectType->AllocateProcedure(ObjectBufferSize, ObjectType->PoolTag);
if (ObjectBuffer == NULL) {
// Detected out of memory
*Object = NULL;
Status = STATUS_INSUFFICIENT_RESOURCES;
}
else {
// Remember Name buffer start, and retrieve object header pointer :
// Note : Object memory-layout will be :
// { Name, '\0', Four-byte-alignment padding, OBJECT_STRING } OBJECT_HEADER
char *NameBuffer = (char *)ObjectBuffer;
POBJECT_HEADER ObjectHeader = (OBJECT_HEADER*)((uintptr_t)ObjectBuffer + NameBufferSize);
// Initialize default values of object (header) :
ObjectHeader->PointerCount = 1;
ObjectHeader->HandleCount = 0;
ObjectHeader->Type = ObjectType;
if (NameSize == 0)
ObjectHeader->Flags = 0;
else {
ObjectHeader->Flags = 0;
// TODO : Is this needed? : memset(&ObjectHeader->Body, 0, ObjectBodySize);
// Prepend name (if any) :
if (NameBufferSize > 0) {
LOG_INCOMPLETE();
// TODO : For other Ob* API's it must become possible to get from
// and Object(Header) address to the Name. Right now, this requires
// adding ObjectSize to ObjectHeader. This won't be available outside
// ObCreateObject, so we need a better solution for this.
// It might be possible to put the OBJECT_STRING struct BEFORE the
// ObjectHeader (and the NameBuffer itself before that), which would
// make it possible to simply offset everything off an Object.
// It might also be possible to insert a linked list struct, so
// TODO : It might be possible to insert a linked list struct, so
// ObReferenceObjectByName can iterate over all named objects.
// (It's probably wise to use one list per pool, to reduce the number
// of objects to walk through.)
// Copy name after object (we've reserved NameSize bytes there) :
OBJECT_STRING *Name = (OBJECT_STRING *)((char *)ObjectHeader + ObjectSize);
char *NameBuffer = (char *)Name + sizeof(OBJECT_STRING);
// Initialize name struct :
Name->Buffer = NameBuffer;
Name->Length = Name->MaximumLength = TmpName.Length;
OBJECT_STRING *ObjectName = (OBJECT_STRING *)((uintptr_t)ObjectHeader - sizeof(OBJECT_STRING));
ObjectName->Buffer = NameBuffer;
ObjectName->Length = ObjectName->MaximumLength = ObjectAttributes->ObjectName->Length;
// Copy name into reserved buffer :
memcpy(NameBuffer, TmpName.Buffer, TmpName.Length);
memcpy(NameBuffer, ObjectAttributes->ObjectName->Buffer, ObjectAttributes->ObjectName->Length);
// Terminate the name string with a trailing zero :
NameBuffer[ObjectAttributes->ObjectName->Length] = '\0';
// Mark object as named :
ObjectHeader->Flags = OB_FLAG_NAMED_OBJECT;
// TODO : Verify this all works, then use it somehow
@ -475,17 +555,14 @@ XBSYSAPI EXPORTNUM(250) xboxkrnl::VOID FASTCALL xboxkrnl::ObfDereferenceObject
LOG_FUNC_ONE_ARG_OUT(Object);
POBJECT_HEADER ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
if (InterlockedDecrement(&ObjectHeader->PointerCount) == 0)
{
if (InterlockedDecrement(&ObjectHeader->PointerCount) == 0) {
POBJECT_TYPE ObjectType = ObjectHeader->Type;
if (ObjectType->DeleteProcedure != NULL)
if (ObjectType->DeleteProcedure != NULL) {
ObjectType->DeleteProcedure(Object);
LOG_INCOMPLETE(); // TODO : How to handle named objects? See comments in ObCreateObject
}
ObjectType->FreeProcedure(ObjectHeader); // TODO : Is this ever something else than ExFreePool ?
void *ObjectBase = EmuObjectToBasePointer(Object);
ObjectType->FreeProcedure(ObjectBase); // TODO : Is this ever something else than ExFreePool ?
}
}