2

我有一个生成Bus error (core dumped)消息的二进制文件。当我在调试器 ( gdb) 下运行它时,它无法访问该.bss部分中的内存位置。

程序收到信号 SIGBUS,总线错误。
0x0000000000412275 在?? ()

这个位置的代码是:

  41226f:0f 8f 33 ff ff ff jg 4121a8
  412275: 8b 35 51 b5 22 00 移动 0x22b551(%rip),%esi # 63d7cc
  41227b: 85 f6 测试%esi,%esi

所以它试图访问0x63d7cc明显在该.bss部分内的位置的内存:0x63c4e0 - 0x63d7e0.

gdb(与 /proc/$pid/maps 一起)将此内存显示为已映射:

(gdb) info proc 映射
进程 16533
映射地址空间:

          开始地址结束地址大小偏移objfile
            0x400000 0x43a000 0x3a000 0x0 /somepath/someapp
            0x639000 0x63e000 0x5000 0x39000 /somepath/someapp
            0x63e000 0x65f000 0x21000 0x0 [堆]
(gdb) 信息文件
来自“/somepath/someapp”的符号。
...
        0x0000000000639c80 - 0x000000000063c498 是 .data
        0x000000000063c4e0 - 0x000000000063d7e0 是 .bss

ELF部分的两个检查:

% readelf -S someapp
...
  [24] .data 程序 0000000000639c80 00039c80
       0000000000002818 0000000000000000 西澳 0 0 32
  [25] .bss NOBITS 000000000063c4e0 0003c498
       0000000000001300 0000000000000000 西澳 0 0 32
  [26] .gnu_debuglink 程序 0000000000000000 0003c498
       000000000000000c 0000000000000000 0 0 1
...

和 Segments 将此内存显示为已映射:

% readelf -l 一些应用程序
...
  加载 0x00000000000000000 0x0000000000400000 0x0000000000400000
                 0x000000000003976c 0x000000000003976c RE 200000
  加载 0x0000000000039770 0x0000000000639770 0x0000000000639770
                 0x0000000000004070 0x0000000000004070 读写 200000
...

gdb无法访问它(以及应用程序失败的原因)。有趣gdb的是能够访问.bss内存直到0x63d000

(gdb) x 0x63d7cc
0x63d7cc:无法访问地址 0x63d7cc 的内存
(gdb) x 0x63cff8
0x63cff8: 0x00000000
(gdb) x 0x63cffc
0x63cffc: 0x00000000
(gdb) x 0x63cffd
0x63cffd:无法访问地址 0x63d000 处的内存

问题是:
什么会阻止这种访问?
还有哪些其他方法可以检查运行时内存访问权限?
还有什么可以修改正在运行的进程的访问权限?

4

1 回答 1

3

这个位置的代码是:

通常.bss不是可执行的,因此很可能这就是您SIGBUS尝试跳转到它的原因。

您的readelf输出也显示了RW标志(注意缺少E可执行标志)。

您需要先在mprotect该部分添加执行权限。

请注意,某些环境,例如SELinux,禁止使用 的内存映射RWE,并且将映射更改为R-E将导致程序无法写入其(通常可写的)全局数据。这就是为什么将可执行代码放入.bss其中可能不是最好的想法的原因。

于 2017-07-28T02:07:40.553 回答