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.
Advertisement
Answer
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:
load_elf_binary
infs/binfmt_elf.c
which callsarch_setup_additional_pages
arch_setup_additional_pages
inarch/x86/vdso/vma.c
arch_setup_additional_pages
inarch/x86/vdso/vdso32-setup.c
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.