linuxlinux-kernelx86vdso

Where do the `[stack]`, `[vdso]` and `[vsyscall]` mmaps come from?


Consider the following program targeting Linux x86_64:

inf.s:

    .global _start
    .text
_start:
    jmp _start

Which is basically an infinite loop.

If I link and strip this I get an ELF executable:

$ gcc -nostdlib inf.s

$ ./a.out &

[1] 15862

$ cat /proc/15862/maps

00400000-00401000 r-xp 00000000 fc:00 11404632           a.out
7fffacdb8000-7fffacdd9000 rwxp 00000000 00:00 0          [stack]
7fffacddd000-7fffacdde000 r-xp 00000000 00:00 0          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0  [vsyscall]

In the ELF executable the first program header LOAD contains the map that accounts for the first of the entry in the above mmaps (a.out). (Even if I strip everying but this header and code the same maps are observed.) execve(2) calls the ELF handler in fs/binfmt_elf.c which reads the program header and calls mmap on the file.

What I don't understand is where the other three come from (stack, vdso, vsyscall). They are not mentioned in the ELF file, so the Linux kernel must setup these three "anonymous" or "special" maps up by default.

My question is where in the kernel code (or how) does the Linux kernel create these other three maps? Are they inherited across the execve? I can't seem to see where in fs/exec.c they are created.


Solution

  • They are created automatically by the kernel when is loads a file into memory to run it.

    The precise control flows for [vdso] and [vsyscall] are hard to follow because there is all sorts of defining and redefining of function names as macros depending on whether the kernel is 32 or 64 bit but some relevant routines include:

    The [stack] mapping is not ELF specific and is created by __bprm_mm_init in fs/exec.c which is called by the execve code before it invokes the format specific loader.