/proc/self/maps - 3rd mapped piece of file?

6,695

I finally figured this out. The kernel does map only 2 segments. The third piece is a portion of one of the two loaded by the kernel. The run time linker, the program named in the INTERP pheader, which is /usr/lib/ld-2.24.so for me right now, changes the permissions on the mappings using mprotect() so that there are read/write global variables, read-only global variables, and a read/execute text segment. You can see this happen using strace, but it's easy to miss, as it's only a single mprotect() call.

It wasn't a kernel change that caused this, it was a GNU lib C change.

Share:
6,695

Related videos on Youtube

Admin
Author by

Admin

Updated on September 18, 2022

Comments

  • Admin
    Admin over 1 year

    I'm running Arch linux on my laptop, which is kernel 3.12.9 right now. Something has changed about the way the kernel maps in a dynamically-linked executable and I can't figure it out. Here's the example:

    % /usr/bin/cat /proc/self/maps
    ...
    00400000-0040b000 r-xp 00000000 08:02 1186756             /usr/bin/cat
    0060a000-0060b000 r--p 0000a000 08:02 1186756             /usr/bin/cat
    0060b000-0060c000 rw-p 0000b000 08:02 1186756             /usr/bin/cat
    00d6c000-00d8d000 rw-p 00000000 00:00 0                   [heap]
    7f29b3485000-7f29b3623000 r-xp 00000000 08:02 1182988     /usr/lib/libc-2.19.so
    ...
    

    My question is: what is the third mapping from /usr/bin/cat?

    Based on readelf -l /usr/bin/cat, there's a loadable segment of 0x1f8 bytes that should map at 0x400000. There's a loadable segment of 0xae10 bytes at 0x60ae10. Those two pieces of file correspond to the 00400000-0040b000 mapping, and the 0060a000-0060b000 mapping. But the third mapping, which claims to be at a file offset of 0xb000 bytes, doesn't seem to correspond to any Elf64_Phdr. In fact, the elf header only has 2 PT_LOAD segments.

    I read through fs/binfm_elf.c in the kernel 3.13.2 source code, and I don't see that the kernel maps in anything other than PT_LOAD segments. If I run strace -o trace.out /usr/bin/cat /proc/self/maps, I don't see any mmap() calls that would map in a piece of /usr/bin/cat, so that 3rd piece is mapped in by the kernel.

    I ran the same command (cat /proc/self/maps) on a RHEL server that was running kernel 2.6.18 + RH patches. That only shows 2 pieces of /usr/bin/cat mapped into memory, so this might be new with kernel 3.x.

    • Admin
      Admin about 10 years
      Just confirming your findings, I noticed the same differences on CentOS 5 (2.6.18-238.19.1.el5). However on CentOS 6 (2.6.32-358.11.1.el6.x86_64) it too shows the 3 segments. When reading this I also had the thought if this was something to do with SELinux or security in some way.
    • Admin
      Admin about 10 years
      Isn't that code (.text), read-only data (.rodata), and read-write global data (.data)?
    • Admin
      Admin about 10 years
      @Gilles - if you do readelf -h /usr/bin/cat, you can see that the .text and .rodata sections end up in the first LOAD segment. .data and .bss sections end up in the second LOAD segment. This 3rd mapped segment is something else.
    • Admin
      Admin over 9 years
      @psusi I'm pretty sure that the .data section belongs to the second loadable segment.
    • Admin
      Admin over 9 years
      @newbie, again, it can't since the second mapping is read only, and the data segment must be writable.
    • Admin
      Admin over 9 years
      @psusi I'm talking about segment in ELF header, not a memory region. The second LOAD segment splits into two memory regions with r--p and rw-p execute permissions respectively. The question is why does it happen.
    • Admin
      Admin over 9 years
      @newbie, because the Sections: header says it is divided into the .got.plt, .data, and .bss segments.
    • Admin
      Admin over 9 years
      @psusi - I'm pretty sure that the ELF loader in the kernel doesn't look at the Sections header at all, just the Pheaders. I'm still confused about this, by the way. I was working on a "userland exec" at the time, and mapping in just the 2 LOAD segments works fine for userland exec
    • Admin
      Admin over 9 years
      @newbie, that is pretty fscked up. The .init_array and .fini_array should definitely be read only, as they are actually mapped. Not sure why the headers says they aren't.