Code (.text) not executing only for execution? .Rodata is executable?

I am trying to understand how ELF segments are mapped into memory. I noticed that different sections are mapped to the same ELF segment. For example, .rodata is displayed in the same segment as .text.

Why is this so? Why not map .rodata to a single read-only segment rather than an executable?

Besides, what makes it display the .text section in the "execute ONLY" segment (cannot be read)? Are there kernel / HW limitations that can prevent this?

EDIT: I can also add that I use the GNU linker, if that matters.

+6
source share
3 answers

Compiled from the comments above

On several computer architectures, including x86-64, it is not possible to mark memory as executable, but not readable.

While x86 16-bit and 32-bit allowed legacy segmentation, and theoretically, memory segments could only be used as executable memory, the advantages of flat address space were so great that now x86-64 mostly ignores segment registers :

3.2.4 IA-32e segmentation

In Intel 64-IA-32e mode, segmentation effects depend on whether the processor is in compatibility mode or 64-bit mode. In compatibility mode, segmentation functions in the same way as using the outdated semantics of 16-bit or 32-bit protected mode.

In 64-bit mode, segmentation is usually (but not completely) disabled, creating a flat 64-bit linear address space. The processor processes the base of the CS, DS, ES, SS segments as zero, creating a linear address equal to the effective address. The FS and GS segments are exceptions. These segment registers (which contain the segment base) can be used as additional base registers in linear address calculations. They make it easy to access local data and specific data structures of the operating system.

Note that the processor does not check segment limit values ​​at run time in 64-bit mode.

Thus, kernels simply set their segments to cover the entire address space and do not rely on segmentation to provide memory protection.

What they use is the attributes of the page table. Each page on the process memory card has an entry in the page table that controls access to it. An overview of their format can be seen here , but, most importantly, there are two bits that control what type of access is allowed:

  • Bit 1 (R / W): 0 indicates read-only, 1 indicates read-write.
  • Bit 63 (XD): 0 indicates an executable file, 1 indicates non-execution.

It is not possible to specify a combination with executable-noread-nowrite with these flags. If the page is present on the memory card, it must be readable.

The solution is quickly approaching the latest Intel Skylake microarchitecture, which will only use RAM: this is the baptism function MPK ( memory protection key ), support for which has landed in the recently released Linux 4.6 kernel. The keys occupy four bits of 62:59 entries in the page table, and memory areas can be marked with a key indicating access to some type-noworite.

+7
source
% 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 

Each section has its own attributes, such as READONLY , CONTENTS , ALLOC , LOAD , DATA

sections with the same attr can be displayed together.

According to the elf

  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. 

ELF has a SHF_EXECINSTR attr section, so this compiler or link does not set attr.

-one
source

section and segment are two different concepts, the boot program use a segment, you can even split the partition table. a segment can contain several sections ..rodata and .text are both read-only. therefore, they can be placed in the same segment.

-one
source

All Articles