gpt4 book ai didi

linux - 为什么 linux 内核将我的 RW 段映射为 RWX?

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:26:54 26 4
gpt4 key购买 nike

我有一个非常简单的 ELF 可执行文件:

$ readelf -l ./plt.out

Elf file type is EXEC (Executable file)
Entry point 0x400338
There are 7 program headers, starting at offset 64

Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
PHDR 0x0000000000000040 0x00000000003ff040 0x00000000003ff040
0x0000000000000188 0x0000000000000188 R E 8
LOAD 0x0000000000000000 0x00000000003ff000 0x00000000003ff000
0x0000000000001000 0x0000000000001000 RW 1000
INTERP 0x00000000000001c8 0x00000000003ff1c8 0x00000000003ff1c8
0x0000000000000032 0x0000000000000032 R 1
[Requesting program interpreter: /data/keno/new_glibc/usr/lib/ld-linux-x86-64.so.2]
LOAD 0x0000000000001000 0x0000000000400000 0x0000000000400000
0x00000000000003b0 0x00000000000003b0 R E 1000
LOAD 0x0000000000001ea0 0x0000000000600ea0 0x0000000000600ea0
0x0000000000000180 0x0000000000000180 RW 1000
DYNAMIC 0x0000000000001ea0 0x0000000000600ea0 0x0000000000600ea0
0x0000000000000150 0x0000000000000150 RW 8
GNU_RELRO 0x0000000000001ea0 0x0000000000600ea0 0x0000000000600ea0
0x0000000000000160 0x0000000000000160 R 1

现在,根据我对 ELF 工作原理的理解,我希望分为三个部分:

  • 来自 0x3ff000-0x400000 的一个 RW
  • 来自 0x400000-0x401000 的一个 RX
  • 来自 0x600000-0x602000 的一个 RW (0xea0+0x180 > 0x1000)

但是,当我实际查看可执行文件使用 /proc/pid/maps 运行时得到的内容时,我看到以下内容:

003ff000-00400000 rwxp 00000000 00:28 1456774                            plt.out
00400000-00401000 r-xp 00001000 00:28 1456774 plt.out
00600000-00601000 r-xp 00001000 00:28 1456774 plt.out
00601000-00602000 rwxp 00002000 00:28 1456774 plt.out

这完全不是我所期望的。这是怎么回事?

最佳答案

这里的答案有两方面,一部分由动态链接器提供,另一部分由内核提供。为了看到这一点,让我们在进入动态链接器后立即查看内存映射(例如,通过在 _dl_start 中设置断点)。我们看到:

003ff000-00400000 rwxp 00000000 00:28 1456774                            plt.out
00400000-00401000 r-xp 00001000 00:28 1456774 plt.out
00600000-00602000 rwxp 00001000 00:28 1456774 plt.out

这至少更接近我们想要的(它有正确的段,在正确的位置)。现在,最后一段被分开的原因是因为 GNU_RELRO 程序头,它对动态链接器说“嘿,在你完成初始重定位后我不再需要写这个了”,so the dynamic linker faithfully tries to set that region of memory to PROT_READ (请注意,它忽略了程序头中设置的实际权限标志,尽管它们似乎通常设置为 PF_R)。

但这只是谜团的一半。我们仍然有那些讨厌的 PROT_EXEC 位,我们没有订购。这些结果归结为 Linux 内核的一个特性,称为 READ_IMPLIES_EXEC 个性,导致所有具有 PROT_READ 权限的映射也具有 PROT_EXEC 权限(参见 man page for personality(2) )。事实证明,出于兼容性原因,linux automatically sets this personality 除非一个 PT_GNU_STACK 程序头告诉它不要。如果所有输入对象都有一个(空的).note.GNU-stack 部分,链接器会自动创建这个程序头。有关该机制的更多信息,请参阅 here

关于linux - 为什么 linux 内核将我的 RW 段映射为 RWX?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40623450/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com