tags:

views:

73

answers:

1

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.

+3  A: 

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.

sigjuice
Ah, OK, I was unaware of that limitation, and cmem does indeed set VM_IO (as does the driver for /dev/mem, so that makes sense). Thank you.Any idea why GDB would declare the address out of bounds at stack frame 1 but not at stack frame 2?
Ryan Talbot
This could be the bug you are looking for. 1. Wrapper() gets a valid pointer 2. Another thread (or Wrapper(), less likely) frees this pointer 3. Wrapper() still passes this pointer to Writer() 4. Writer() passes this pointer to fwrite() 5. fwrite() uses this pointer and dies
sigjuice
Actually, the buffer address was a total red herring. Turns out another thread was closing the file pointer, so fwrite was dying because of that. The buffer itself isn't released until the process is shut down, which happens after thread teardown. Thanks for the help!
Ryan Talbot