- Implement setting/getting heap user values and flags (very easy provided heap design is now proper). Amount of winetest failures is down to 12 (but 3 crashes in child processes).

svn path=/trunk/; revision=49069
This commit is contained in:
Aleksey Bragin 2010-10-09 12:49:30 +00:00
parent 60ede58f09
commit c76fdb3cd6

View file

@ -12,6 +12,7 @@
http://binglongx.spaces.live.com/blog/cns!142CBF6D49079DE8!596.entry http://binglongx.spaces.live.com/blog/cns!142CBF6D49079DE8!596.entry
http://www.phreedom.org/research/exploits/asn1-bitstring/ http://www.phreedom.org/research/exploits/asn1-bitstring/
http://illmatics.com/Understanding_the_LFH.pdf http://illmatics.com/Understanding_the_LFH.pdf
http://www.alex-ionescu.com/?p=18
*/ */
/* INCLUDES *****************************************************************/ /* INCLUDES *****************************************************************/
@ -243,7 +244,7 @@ typedef struct _HEAP_ENTRY_EXTRA
{ {
USHORT AllocatorBackTraceIndex; USHORT AllocatorBackTraceIndex;
USHORT TagIndex; USHORT TagIndex;
ULONG Settable; ULONG_PTR Settable;
}; };
UINT64 ZeroInit; UINT64 ZeroInit;
}; };
@ -1153,7 +1154,7 @@ RtlpDestroyHeapSegment(PHEAP_SEGMENT Segment)
if (Segment->SegmentFlags & HEAP_USER_ALLOCATED) return; if (Segment->SegmentFlags & HEAP_USER_ALLOCATED) return;
BaseAddress = Segment->BaseAddress; BaseAddress = Segment->BaseAddress;
DPRINT1("Destroying segment %p, BA %p\n", Segment, BaseAddress); DPRINT("Destroying segment %p, BA %p\n", Segment, BaseAddress);
/* Release virtual memory */ /* Release virtual memory */
Status = ZwFreeVirtualMemory(NtCurrentProcess(), Status = ZwFreeVirtualMemory(NtCurrentProcess(),
@ -2983,7 +2984,15 @@ RtlReAllocateHeap(HANDLE HeapPtr,
Flags |= HEAP_SETTABLE_USER_VALUE | ((InUseEntry->Flags & HEAP_ENTRY_SETTABLE_FLAGS) << 4); Flags |= HEAP_SETTABLE_USER_VALUE | ((InUseEntry->Flags & HEAP_ENTRY_SETTABLE_FLAGS) << 4);
UNIMPLEMENTED; /* Get pointer to the old extra data */
OldExtra = RtlpGetExtraStuffPointer(InUseEntry);
/* Save tag index if it was set */
if (OldExtra->TagIndex &&
!(OldExtra->TagIndex & HEAP_PSEUDO_TAG_FLAG))
{
Flags |= OldExtra->TagIndex << HEAP_TAG_SHIFT;
}
} }
else if (InUseEntry->SmallTagIndex) else if (InUseEntry->SmallTagIndex)
{ {
@ -3131,7 +3140,7 @@ RtlUnlockHeap(HANDLE HeapPtr)
/* Check if it's really a heap */ /* Check if it's really a heap */
if (Heap->Signature != HEAP_SIGNATURE) return FALSE; if (Heap->Signature != HEAP_SIGNATURE) return FALSE;
/* Lock if it's lockable */ /* Unlock if it's lockable */
if (!(Heap->Flags & HEAP_NO_SERIALIZE)) if (!(Heap->Flags & HEAP_NO_SERIALIZE))
{ {
RtlLeaveHeapLock(Heap->LockVariable); RtlLeaveHeapLock(Heap->LockVariable);
@ -3307,8 +3316,49 @@ RtlSetUserValueHeap(IN PVOID HeapHandle,
IN PVOID BaseAddress, IN PVOID BaseAddress,
IN PVOID UserValue) IN PVOID UserValue)
{ {
UNIMPLEMENTED; PHEAP Heap = (PHEAP)HeapHandle;
return FALSE; PHEAP_ENTRY HeapEntry;
PHEAP_ENTRY_EXTRA Extra;
BOOLEAN HeapLocked = FALSE;
/* Force flags */
Flags |= Heap->Flags;
/* Lock if it's lockable */
if (!(Heap->Flags & HEAP_NO_SERIALIZE))
{
RtlEnterHeapLock(Heap->LockVariable);
HeapLocked = TRUE;
}
/* Get a pointer to the entry */
HeapEntry = (PHEAP_ENTRY)BaseAddress - 1;
/* If it's a free entry - return error */
if (!(HeapEntry->Flags & HEAP_ENTRY_BUSY))
{
RtlSetLastWin32ErrorAndNtStatusFromNtStatus(STATUS_INVALID_PARAMETER);
/* Release the heap lock if it was acquired */
if (HeapLocked)
RtlLeaveHeapLock(Heap->LockVariable);
return FALSE;
}
/* Check if this entry has an extra stuff associated with it */
if (HeapEntry->Flags & HEAP_ENTRY_EXTRA_PRESENT)
{
/* Use extra to store the value */
Extra = RtlpGetExtraStuffPointer(HeapEntry);
Extra->Settable = (ULONG_PTR)UserValue;
}
/* Release the heap lock if it was acquired */
if (HeapLocked)
RtlLeaveHeapLock(Heap->LockVariable);
return TRUE;
} }
/* /*
@ -3319,9 +3369,47 @@ NTAPI
RtlSetUserFlagsHeap(IN PVOID HeapHandle, RtlSetUserFlagsHeap(IN PVOID HeapHandle,
IN ULONG Flags, IN ULONG Flags,
IN PVOID BaseAddress, IN PVOID BaseAddress,
IN ULONG UserFlags) IN ULONG UserFlagsReset,
IN ULONG UserFlagsSet)
{ {
return FALSE; PHEAP Heap = (PHEAP)HeapHandle;
PHEAP_ENTRY HeapEntry;
BOOLEAN HeapLocked = FALSE;
/* Force flags */
Flags |= Heap->Flags;
/* Lock if it's lockable */
if (!(Heap->Flags & HEAP_NO_SERIALIZE))
{
RtlEnterHeapLock(Heap->LockVariable);
HeapLocked = TRUE;
}
/* Get a pointer to the entry */
HeapEntry = (PHEAP_ENTRY)BaseAddress - 1;
/* If it's a free entry - return error */
if (!(HeapEntry->Flags & HEAP_ENTRY_BUSY))
{
RtlSetLastWin32ErrorAndNtStatusFromNtStatus(STATUS_INVALID_PARAMETER);
/* Release the heap lock if it was acquired */
if (HeapLocked)
RtlLeaveHeapLock(Heap->LockVariable);
return FALSE;
}
/* Set / reset flags */
HeapEntry->Flags &= ~(UserFlagsReset >> 4);
HeapEntry->Flags |= (UserFlagsSet >> 4);
/* Release the heap lock if it was acquired */
if (HeapLocked)
RtlLeaveHeapLock(Heap->LockVariable);
return TRUE;
} }
/* /*
@ -3335,8 +3423,56 @@ RtlGetUserInfoHeap(IN PVOID HeapHandle,
OUT PVOID *UserValue, OUT PVOID *UserValue,
OUT PULONG UserFlags) OUT PULONG UserFlags)
{ {
UNIMPLEMENTED; PHEAP Heap = (PHEAP)HeapHandle;
return FALSE; PHEAP_ENTRY HeapEntry;
PHEAP_ENTRY_EXTRA Extra;
BOOLEAN HeapLocked = FALSE;
/* Force flags */
Flags |= Heap->Flags;
/* Lock if it's lockable */
if (!(Heap->Flags & HEAP_NO_SERIALIZE))
{
RtlEnterHeapLock(Heap->LockVariable);
HeapLocked = TRUE;
}
/* Get a pointer to the entry */
HeapEntry = (PHEAP_ENTRY)BaseAddress - 1;
/* If it's a free entry - return error */
if (!(HeapEntry->Flags & HEAP_ENTRY_BUSY))
{
RtlSetLastWin32ErrorAndNtStatusFromNtStatus(STATUS_INVALID_PARAMETER);
/* Release the heap lock if it was acquired */
if (HeapLocked)
RtlLeaveHeapLock(Heap->LockVariable);
return FALSE;
}
/* Check if this entry has an extra stuff associated with it */
if (HeapEntry->Flags & HEAP_ENTRY_EXTRA_PRESENT)
{
/* Get pointer to extra data */
Extra = RtlpGetExtraStuffPointer(HeapEntry);
/* Pass user value */
if (UserValue)
*UserValue = (PVOID)Extra->Settable;
/* Decode and return user flags */
if (UserFlags)
*UserFlags = (HeapEntry->Flags & HEAP_ENTRY_SETTABLE_FLAGS) << 4;
}
/* Release the heap lock if it was acquired */
if (HeapLocked)
RtlLeaveHeapLock(Heap->LockVariable);
return TRUE;
} }
/* /*