LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   Dark memory hacking under Linux (https://www.linuxquestions.org/questions/programming-9/dark-memory-hacking-under-linux-792373/)

cymric 03-01-2010 11:50 AM

Dark memory hacking under Linux
 
I had this crazy idea a few days ago about some quite dark memory hackery for Linux and wanted to try it out, but I'm not sure how to proceed as it involves usage of Linux kernel functions beyond what is offered by glibc. Those are not always documented as well as one would like. I've spent many enjoyable hours learning about the memory subsystems of Linux (the book Understanding the Linux Virtual Memory Manager should come in different flavours: Scheduling, IPC, Networking, ...), but still I'm not quite sure how to tie that knowledge in with the idea I had. It's a bit tricky to explain unfortunately (and can be solved in quite a different way too), but this way gave me an excuse to dig into the system a bit more.

Keep in mind that all the questions below assume user space program code.


QUESTION 1
Can I request the kernel to allocate single memory pages for me, but in such a fashion that they form a contiguous region of memory, and if so, how?

Think of it as follows. Suppose I make a call to mmap(), requesting 10 * pagesize bytes. A new vm_area_struct in the task making this call is then created pointing at this tiny region of virtual memory as a whole. So far so good. My question is now: suppose I call mmap() 10 times, every time requesting 1 * pagesize bytes. There will then be 10 vm_area_structs, one for every single page. Can I do this—using something different than mmap(), I suppose—in such a fashion that those 10 single pages are contiguous in memory?

QUESTION 2
Memory pages come with all sorts of nifty bits to describe whether they're backed up by real memory, whether they're readable, writable, and so forth. Can I request the kernel to change those bits on an individual page-basis, and if so, how?

This ties in with question 1: using mmap(10 * pagesize) only allows me to specify a setting for that region as a whole. So the granularity isn't sufficiently fine. And if I use 10 * mmap(1 * pagesize), I might not get a contiguous series of pages...

QUESTION 3
Linux uses a 'lazy allocator' from what I understand, so requesting pages doesn't allocate the frames yet. That only happens when a program tries to access those pages. Can I force the kernel to allocate and deallocate frames for me?

I can make the kernel allocate frames by simply 'touching' every page; mmap() provides a flag which does the same thing (I think) on a much higher level (MAP_POPULATE). But that's only the allocating part. I know, deallocation doesn't make a whole lot of sense in this example (relinquish the pages and the frames go away too) but humour me, please.


Thanks for any insight you can advance.

10110111 03-02-2010 02:29 PM

Quote:

Can I request the kernel to allocate single memory pages for me, but in such a fashion that they form a contiguous region of memory
This may be very difficult since once a page has been allocated, it may be followed by another page allocated for another process, so you'll lose continuity this way. Or you mean continuity in virtual address space, not physical?

cymric 03-02-2010 04:20 PM

I mean continuity in virtual address space. Continuity in physical address space matters very little here; I'm not after constructing a DMA-capable device driver, for example.

orgcandman 03-02-2010 05:11 PM

You should be able to get a known region of memory by mmap'ing /dev/mem at a particular offset.

something like:

Code:

void *base_ptr = NULL;
int fd = open("/dev/mem", O_RDWR);
int flags = MAP_SHARED;
int max_addr = END_OF_THE_REGION;
int min_addr = BEGINNING_OF_THE_REGION;
int region_len = max_addr - min_addr + 1;
base_ptr = mmap64(base_ptr, region_len, PROT_READ|PROT_WRITE, flags, fd, min_addr);

Will map a particular physical memory region into your address space.

You also might want to look into mprotect() for setting r/w bits. Setting the nx bit might be restricted for security issues.

Hope this was helpful to what you're doing. I can't comment on whether or not something will/won't work, since you haven't given enough information.

-Aaron

cymric 03-02-2010 05:35 PM

*Duh*. I can't believe I missed the mprotect()-manpage. In combination with mmap() it solves the problem of questions 1 and 2: I can allocate things in a single mmap()-call (no need to go the route via /dev/mem then, just keep everything anonymous), then mprotect() smaller chunks as I see fit. Thanks!

That leaves question 3, but its value is more theoretical rather than practical.


All times are GMT -5. The time now is 03:20 PM.