5

I tried to allocate some memory pages with read only access using mmap function. I printed /proc/self/maps to check if the memory protection was working. It showed like this even though the protection argument of mmap was PROT_READ

 7fec0c585000-7fec0c785000 r-xp 00000000 00:00 0 

This means that when I ask the kernel to allocate some read only memory pages it mark them as executable too.

I did some other test and I realized that when I ask for a write only pages,PROT_WRITE without PROT_READ, the output of maps file is like this:

7fec0c585000-7fec0c785000 -w-p 00000000 00:00 0 

This means in addition with the previous example that PROT_READ is equivalent to PROT_EXEC

Calling mmap with both PROT_WRITE|PROT_READ, enables execution too.

I wonder if there is a way to map a read only, no executable memory page; or one that is read write and no executable?


Information of the computer where the test were run:

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

  2. Intel Core i5-2310, x86_64

2 Answers 2

11

After doing some research I realized that Linux only activates memory protection when a GNU_STACK program header is included in the ELF program headers. By memory protection I mean the use of the NX bit of the processor, so memory pages can be marked as not executable.

For what I understand, GNU_STACK program header is designed to tell the kernel that you want some specific properties for the stack, one those properties is a non-executable stack. It appears that if you don't explicitly ask for a non-executable stack, all the ELF sections marked as readable will be executable too. And also all the memory mapping with mmap while have the same behavior.

Sadly there is no enough documentation on what GNU_STACK does, and the documentation of mmap doesn't specify its connection with GNU_STACK to enable execute protection.

References:

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

Sign up to request clarification or add additional context in comments.

1 Comment

Doing some more digging, this is because of READ_IMPLIES_EXEC flag on the personality. You can change this without the GNU_STACK header by getting the persona (passing -1 to sys_personality), then masking out the flag (persona & ~0x0400000) whose value can be found in sys/personality.h, then resetting the persona.
0

I test this issue in my Debian Jessie.

I mmap an anonymous area in a special address,and print the content of maps, the corresponding permission form:

PROT_READ r--p PROT_WRITE -w-p PROT_EXEC --xp PROT_READ|PROT_WRITE rw-p PROT_READ|PROT_EXEC r-xp 

I don't test PROT_WRITE | PROT_EXEC ..., because pax/grsecurity protects against creating writable and executable mapping.

test information:
Linux 3.16.0-4-amd64 #1 SMP Debian 3.16.7-ckt17-1 (2015-09-26) x86_64 GNU/Linux
Intel i7,x86_64

3 Comments

Check the section header of you elf file. There must be a GNU_STACK section
GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 RW 10 you're right!
I have found the trick : GUN_STACK(RW/RWX) -> load_elf_binary verify this permission -> process personality(READ_IMPLIES_EXEC) -> If this bit is set then PROT_READ will also add the PROT_EXEC bit -> So you can know the answer.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.