0

I am trying to figure out how to directly read any location in physical memory on a Power9 processor using /dev/mem. The following is the code that I have used to that end.

FILE* fp;
int _fdmem;
int *map = NULL;
const char memDevice[] = "/dev/mem";

_fdmem = open( "/dev/mem", O_RDWR | O_SYNC );

if (_fdmem < 0){
printf("Failed to open the /dev/mem !\n");
return 0;
}
else{
printf("open /dev/mem successfully !\n");
}

map= (int *)(mmap(NULL,1,PROT_READ|PROT_WRITE,MAP_PRIVATE,_fdmem,0));

fp=fopen("./memm2out.txt","w");

for (int i=0; i<131073;i++)
{
fprintf(fp, "%x",*(map+i));
}

When I run the code I get the following output.

open /dev/mem successfully !
Segmentation fault

Using GDB, this is where the segfault occurs

Program received signal SIGSEGV, Segmentation fault.
0x0000000100000a2c in main () at memmapper2.c:34
34      fprintf(fp, "%x",*(map+i));

When I use 131072 as the value for i there is no segfault, which makes me believe there is some kind of boundary to reading after 64 kB. The file is run with root permissions. The processor I'm using is running Linux kernel version 4.18. What may be restricting my access?

Edit: When the second mmap parameter is set to any value greater than 65536, mmap fails to open and gives the error message ": OPERATION NOT PERMITTED". Now, it's my understanding that what's happening here is that mmap maps the file pointer for /dev/mem to a specific location in virtual memory from which you can invoke the functionality of /dev/mem to read physical memory. Am I mistaken in this understanding?

Jerry9013
  • 1
  • 2
  • 2
    Try calling `mmap()` with a size large enough to span your (loop count) * `sizeof(int)`; initial value shown is 1 – Milag Aug 24 '20 at 16:02
  • Check the return values of `mmap` and `fopen`. One of the two is failing. Use `perror()` to print the error description. – Marco Bonelli Aug 24 '20 at 16:15
  • Can you show the contents of /proc/pid/maps after the mmap call has returned? – Mark Plotnick Aug 26 '20 at 01:19
  • @Milag Interesting enough, if I set the length parameter in mmap to be greater than 65536, then mmap fails. I used perror to check the errno like Marco Bonelli said, and the error message is ": OPERATION NOT PERMITTED". That being said, it doesn't seem that the value for *length* in the range of 1-65536 has any impact on the output, or on the location of the segfault when reading from /dev/mem. Again, this file has root permissions. – Jerry9013 Aug 28 '20 at 22:21
  • See the kernel routine `mmap_mem()`. Looks like there's some range limitations. Consider experimenting with read-only, different flags, or both. – Milag Aug 29 '20 at 00:29
  • @Milag I found a textbook Learning Linux Binary Analysis [pg 241] that says only the first MB of memory is accessible to /dev/mem. It's pretty demoralizing haha – Jerry9013 Sep 06 '20 at 01:58

0 Answers0