【问题标题】:Code (.text) not execute-only? .rodata is executable?代码(.text)不是只执行的? .rodata 是可执行的吗?
【发布时间】:2016-09-15 15:55:09
【问题描述】:

我试图了解 ELF 段是如何进行内存映射的。我注意到各个部分都映射到同一个 ELF 段。例如,.rodata 映射到与 .text 相同的段。

为什么会这样?为什么不将 .rodata 映射到单独的只读且不可执行的段?

另外,将 .text 部分映射到“仅执行”段(不可读)需要什么?是否有任何内核/硬件限制可能会阻碍这一点?

编辑: 如果有什么不同的话,我不妨补充一下,我正在使用 GNU 链接器。

【问题讨论】:

  • 在许多硬件架构上不可能拥有 XOM。例如,在 x86 上,执行权限意味着读取权限。
  • 您有任何支持该主张的参考资料吗? 386 和转发设置的权限不是由内核页面处理程序分页设置的吗?
  • 它们是,但这些位不允许您设置组合执行-noread。 Look here at the page directory;有一个位表示用户区可以访问它,还有一个 R/W 位表示用户区可以对其进行写入,但是如果您阅读说明,它会说 0=RO,1=RW。仅执行内存功能实际上是首先在具有 MPK(内存保护密钥)功能的 Skylake-Server CPU 中出现的东西。对此的支持刚刚登陆Linux 4.6(参见第 1.3 节)。
  • 我明白了。 GDT (wiki.osdev.org/Global_Descriptor_Table) 中的保护标志呢?为什么不能使用这些来启用只执行代码?是否与内核安装平面重叠的 USER_CS 和 USER_DS 有关?这些标志与页表标志有什么关系?
  • 正确;现在的 CS 和 DS 表示基于 0 的平坦地址空间。这使程序员和优化编译器的工作比 86 年代早期的分段地址空间更容易,这就是为什么现在的内核不妨碍分段,启用分页并且只使用页位作为他们的访问控制。分段是一种现在已经过时的黑客来获取更多内存(8086 需要允许它通过其 16 位地址触及 1MB),而分页是将虚拟内存的页面换入/换出物理帧的机制的物理内存。对此进行了访问控制。

标签: linux-kernel elf


【解决方案1】:

section和segment是两个不同的概念,程序加载使用segment,甚至可以剥离section表。一个段可以包含多个部分。 .rodata 和 .text 都是只读的。所以它们可以放在同一段。

【讨论】:

    【解决方案2】:

    收集自上面的 cmets

    在包括 x86-64 在内的多种计算机体系结构上,无法将内存标记为可执行但不可读。

    虽然 16 位和 32 位 x86 确实允许在传统模式下进行分段,并且内存段理论上可以用于将内存标记为仅可执行文件,但平面地址空间的好处是如此之大,以至于 x86-64 现在 @ 987654321@:

    3.2.4 IA-32e 模式下的分割

    在 Intel 64 架构的 IA-32e 模式下,分段的效果取决于处理器是在兼​​容模式还是 64 位模式下运行。在兼容模式下,分段功能与使用旧的 16 位或 32 位保护模式语义一样。

    在 64 位模式下,通常(但不完全)禁用分段,创建一个平坦的 64 位线性地址空间。处理器将 CS、DS、ES、SS 的段基数视为零,创建一个等于有效地址的线性地址。 FS 和 GS 段是例外。这些段寄存器(保存段基址)可用作线性地址计算中的附加基址寄存器。它们有助于处理本地数据和某些操作系统数据结构。

    请注意,在 64 位模式下,处理器不会在运行时执行段限制检查。

    因此,内核只需将它们的段设置为覆盖整个地址空间,而不依赖于分段来实现内存保护。

    他们使用的是页表的属性。存在于进程内存映射中的每个页面都有一个页表条目来管理对它的访问。可以看到它们的格式概述here,但最关键的是有两个位控制允许的访问类型:

    • Bit 1 (R/W):0 表示只读,1 表示可读写。
    • 位 63 (XD):0 表示可执行,1 表示不可执行。

    不可能用这些标志指示可执行-不读取-不写入组合。如果该页面完全存在于内存映射中,则它必须是可读的。

    英特尔最新微架构 Skylake 中的解决方案正在快速接近,允许只执行内存:它是经过洗礼的 MPK (memory protection keys) 功能,在 Linux 内核 4.6 中得到了支持刚刚发布。键占用页表条目的 62:59 四个位,内存区域可以用表示执行-不读-不写访问的键标记。

    【讨论】:

      【解决方案3】:
      % objdump -h /bin/ls
      
      /bin/ls:     file format elf64-x86-64
      
      Sections:     
      Idx Name          Size      VMA               LMA               File off  Algn
        0 .interp       0000001c  0000000000400238  0000000000400238  00000238  2**0
                        CONTENTS, ALLOC, LOAD, READONLY, DATA
        1 .note.ABI-tag 00000020  0000000000400254  0000000000400254  00000254  2**2
                        CONTENTS, ALLOC, LOAD, READONLY, DATA
        2 .note.gnu.build-id 00000024  0000000000400274  0000000000400274  00000274  2**2
                        CONTENTS, ALLOC, LOAD, READONLY, DATA
        3 .gnu.hash     000000c0  0000000000400298  0000000000400298  00000298  2**3
                        CONTENTS, ALLOC, LOAD, READONLY, DATA
        4 .dynsym       00000cd8  0000000000400358  0000000000400358  00000358  2**3
                        CONTENTS, ALLOC, LOAD, READONLY, DATA
        5 .dynstr       000005dc  0000000000401030  0000000000401030  00001030  2**0
                        CONTENTS, ALLOC, LOAD, READONLY, DATA
        6 .gnu.version  00000112  000000000040160c  000000000040160c  0000160c  2**1
                        CONTENTS, ALLOC, LOAD, READONLY, DATA
        7 .gnu.version_r 00000070  0000000000401720  0000000000401720  00001720  2**3
                        CONTENTS, ALLOC, LOAD, READONLY, DATA
        8 .rela.dyn     000000a8  0000000000401790  0000000000401790  00001790  2**3
                        CONTENTS, ALLOC, LOAD, READONLY, DATA
        9 .rela.plt     00000a98  0000000000401838  0000000000401838  00001838  2**3
                        CONTENTS, ALLOC, LOAD, READONLY, DATA
       10 .init         0000001a  00000000004022d0  00000000004022d0  000022d0  2**2
                        CONTENTS, ALLOC, LOAD, READONLY, CODE
       11 .plt          00000720  00000000004022f0  00000000004022f0  000022f0  2**4
                        CONTENTS, ALLOC, LOAD, READONLY, CODE
       12 .text         0001112a  0000000000402a10  0000000000402a10  00002a10  2**4
                        CONTENTS, ALLOC, LOAD, READONLY, CODE
       13 .fini         00000009  0000000000413b3c  0000000000413b3c  00013b3c  2**2
                        CONTENTS, ALLOC, LOAD, READONLY, CODE
       14 .rodata       00006754  0000000000413b80  0000000000413b80  00013b80  2**6
                        CONTENTS, ALLOC, LOAD, READONLY, DATA
       15 .eh_frame_hdr 0000081c  000000000041a2d4  000000000041a2d4  0001a2d4  2**2
                        CONTENTS, ALLOC, LOAD, READONLY, DATA
       16 .eh_frame     00002c7c  000000000041aaf0  000000000041aaf0  0001aaf0  2**3
                        CONTENTS, ALLOC, LOAD, READONLY, DATA
       17 .init_array   00000008  000000000061de00  000000000061de00  0001de00  2**3
                        CONTENTS, ALLOC, LOAD, DATA
       18 .fini_array   00000008  000000000061de08  000000000061de08  0001de08  2**3
                        CONTENTS, ALLOC, LOAD, DATA
       19 .jcr          00000008  000000000061de10  000000000061de10  0001de10  2**3
                        CONTENTS, ALLOC, LOAD, DATA
       20 .dynamic      000001e0  000000000061de18  000000000061de18  0001de18  2**3
                        CONTENTS, ALLOC, LOAD, DATA
       21 .got          00000008  000000000061dff8  000000000061dff8  0001dff8  2**3
                        CONTENTS, ALLOC, LOAD, DATA
       22 .got.plt      000003a0  000000000061e000  000000000061e000  0001e000  2**3
                        CONTENTS, ALLOC, LOAD, DATA
       23 .data         000002a0  000000000061e3c0  000000000061e3c0  0001e3c0  2**6
                        CONTENTS, ALLOC, LOAD, DATA
       24 .bss          00000e08  000000000061e680  000000000061e680  0001e660  2**6
                        ALLOC
      

      每个部分都有自己的属性,例如READONLYCONTENTSALLOCLOADDATA

      具有相同属性的部分可以映射在一起。

      根据elf format

         sh_flags  Sections support one-bit flags that describe miscellaneous
                   attributes.  If a flag bit is set in sh_flags, the
                   attribute is "on" for the section.  Otherwise, the
                   attribute is "off" or does not apply.  Undefined attributes
                   are set to zero.
      
                   SHF_WRITE      This section contains data that should be
                                  writable during process execution.
      
                   SHF_ALLOC      This section occupies memory during process
                                  execution.  Some control sections do not
                                  reside in the memory image of an object
                                  file.  This attribute is off for those
                                  sections.
      
                   SHF_EXECINSTR  This section contains executable machine
                                  instructions.
      
                   SHF_MASKPROC   All bits included in this mask are reserved
                                  for processor-specific semantics.
      

      ELFSHF_EXECINSTR 部分属性,所以是编译器或链接没有设置属性。

      【讨论】:

      • 很抱歉,您的帖子没有回答任何问题。我知道链接器将这些部分映射到段。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-28
      • 1970-01-01
      • 2017-07-11
      • 1970-01-01
      • 2017-07-31
      • 2021-03-17
      相关资源
      最近更新 更多