Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Linux minimum Load Address with LD

In the process of understanding ELF program loading in Linux I was trying to experiment with the load address of a segment.

Using ld with the following linker script:

SECTIONS
{
    . = 0x2000;
    .text :
    {
        *(.text)     
    }
} 

With the following link command:

ld -o elftest -z max-page-size=4096 -Telftest.l elftest.o

Please assume that the elftest.o is the compilation result of a trivial non important asm code.

The program links correctly with the entrypoint at 0x2000. What happens is that the program gets killed by the kernel with the output KILLED in the shell.

I want to set one thing straight:

it isn't a segfault or any other exception, the program doesn't even reach entry point

The readelf output for --segments is

Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align

LOAD           0x0000000000001000 0x0000000000002000 0x0000000000002000
                 0x0000000000000009 0x0000000000000009  R E    1000

What I understand is the following:

  • Using max-page-size=4096 allows me to break the 2MiB aligment requirment for ld https://lkml.org/lkml/2012/7/9/46
  • The segment must be in aligned to a memory page, i.e. 4KiB so setting to 4096 is correct
  • The base address is arbitrary, usually for x86_64 is 0x400000

What I don't understand is:

  • When aligment requirment is met, why does an small address doesn't work (gets killed)?
  • If there is a minimun required address where is documented?
  • Why does it work with a higher base address i.e. 0x16000?

I'm doing this test in a 64bit computer with Arch Linux with kernel 3.17.1 and ld 2.24

like image 938
felknight Avatar asked Dec 06 '25 12:12

felknight


1 Answers

You're running into kernel limitations on where pages can be mapped by userspace applications; these restrictions are intended to prevent certain kernel exploits from working. The minimum mappable address is set by the vm.mmap_min_addr sysctl value, and is usually at least 4096 (i.e, 0x1000).

For details, see: https://wiki.debian.org/mmap_min_addr (The situation is not unique to Debian; their documentation is just the first I found.)


Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!