ld.so --verify on this program crashes (when compiled on x86_64): char buffer[3ULL << 45]; int main (void) { } Before running the following command, enable unlimited memory overcommit with vm.overcommit_memory=1. $ gdb --args /lib64/ld-linux-x86-64.so.2 ./a.out … (gdb) r Starting program: /usr/lib64/ld-linux-x86-64.so.2 ./a.out Program received signal SIGSEGV, Segmentation fault. 0x000055555556d4ba in mmap64 () at ../sysdeps/unix/syscall-template.S:84 84 T_PSEUDO (SYSCALL_SYMBOL, SYSCALL_NAME, SYSCALL_NARGS) (gdb) disas Dump of assembler code for function mmap64: 0x000055555556d4b0 <+0>: add %al,(%rax) 0x000055555556d4b2 <+2>: add %al,(%rax) 0x000055555556d4b4 <+4>: add %al,(%rax) 0x000055555556d4b6 <+6>: add %al,(%rax) 0x000055555556d4b8 <+8>: add %al,(%rax) => 0x000055555556d4ba <+10>: add %al,(%rax) 0x000055555556d4bc <+12>: add %al,(%rax) 0x000055555556d4be <+14>: add %al,(%rax) 0x000055555556d4c0 <+16>: add %al,(%rax) 0x000055555556d4c2 <+18>: add %al,(%rax) 0x000055555556d4c4 <+20>: add %al,(%rax) 0x000055555556d4c6 <+22>: add %al,(%rax) 0x000055555556d4c8 <+24>: add %al,(%rax) 0x000055555556d4ca <+26>: add %al,(%rax) 0x000055555556d4cc <+28>: add %al,(%rax) 0x000055555556d4ce <+30>: add %al,(%rax) 0x000055555556d4d0 <+32>: add %al,(%rax) 0x000055555556d4d2 <+34>: add %al,(%rax) End of assembler dump. (gdb) The opcodes correspond to NUL bytes, so the mmap system call stub itself has been over-mapped. Due to ASLR, this can happen randomly with much smaller executables.
Reportedly, this affects ldd as well.
I cannot reproduce this with ldd. Could you provide more details on how to compile the binary to reproduce the issue? I used `gcc -pie -ggdb ./test.c` but although it crashes when I execute the program, it does not crash when I run `ldd`.
It looks like the kernel has changed the address space layout since I posted this. Try this with vm.overcommit_memory=1: char buffer[(128ULL << 40) - 0x500000]; int main (void) { } I get: openat(AT_FDCWD, "./a.out", O_RDONLY|O_CLOEXEC) = 3 read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\2\0>\0\1\0\0\0 \20@\0\0\0\0\0"..., 832) = 832 fstat(3, {st_mode=S_IFREG|0775, st_size=21760, ...}) = 0 getcwd("/tmp", 128) = 5 mmap(0x400000, 4096, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0) = 0x400000 mmap(0x401000, 4096, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1000) = 0x401000 mmap(0x402000, 4096, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x2000) = 0x402000 mmap(0x403000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x2000) = 0x403000 mmap(0x405000, 140737483108416, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x405000 --- SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_ACCERR, si_addr=0x7f01bd2e2086} --- +++ killed by SIGSEGV (core dumped) +++