Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GDB can't access mmap()'d kernel allocated memory?

Tags:

c++

c

gdb

mmap

I'm running into an issue with GDB and some buffers allocated in kernel space. The buffers are allocated by a kernel module that is supposed to allocate contiguous blocks of memory, and then memory mapped into userspace via a mmap() call. GDB, however, can't seem to access these blocks at any time. For example, after hitting a breakpoint in GDB:

(gdb) x /10xb 0x4567e000
0x4567e000:     Cannot access memory at address 0x4567e000

However, looking at the application's currently mapped memory regions in /proc//smaps shows:

4567e000-456d3000 rwxs 8913f000 00:0d 883        /dev/cmem
Size:                340 kB
Rss:                 340 kB
Pss:                   0 kB
Shared_Clean:          0 kB
Shared_Dirty:          0 kB
Private_Clean:         0 kB
Private_Dirty:         0 kB
Referenced:            0 kB
Swap:                  0 kB

The reason I'm even looking into this is because at some point during the run, this buffer address (or another allocated in a similar manner) causes a SIGSEGV.

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x49aea490 (LWP 652)]
0x402e4ea8 in fwrite () from /lib/libc.so.6
(gdb)
(gdb)
(gdb) where
#0  0x402e4ea8 in fwrite () from /lib/libc.so.6
#1  0x000eb394 in EncryptedWriter::Write (this=0x198600, buffRaw=0x4567e000 <Address     0x4567e000 out of bounds>, iLenRaw=719) at encrypted_writer.cpp:397
#2  0x0006b0f4 in EncryptionWrapper::Write (this=0x3ab2698, buffer=0x4567e000, size=719) at encryption.cpp:54

This segfault occurs despite the fact that the buffer had been used heavily up until the crash, and the /proc//smaps file still shows this buffer to be mapped as above.

I am completely at a loss as to why this might be happening, and why the mapping seems valid in /proc but never in GDB.

like image 729
Ryan Talbot Avatar asked Sep 03 '10 22:09

Ryan Talbot


2 Answers

About why gdb cannot access the memory you want, I believe Linux does not make I/O memory accessible via ptrace().

According to cmemk.c (which I found in linuxutils_2_25.tar.gz), mmap() does indeed set the VM_IO flag on the memory in question.

To access this memory from gdb, add a function to your program that reads this memory and have gdb call this function.

like image 157
sigjuice Avatar answered Oct 30 '22 16:10

sigjuice


See examining-mmaped-addresses-using-gdb discussion in another thread and especially the answer here. You should be able to add a custom vm_operations_struct to your VMA in the module's mmap implementation.

Also see mm/memory.c in the Linux kernel. When get_user_pages() fails the code will try to call the custom vma->vm_ops->access implementation in your driver to access the memory.

like image 24
lipnitsk Avatar answered Oct 30 '22 18:10

lipnitsk