Linux: 是什么阻止我们从代码段读取内存?

Linux: what prevents us from reading the memory from code segment?

我写了一个简单的代码试图找出我们是否可以读取和打印代码段中的内存:

#include <stdio.h>

void main() {
  int *code_ptr = 0x4;
  printf("code_ptr = %x\n", code_ptr);
  printf("*code_ptr = %x\n", *code_ptr);
}

我的系统是 x86_64 + Ubuntu 19.04 (Disco Dingo)。程序失败,输出如下:

code_ptr = 4
Segmentation fault (core dumped)

IIUC,在Linux中,代码段和数据段共享同一个基地址。如果那是真的,这个程序将读取代码段中的内存,我期望不会有任何崩溃,因为 0x04 应该在数据段的范围内(从开头开始)。这应该通过分页检查,因为代码段的映射内存是只读的,我们只读取这里的内存。

那么我是不是遗漏了什么或者是否有任何其他机制阻止我们阅读这篇文章%ds:0x4

我认为您的主要误解是您假设称为 "the data segment" 的 8086 硬件功能与也称为 "the data segment." 的可执行映像细分相同 Xenix 可能已经使用了它硬件功能是这样的,但现代 x86 Unix 没有。在现代 Unix 上,%ds:0 总是指向线性地址零,而不是可执行文件数据段的开头。 (同样 %cs:0 指向线性地址零,而不是可执行文件的文本段。)

所有可执行文件的段都将加载到线性地址 space 某处 远高于 线性地址 0,并且在当前一代操作系统上,加载地址将被随机化每个 运行.

没有标准方法可以获取指向可执行文件代码或数据段开头的指针。在 GNU 系统上,您可以使用 dl_iterate_phdr,其他操作系统可能在不同的名称下具有类似的功能。