Esempio n. 1
0
static MDL *
BalloonAllocatePagesForMdl(
    IN  ULONG       Count
    )
{
    LARGE_INTEGER   LowAddress;
    LARGE_INTEGER   HighAddress;
    LARGE_INTEGER   SkipBytes;
    SIZE_T          TotalBytes;
    MDL             *Mdl;

    XM_ASSERT(AllocatorInitialized);

    LowAddress.QuadPart = 0ull;
    HighAddress.QuadPart = ~0ull;
    SkipBytes.QuadPart = 0ull;
    TotalBytes = (SIZE_T)Count << PAGE_SHIFT;
    
    if (__MmAllocatePagesForMdlEx != NULL)
        Mdl = __MmAllocatePagesForMdlEx(LowAddress,
                                        HighAddress,
                                        SkipBytes,
                                        TotalBytes,
                                        MmCached,
                                        MM_DONT_ZERO_ALLOCATION);
    else
        Mdl = MmAllocatePagesForMdl(LowAddress,
                                    HighAddress,
                                    SkipBytes,
                                    TotalBytes);

    if (Mdl == NULL)
        goto done;

    XM_ASSERT((Mdl->MdlFlags & (MDL_MAPPED_TO_SYSTEM_VA |
                                MDL_PARTIAL_HAS_BEEN_MAPPED |
                                MDL_PARTIAL |
                                MDL_PARENT_MAPPED_SYSTEM_VA |
                                MDL_SOURCE_IS_NONPAGED_POOL |
                                MDL_IO_SPACE)) == 0);

done:
    return Mdl;
}
Esempio n. 2
0
DECLHIDDEN(int) rtR0MemObjNativeAllocLow(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, bool fExecutable)
{
    AssertMsgReturn(cb <= _1G, ("%#x\n", cb), VERR_OUT_OF_RANGE); /* for safe size_t -> ULONG */

    /*
     * Try see if we get lucky first...
     * (We could probably just assume we're lucky on NT4.)
     */
    int rc = rtR0MemObjNativeAllocPage(ppMem, cb, fExecutable);
    if (RT_SUCCESS(rc))
    {
        size_t iPage = cb >> PAGE_SHIFT;
        while (iPage-- > 0)
            if (rtR0MemObjNativeGetPagePhysAddr(*ppMem, iPage) >= _4G)
            {
                rc = VERR_NO_LOW_MEMORY;
                break;
            }
        if (RT_SUCCESS(rc))
            return rc;

        /* The following ASSUMES that rtR0MemObjNativeAllocPage returns a completed object. */
        RTR0MemObjFree(*ppMem, false);
        *ppMem = NULL;
    }

#ifndef IPRT_TARGET_NT4
    /*
     * Use MmAllocatePagesForMdl to specify the range of physical addresses we wish to use.
     */
    PHYSICAL_ADDRESS Zero;
    Zero.QuadPart = 0;
    PHYSICAL_ADDRESS HighAddr;
    HighAddr.QuadPart = _4G - 1;
    PMDL pMdl = MmAllocatePagesForMdl(Zero, HighAddr, Zero, cb);
    if (pMdl)
    {
        if (MmGetMdlByteCount(pMdl) >= cb)
        {
            __try
            {
                void *pv = MmMapLockedPagesSpecifyCache(pMdl, KernelMode, MmCached, NULL /* no base address */,
                                                        FALSE /* no bug check on failure */, NormalPagePriority);
                if (pv)
                {
                    PRTR0MEMOBJNT pMemNt = (PRTR0MEMOBJNT)rtR0MemObjNew(sizeof(*pMemNt), RTR0MEMOBJTYPE_LOW, pv, cb);
                    if (pMemNt)
                    {
                        pMemNt->fAllocatedPagesForMdl = true;
                        pMemNt->cMdls = 1;
                        pMemNt->apMdls[0] = pMdl;
                        *ppMem = &pMemNt->Core;
                        return VINF_SUCCESS;
                    }
                    MmUnmapLockedPages(pv, pMdl);
                }
            }
            __except(EXCEPTION_EXECUTE_HANDLER)
            {
                NTSTATUS rcNt = GetExceptionCode();
                Log(("rtR0MemObjNativeAllocLow: Exception Code %#x\n", rcNt));
                /* nothing */
            }
        }
        MmFreePagesFromMdl(pMdl);
        ExFreePool(pMdl);
    }
Esempio n. 3
0
/// <summary>
/// System worker thread that performs actual mapping
/// </summary>
/// <param name="pArg">Path to the driver - PUNICODE_STRING type</param>
/// <returns>Status code</returns>
NTSTATUS BBMapWorker( IN PVOID pArg )
{
    NTSTATUS status = STATUS_SUCCESS;
    HANDLE hFile = NULL;
    PUNICODE_STRING pPath = (PUNICODE_STRING)pArg;
    OBJECT_ATTRIBUTES obAttr = { 0 };
    IO_STATUS_BLOCK statusBlock = { 0 };
    PVOID fileData = NULL;
    PIMAGE_NT_HEADERS pNTHeader = NULL;
    PVOID imageSection = NULL;
    PMDL pMDL = NULL;
    FILE_STANDARD_INFORMATION fileInfo = { 0 };

    InitializeObjectAttributes( &obAttr, pPath, OBJ_KERNEL_HANDLE, NULL, NULL );

    // Open driver file
    status = ZwCreateFile( 
        &hFile, FILE_READ_DATA | SYNCHRONIZE, &obAttr, 
        &statusBlock, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, 
        FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0
        );

    if (!NT_SUCCESS( status ))
    {
        DPRINT( "BlackBone: %s: Failed to open '%wZ'. Status: 0x%X\n", __FUNCTION__, pPath, status );
        return status;
    }

    // Allocate memory for file contents
    status = ZwQueryInformationFile( hFile, &statusBlock, &fileInfo, sizeof( fileInfo ), FileStandardInformation );
    if (NT_SUCCESS( status ))
        fileData = ExAllocatePoolWithTag( PagedPool, fileInfo.EndOfFile.QuadPart, BB_POOL_TAG );
    else
        DPRINT( "BlackBone: %s: Failed to get '%wZ' size. Status: 0x%X\n", __FUNCTION__, pPath, status );

    // Get file contents
    status = ZwReadFile( hFile, NULL, NULL, NULL, &statusBlock, fileData, fileInfo.EndOfFile.LowPart, NULL, NULL );
    if (NT_SUCCESS( status ))
    {
        pNTHeader = RtlImageNtHeader( fileData );
        if (!pNTHeader)
        {
            DPRINT( "BlackBone: %s: Failed to obtaint NT Header for '%wZ'\n", __FUNCTION__, pPath );
            status = STATUS_INVALID_IMAGE_FORMAT;
        }
    }
    else
        DPRINT( "BlackBone: %s: Failed to read '%wZ'. Status: 0x%X\n", __FUNCTION__, pPath, status );

    ZwClose( hFile );

    __try
    {
        if (NT_SUCCESS( status ))
        {
            //
            // Allocate memory from System PTEs
            //
            PHYSICAL_ADDRESS start = { 0 }, end = { 0 };
            end.QuadPart = MAXULONG64;

            pMDL = MmAllocatePagesForMdl( start, end, start, pNTHeader->OptionalHeader.SizeOfImage );
            imageSection = MmGetSystemAddressForMdlSafe( pMDL, NormalPagePriority );

            if (NT_SUCCESS( status ) && imageSection)
            {
                // Copy header
                RtlCopyMemory( imageSection, fileData, pNTHeader->OptionalHeader.SizeOfHeaders );

                // Copy sections
                for (PIMAGE_SECTION_HEADER pSection = (PIMAGE_SECTION_HEADER)(pNTHeader + 1);
                      pSection < (PIMAGE_SECTION_HEADER)(pNTHeader + 1) + pNTHeader->FileHeader.NumberOfSections;
                      pSection++)
                {
                    RtlCopyMemory( 
                        (PUCHAR)imageSection + pSection->VirtualAddress,
                        (PUCHAR)fileData + pSection->PointerToRawData,
                        pSection->SizeOfRawData
                        );
                }

                // Relocate image
                status = LdrRelocateImage( imageSection, STATUS_SUCCESS, STATUS_CONFLICTING_ADDRESSES, STATUS_INVALID_IMAGE_FORMAT );
                if (!NT_SUCCESS( status ))
                    DPRINT( "BlackBone: %s: Failed to relocate image '%wZ'. Status: 0x%X\n", __FUNCTION__, pPath, status );

                // Fill IAT
                if (NT_SUCCESS( status ))
                    status = BBResolveImageRefs( imageSection, TRUE, NULL, FALSE, NULL, 0 );
            }
            else
            {
                DPRINT( "BlackBone: %s: Failed to allocate memory for image '%wZ'\n", __FUNCTION__, pPath );
                status = STATUS_MEMORY_NOT_ALLOCATED;
            }
        }

        // Call entrypoint
        if (NT_SUCCESS( status ) && pNTHeader->OptionalHeader.AddressOfEntryPoint)
        {
            PDRIVER_INITIALIZE pEntryPoint = (PDRIVER_INITIALIZE)((ULONG_PTR)imageSection + pNTHeader->OptionalHeader.AddressOfEntryPoint);
            pEntryPoint( NULL, NULL );
        }

        // Wipe header
        if (NT_SUCCESS( status ) && imageSection)
            RtlZeroMemory( imageSection, pNTHeader->OptionalHeader.SizeOfHeaders );
    }
    __except (EXCEPTION_EXECUTE_HANDLER)
    {
        DPRINT( "BlackBone: %s: Exception: 0x%X \n", __FUNCTION__, GetExceptionCode() );
    }

    // Erase info about allocated region
    if (pMDL)
    {
        // Free image memory in case of failure
        if(!NT_SUCCESS( status ))
            MmFreePagesFromMdl( pMDL );

        ExFreePool( pMDL );
    }

    if (fileData)
        ExFreePoolWithTag( fileData, BB_POOL_TAG );

    if (NT_SUCCESS( status ))
        DPRINT( "BlackBone: %s: Successfully mapped '%wZ' at 0x%p\n", __FUNCTION__, pPath, imageSection );

    return status;
}
VOID
BalloonFill(
    IN WDFOBJECT WdfDevice,
    IN size_t num)
{
    PMDL                pPageMdl;
    PHYSICAL_ADDRESS    LowAddress;
    PHYSICAL_ADDRESS    HighAddress;
    PPAGE_LIST_ENTRY    pNewPageListEntry;
    PDEVICE_CONTEXT     devCtx = GetDeviceContext(WdfDevice);
    ULONG               pages_per_request = PAGE_SIZE/sizeof(PFN_NUMBER);

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_HW_ACCESS, "--> %s\n", __FUNCTION__);

    LowAddress.QuadPart = 0;
    HighAddress.QuadPart = (ULONGLONG)-1;

    num = min(num, pages_per_request);
    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_HW_ACCESS, "--> BalloonFill num = %d\n", num);

    for (devCtx->num_pfns = 0; devCtx->num_pfns < num; devCtx->num_pfns++)
    {
        if(IsLowMemory(WdfDevice))
        {
           TraceEvents(TRACE_LEVEL_WARNING, DBG_HW_ACCESS,
                "LowMemoryCondition event was set to signaled,allocations stops, BalPageCount=%d\n", devCtx->num_pages);
           break;
        }
        pPageMdl = MmAllocatePagesForMdl(
                                        LowAddress,
                                        HighAddress,
                                        LowAddress,
                                        PAGE_SIZE
                                        );
        if (pPageMdl == NULL)
        {
            TraceEvents(TRACE_LEVEL_WARNING, DBG_HW_ACCESS,
                 "Balloon MDL Page Allocation Failed!!!, BalPageCount=%d\n", devCtx->num_pages);
            break;
        }

        if (MmGetMdlByteCount(pPageMdl) != PAGE_SIZE)
        {
            TraceEvents(TRACE_LEVEL_WARNING, DBG_HW_ACCESS,
                 "Balloon MDL Page Allocation < PAGE_SIZE =%d, Failed!!!, BalPageCount=%d\n",MmGetMdlByteCount(pPageMdl), devCtx->num_pages);
            MmFreePagesFromMdl(pPageMdl);
            ExFreePool(pPageMdl);
            break;
        }

        pNewPageListEntry = (PPAGE_LIST_ENTRY)ExAllocateFromNPagedLookasideList(&devCtx->LookAsideList);
        if (pNewPageListEntry == NULL)
        {
            TraceEvents(TRACE_LEVEL_ERROR, DBG_HW_ACCESS, "List Entry Allocation Failed!!!\n");
            MmFreePagesFromMdl(pPageMdl);
            ExFreePool(pPageMdl);
            break;
        }

        pNewPageListEntry->PageMdl = pPageMdl;
        pNewPageListEntry->PagePfn = devCtx->pfns_table[devCtx->num_pfns] = *MmGetMdlPfnArray(pPageMdl);

        PushEntryList(&devCtx->PageListHead, &(pNewPageListEntry->SingleListEntry));
        devCtx->num_pages++;
    }

    if (devCtx->num_pfns > 0)
    {
        BalloonTellHost(WdfDevice, devCtx->InfVirtQueue);
    }
}
VOID
BalloonFill(
    IN WDFOBJECT WdfDevice,
    IN size_t num)
{
    PDEVICE_CONTEXT ctx = GetDeviceContext(WdfDevice);
    PHYSICAL_ADDRESS LowAddress;
    PHYSICAL_ADDRESS HighAddress;
    PHYSICAL_ADDRESS SkipBytes;
    PPAGE_LIST_ENTRY pNewPageListEntry;
    PMDL pPageMdl;

    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_HW_ACCESS, "--> %s\n", __FUNCTION__);

    ctx->num_pfns = 0;

    if (IsLowMemory(WdfDevice))
    {
        TraceEvents(TRACE_LEVEL_WARNING, DBG_HW_ACCESS,
            "Low memory. Allocated pages: %d\n", ctx->num_pages);
        return;
    }

    num = min(num, PAGE_SIZE / sizeof(PFN_NUMBER));
    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_HW_ACCESS,
        "Inflate balloon with %d pages.\n", num);

    LowAddress.QuadPart = 0;
    HighAddress.QuadPart = (ULONGLONG)-1;
    SkipBytes.QuadPart = 0;

#if (NTDDI_VERSION < NTDDI_WS03SP1)
    pPageMdl = MmAllocatePagesForMdl(LowAddress, HighAddress, SkipBytes,
        num * PAGE_SIZE);
#else
    pPageMdl = MmAllocatePagesForMdlEx(LowAddress, HighAddress, SkipBytes,
        num * PAGE_SIZE, MmNonCached, MM_DONT_ZERO_ALLOCATION);
#endif

    if (pPageMdl == NULL)
    {
        TraceEvents(TRACE_LEVEL_WARNING, DBG_HW_ACCESS,
            "Failed to allocate pages.\n");
        return;
    }

    if (MmGetMdlByteCount(pPageMdl) != (num * PAGE_SIZE))
    {
        TraceEvents(TRACE_LEVEL_WARNING, DBG_HW_ACCESS,
            "Not all requested memory was allocated (%d/%d).\n",
            MmGetMdlByteCount(pPageMdl), num * PAGE_SIZE);
        MmFreePagesFromMdl(pPageMdl);
        ExFreePool(pPageMdl);
        return;
    }

    pNewPageListEntry = (PPAGE_LIST_ENTRY)ExAllocateFromNPagedLookasideList(
        &ctx->LookAsideList);

    if (pNewPageListEntry == NULL)
    {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_HW_ACCESS,
            "Failed to allocate list entry.\n");
        MmFreePagesFromMdl(pPageMdl);
        ExFreePool(pPageMdl);
        return;
    }

    pNewPageListEntry->PageMdl = pPageMdl;
    PushEntryList(&ctx->PageListHead, &(pNewPageListEntry->SingleListEntry));

    ctx->num_pfns = num;
    ctx->num_pages += ctx->num_pfns;

    RtlCopyMemory(ctx->pfns_table, MmGetMdlPfnArray(pPageMdl),
        ctx->num_pfns * sizeof(PFN_NUMBER));

    BalloonTellHost(WdfDevice, ctx->InfVirtQueue);

    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_HW_ACCESS, "<-- %s\n", __FUNCTION__);
}
Esempio n. 6
0
NTSTATUS
AWEAllocSetSize(IN POBJECT_CONTEXT Context,
IN OUT PIO_STATUS_BLOCK IoStatus,
IN PLARGE_INTEGER EndOfFile)
{
    PAGED_CODE();

    KdPrint(("AWEAlloc: Setting size to %u MB.\n",
	(ULONG)(EndOfFile->QuadPart >> 20)));

    if (EndOfFile->QuadPart == 0)
    {
	Context->VirtualSize = EndOfFile->QuadPart;
	IoStatus->Status = STATUS_SUCCESS;
	IoStatus->Information = 0;
	return STATUS_SUCCESS;
    }

    for (;;)
    {
	PBLOCK_DESCRIPTOR block;
	SIZE_T bytes_to_allocate;

	if (Context->TotalSize >= EndOfFile->QuadPart)
	{
	    Context->VirtualSize = EndOfFile->QuadPart;
	    IoStatus->Status = STATUS_SUCCESS;
	    IoStatus->Information = 0;
	    return STATUS_SUCCESS;
	}

	block = ExAllocatePoolWithTag(NonPagedPool,
	    sizeof(BLOCK_DESCRIPTOR), POOL_TAG);

	if (block == NULL)
	{
	    IoStatus->Status = STATUS_NO_MEMORY;
	    IoStatus->Information = 0;
	    return STATUS_NO_MEMORY;
	}

	RtlZeroMemory(block, sizeof(BLOCK_DESCRIPTOR));

	if ((EndOfFile->QuadPart - Context->TotalSize) > MAX_BLOCK_SIZE)
	    bytes_to_allocate = MAX_BLOCK_SIZE;
	else
	    bytes_to_allocate = (SIZE_T)
	    AWEAllocGetRequiredPagesForSize(EndOfFile->QuadPart -
	    Context->TotalSize);

	KdPrint(("AWEAlloc: Allocating %u MB.\n",
	    (ULONG)(bytes_to_allocate >> 20)));

#ifndef _WIN64

	// On 32-bit, first try to allocate as high as possible
	KdPrint(("AWEAlloc: Allocating above 8 GB.\n"));

	block->Mdl = MmAllocatePagesForMdl(physical_address_8GB,
	    physical_address_max64,
	    physical_address_zero,
	    bytes_to_allocate);

	if (AWEAllocAddBlock(Context, block))
	    continue;

	KdPrint(("AWEAlloc: Not enough memory available above 8 GB.\n"
	    "AWEAlloc: Allocating above 6 GB.\n"));

	AWEAllocLogError(AWEAllocDriverObject,
	    0,
	    0,
	    NULL,
	    0,
	    1000,
	    AWEALLOC_STATUS_ALLOCATION_LOW_MEMORY,
	    101,
	    STATUS_INSUFFICIENT_RESOURCES,
	    0,
	    0,
	    NULL,
	    L"Error allocating above 8 GB.");

	block->Mdl = MmAllocatePagesForMdl(physical_address_6GB,
	    physical_address_max64,
	    physical_address_zero,
	    bytes_to_allocate);

	if (AWEAllocAddBlock(Context, block))
	    continue;

	KdPrint(("AWEAlloc: Not enough memory available above 6 GB.\n"
	    "AWEAlloc: Allocating above 5 GB.\n"));

	AWEAllocLogError(AWEAllocDriverObject,
	    0,
	    0,
	    NULL,
	    0,
	    1000,
	    AWEALLOC_STATUS_ALLOCATION_LOW_MEMORY,
	    101,
	    STATUS_INSUFFICIENT_RESOURCES,
	    0,
	    0,
	    NULL,
	    L"Error allocating above 6 GB.");

	block->Mdl = MmAllocatePagesForMdl(physical_address_5GB,
	    physical_address_max64,
	    physical_address_zero,
	    bytes_to_allocate);

	if (AWEAllocAddBlock(Context, block))
	    continue;

	KdPrint(("AWEAlloc: Not enough memory available above 5 GB.\n"
	    "AWEAlloc: Allocating above 4 GB.\n"));

	AWEAllocLogError(AWEAllocDriverObject,
	    0,
	    0,
	    NULL,
	    0,
	    1000,
	    AWEALLOC_STATUS_ALLOCATION_LOW_MEMORY,
	    101,
	    STATUS_INSUFFICIENT_RESOURCES,
	    0,
	    0,
	    NULL,
	    L"Error allocating above 5 GB.");

	block->Mdl = MmAllocatePagesForMdl(physical_address_4GB,
	    physical_address_max64,
	    physical_address_zero,
	    bytes_to_allocate);

	if (AWEAllocAddBlock(Context, block))
	    continue;

	KdPrint(("AWEAlloc: Not enough memory available above 4 GB.\n"
	    "AWEAlloc: Allocating at any available location.\n"));

	AWEAllocLogError(AWEAllocDriverObject,
	    0,
	    0,
	    NULL,
	    0,
	    1000,
	    AWEALLOC_STATUS_ALLOCATION_LOW_MEMORY,
	    101,
	    STATUS_INSUFFICIENT_RESOURCES,
	    0,
	    0,
	    NULL,
	    L"Error allocating above 4 GB.");

#endif // !_WIN64

	block->Mdl = MmAllocatePagesForMdl(physical_address_zero,
	    physical_address_max64,
	    physical_address_zero,
	    bytes_to_allocate);

	if (AWEAllocAddBlock(Context, block))
	    continue;

	KdPrint(("AWEAlloc: MmAllocatePagesForMdl failed.\n"));

	AWEAllocLogError(AWEAllocDriverObject,
	    0,
	    0,
	    NULL,
	    0,
	    1000,
	    STATUS_NO_MEMORY,
	    101,
	    STATUS_NO_MEMORY,
	    0,
	    0,
	    NULL,
	    L"Error allocating physical memory.");

	ExFreePoolWithTag(block, POOL_TAG);
	
	IoStatus->Status = STATUS_NO_MEMORY;
	IoStatus->Information = 0;
	return STATUS_NO_MEMORY;
    }
}