Allocate at low memory address

江枫思渺然 提交于 2021-02-05 06:38:05

问题


In order to test a software in limit conditions, I'm trying to create a test case where the provided user buffer is allocated at some very low memory address. Something very close to NULL, like for example 0x1000h.

This is proving a tough condition to create. Actually, I'm unable to generate that with malloc() on Linux, BSD, Windows, or OS-X. I'm convinced this situation can happen on other types of devices, but I need a reproducible test case that can be inserted into a CI test suite.

Is there any known method with moderate complexity (and dependencies) to generate such conditions ?

Edit : Selected the solution proposed by Eric Postpischil, using mmap(). Note that, as underlined by R., it's first necessary to lower the lowest address limit, readable at /proc/sys/vm/mmap_min_addr (on Linux).

sudo sysctl -w vm.mmap_min_addr="4096"

Then the example code :

#include <stdio.h>      /* printf */
#include <sys/mman.h>   /* mmap */

int main(int argc, const char** argv)
{
    void* lowBuff = mmap((void*)(0x1000), 64<<10,
                    PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS,
                   -1, 0);
    printf("lowBuff starts at %p \n", lowBuff);
}

And the result :

lowBuff starts at 0x1000

回答1:


On a POSIX/Unix system, you can use mmap to request memory at specific page-aligned addresses. The lowest you can get will depend on your particular system and circumstances.




回答2:


You can only allocate virtual memory in C (malloc is a wrapper around VirtualAlloc on Windows as far as I know), and virtual memory is managed by your operating system, so it is pretty much impossible to predict what address you will get. It will likely never be close to 0x00 though. Unless you're writing a custom a memory allocation system, you shouldn't really have to deal with that and even then it shouldn't care about the provided address.




回答3:


On Windows, the lowest part of memory (64KB?) is reserved by the system specifically to catch accesses through invalid pointers. For example, if you try to dereference a null pointer, perhaps with an offset, you'll trigger an access violation. So 0x1000 is off the table because it's within the first 64KB.

Beyond that initial range, you can try to reserve and commit memory with VirtualAlloc, specifying a base address (the parameter is named lpAddress). The base address will be rounded down to the allocation granularity (which I think is also 64KB). If that memory is available, you're all set, but it might not be.

LPVOID desired_address = (LPVOID) 0x00010000;
LPVOID actual_address =
    VirtualAlloc(desired_address, desired_size,
                 MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
if (actual_address == NULL) {
    // we couldn't get the address we wanted.
} else if (actual_address != desired_address) {
    // something very weird happened
} else {
    // we got the low memory we wanted
}

Historically, typical 32-bit user processes has their executable code loaded starting at 0x00400000 and DLLs generally started higher (like 0x10000000), so you might get lucky shooting for something in that second block of 64KB. But address space layout randomization (ASLR) changes those defaults, and who knows what strange addresses other libraries are going to grab before you get a chance.

So you can try, but you have to be prepared for the possibility that trying to grab low memory with VirtualAlloc fails.



来源:https://stackoverflow.com/questions/48631207/allocate-at-low-memory-address

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!