为什么在mmap中PROT_READ等于PROT_EXEC

fel*_*ght 3 linux mmap memory-mapping

我试图使用mmap函数分配一些具有只读访问权限的内存页面。我打印/proc/self/maps以检查内存保护是否正常工作。即使的保护论据mmap是PROT_READ

 7fec0c585000-7fec0c785000 r-xp 00000000 00:00 0
Run Code Online (Sandbox Code Playgroud)

这意味着当我要求内核分配一些只读内存页面时,也会将它们也标记为可执行。

我做了一些其他的测试,我意识到当我要求一个只写页面,PROT_WRITE 而没有时PROT_READ,maps文件的输出是这样的:

7fec0c585000-7fec0c785000 -w-p 00000000 00:00 0 
Run Code Online (Sandbox Code Playgroud)

这意味着除了前面的示例外,PROT_READ等效于PROT_EXEC

同时调用mmap,也PROT_WRITE|PROT_READ可以执行。

我想知道是否有一种方法可以映射只读的无可执行内存的页面;还是一个读写但没有可执行文件的文件?


运行测试的计算机的信息:

  1. Linux Arch 4.1.6-1-ARCH#1 SMP PREEMPT Mon Aug 17 08:52:28 CEST 2015 x86_64 GNU / Linux

  2. 英特尔酷睿i5-2310,x86_64

fel*_*ght 6

经过研究后,我意识到Linux仅在GNU_STACK程序头中包含程序头时才激活内存保护ELF。内存保护是指使用处理器的NX位,因此可以将内存页标记为不可执行。

据我了解,GNU_STACK程序标头旨在告诉内核您需要堆栈的某些特定属性,这些属性之一是不可执行的堆栈。看来,如果您没有明确要求不可执行的堆栈,则ELF标记为可读的所有部分也将是可执行的。并且所有与mmapwhile 的内存映射都具有相同的行为。

遗憾的是,没有足够的文档来说明GNU_STACK执行什么操作,并且的文档mmap未指定GNU_STACK用于执行保护的连接。

参考文献:

https://wiki.gentoo.org/wiki/Hardened/GNU_stack_quickstart

  • 多进行一些挖掘,这是因为个性上的READ_IMPLIES_EXEC标志。您可以通过获取角色(将-1传递给sys_personality),然后屏蔽掉可以在sys / personality.h中找到其值的标志(角色&〜0x0400000),然后重设角色,来在不使用GNU_STACK标头的情况下进行更改。 (2认同)