In windows and linux x86 (including x86_64) world, is there any legitimate binary (i.e., a program binary generated by the typical compiling-assembling-linking flow and no manual editing on binary after it is generated) that will have RWX memory pages after being loaded? If yes, what are the use cases?
-
operating system? compiler? binary format?– julian ♦May 3, 2017 at 21:24
-
OS: linux, windows. Compiler: gcc, visual studio, binary: ELF.– drdotMay 3, 2017 at 23:40
-
ELF binaries won't be executed by a windows kernel and ELF segment permissions are denoted RWE rather than RWX– julian ♦May 3, 2017 at 23:44
-
what does it mean for a binary to be considered "legitimate"?– julian ♦May 4, 2017 at 0:42
-
@SYS_V, a program binary generated by the typical compiling-linking-assembling flow, i.e., no manual editing on binary after it is generated.– drdotMay 4, 2017 at 5:27
3 Answers
Note: this answer corresponds to the original question
Process segment permissions may vary across architectures and implementations. For example, it is expected that on more recent x86 Linux systems that GCC creates binaries with non-executable stacks. In contrast with this, it used to be the case that MIPS did not even support an non-executable stack - in other words, every MIPS binary had its stack permissions set to RWE.
MIPS floating point support requires that any instruction that cannot be directly executed by the FPU, be emulated by the kernel. Part of this emulation involves executing non-FPU instructions that fall in the delay slots of FP branch instructions. Since the beginning of MIPS/Linux time, this has been done by placing the instructions on the userspace thread stack, and executing them there, as the instructions must be executed in the MM context of the thread receiving the emulation.
Because of this, the de facto MIPS Linux userspace ABI requires that the userspace thread have an executable stack. It is de facto, because it is not written anywhere that this must be the case, but it is never the less a requirement.[1]
A kernel patch had to be developed in order to support MIPS executable stack protection:
The following series implements an executable stack protection in MIPS.
It sets up a per-thread 'VDSO' page and appropriate TLB support. Page is set write-protected from user and is maintained via kernel VA. MIPS FPU emulation is shifted to new page and stack is relieved for execute protection as is as all data pages in default setup during ELF binary initialization. The real protection is controlled by GLIBC and it can do stack protected now as it is done in other architectures and I learned today that GLIBC team is ready for this.
Note: actual execute-protection depends from HW capability, of course.
This patch is required for MIPS32/64 R2 emulation on MIPS R6 architecture.[2]
Here is a concrete example, using a MIPS ELF binary from a ZTE router:
$ file cspd
cspd: ELF 32-bit MSB executable, MIPS, MIPS-I version 1 (SYSV), dynamically linked, interpreter /lib/ld-uClibc.so.0, stripped
Note the permissions of segment GNU_STACK
:
$ readelf -l cspd
Elf file type is EXEC (Executable file)
Entry point 0x59d790
There are 8 program headers, starting at offset 52
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
PHDR 0x000034 0x00400034 0x00400034 0x00100 0x00100 R E 0x4
INTERP 0x000134 0x00400134 0x00400134 0x00014 0x00014 R 0x1
[Requesting program interpreter: /lib/ld-uClibc.so.0]
REGINFO 0x000148 0x00400148 0x00400148 0x00018 0x00018 R 0x4
LOAD 0x000000 0x00400000 0x00400000 0x1ef050 0x1ef050 R E 0x10000
LOAD 0x1ef050 0x005ff050 0x005ff050 0x148e2 0x2a070 RW 0x10000
DYNAMIC 0x000160 0x00400160 0x00400160 0x00130 0x00130 RWE 0x4
GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RWE 0x4 <---
NULL 0x000000 0x00000000 0x00000000 0x00000 0x00000 0x4
Section to Segment mapping:
Segment Sections...
00
01 .interp
02 .reginfo
03 .interp .reginfo .dynamic .hash .dynsym .dynstr .init .text .MIPS.stubs .fini .rodata
04 .data.rel.ro .data .rld_map .got .sbss .bss
05 .dynamic
06
07
1. Patchwork MIPS: Allow FPU emulator to use non-stack area.
-
Thank you for the answer. I did not realize the question is so broad. I am only interested in the case for x86. Optionally, if you know something about ARM, that would be great. But I am OK with x86 only use cases.– drdotMay 3, 2017 at 21:12
Just-In-Time Compilation support could be one reason for pages to be legitimately marked RWX. In iOS MobileSafari is one of a small number of Apple apps that has a "dynamic codesigning" entitlement which allows for the RWX pages to be mapped. Despite the potential danger, JavaScript performance is too important to not have these pages. This makes Safari a desirable target for exploits. For more information on a recent iOS exploit that attacked Safari for its RWX pages read the Pegasus Technical Report
It seems some .NET native binaries, e.g. System.ni.dll
have an RWX .xdata
section, although I believe they're not generated by a normal compilation workflow (they're produced by ngen
AFAIK) so they're probably not covered by the current version of the question.