我有一个生成 Bus error (core dumped)
消息的二进制文件 . 当我在调试器( gdb
)下运行它时,它无法访问 .bss
部分中的内存位置 .
Program received signal SIGBUS, Bus error.
0x0000000000412275 in ?? ()
这个位置的代码是:
41226f: 0f 8f 33 ff ff ff jg 4121a8
412275: 8b 35 51 b5 22 00 mov 0x22b551(%rip),%esi # 63d7cc
41227b: 85 f6 test %esi,%esi
所以它试图访问 0x63d7cc
位置的内存,这显然位于 .bss
部分: 0x63c4e0 - 0x63d7e0
.
gdb
(与/ proc / $ pid / maps一起)将此内存显示为已映射:
(gdb) info proc mappings
process 16533
Mapped address spaces:
Start Addr End Addr Size Offset objfile
0x400000 0x43a000 0x3a000 0x0 /somepath/someapp
0x639000 0x63e000 0x5000 0x39000 /somepath/someapp
0x63e000 0x65f000 0x21000 0x0 [heap]
(gdb) info files
Symbols from "/somepath/someapp".
...
0x0000000000639c80 - 0x000000000063c498 is .data
0x000000000063c4e0 - 0x000000000063d7e0 is .bss
两个ELF部分的检查:
% readelf -S someapp
...
[24] .data PROGBITS 0000000000639c80 00039c80
0000000000002818 0000000000000000 WA 0 0 32
[25] .bss NOBITS 000000000063c4e0 0003c498
0000000000001300 0000000000000000 WA 0 0 32
[26] .gnu_debuglink PROGBITS 0000000000000000 0003c498
000000000000000c 0000000000000000 0 0 1
...
和Segments将此内存显示为已映射:
% readelf -l someapp
...
LOAD 0x0000000000000000 0x0000000000400000 0x0000000000400000
0x000000000003976c 0x000000000003976c R E 200000
LOAD 0x0000000000039770 0x0000000000639770 0x0000000000639770
0x0000000000004070 0x0000000000004070 RW 200000
...
但 gdb
无法访问它(因此应用程序失败的原因) . 有趣的是 gdb
能够访问 .bss
内存,直到 0x63d000
:
(gdb) x 0x63d7cc
0x63d7cc: Cannot access memory at address 0x63d7cc
(gdb) x 0x63cff8
0x63cff8: 0x00000000
(gdb) x 0x63cffc
0x63cffc: 0x00000000
(gdb) x 0x63cffd
0x63cffd: Cannot access memory at address 0x63d000
问题是:
有什么可能阻止这种访问?
还有哪些其他方法可用于检查运行时内存访问权限?
还有什么可以修改正在运行的进程的访问权限?
1 回答
.bss
通常不是可执行的,所以很可能这就是为什么在尝试跳转到它时会得到SIGBUS
.您的
readelf
输出显示RW
标志(注意缺少E
xecutable标志) .您需要
mprotect
该部分首先添加执行权限 .请注意,某些环境(例如
SELinux
)禁止使用RWE
进行内存映射,并且将映射更改为R-E
将导致程序无法写入其(通常可写)全局数据 . 这就是为什么将可执行代码放入.bss
可能不是最好的想法 .