Ubuntu 执行某些x64二进制文件时出现execve ENOMEM(无法分配内存)错误

Ubuntu 执行某些x64二进制文件时出现execve ENOMEM(无法分配内存)错误,ubuntu,binary,execve,Ubuntu,Binary,Execve,当我在ubuntu 17.10中执行一些静态链接的二进制文件时, 其他二进制文件也可以,但一些特定的二进制文件是个问题 gdb-peda$ x/15i 0x4000f0 0x4000f0: push 0x400105 0x4000f5: push 0x0 0x4000f7: xor rax,rax 0x4000fa: mov edx,0x10000 0x4000ff: mov rsi,rsp 0x4001

当我在ubuntu 17.10中执行一些静态链接的二进制文件时, 其他二进制文件也可以,但一些特定的二进制文件是个问题

gdb-peda$ x/15i 0x4000f0
   0x4000f0:    push   0x400105
   0x4000f5:    push   0x0
   0x4000f7:    xor    rax,rax
   0x4000fa:    mov    edx,0x10000
   0x4000ff:    mov    rsi,rsp
   0x400102:    xor    rdi,rdi
   0x400105:    syscall 
   0x400107:    mov    eax,0x1
   0x40010c:    mov    edx,0x1000
   0x400111:    pop    rsi
   0x400112:    mov    edi,0x1
   0x400117:    syscall 
   0x400119:    mov    eax,0x3c
   0x40011e:    ret
所有代码都类似于上面的代码。 如果运行此二进制文件,则会得到以下错误语句:

root@ubuntu:/home/hitcon/Desktop# ./biglittle 
Segmentation fault
我用strace追踪它因为这个二进制是静态链接的, 我知道了

root@ubuntu:/home/hitcon/Desktop# strace -fFi ./biglittle 
[00007f9eaed12fa7] execve("./biglittle", ["./biglittle"], [/* 53 vars */]) = -1 ENOMEM (Cannot allocate memory)
[00007f9eaed12fa7] --- SIGSEGV {si_signo=SIGSEGV, si_code=SI_KERNEL, si_addr=NULL} ---
[????????????????] +++ killed by SIGSEGV +++
Segmentation fault (core dumped)

有人能给我一些建议来修复它吗?

我在一个特殊的二进制文件上使用了完全相同的
strace
。让我们命名一个比二进制文件更简单的
foo.elf

在docker中运行时,在流控制到达elf入口点之前,在内核空间中运行
foo.elf
segfaults*。正如您所展示的:
execve
返回ENOMEM,然后
strace
进程本身通过
si_code=si_内核
接收奇怪的SIGSEGV

*更准确地说,segfaults不是由
foo.elf
进程引起的(该进程甚至从未开始运行),而是由其post-fork()父进程获得SIGSEGV

但是,
foo.elf
在主机系统上运行良好

令人费解


这就是我在我的案例中发现的。My
foo.elf
可执行文件是静态链接的:

⚓ file foo.elf foo.elf: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), statically linked, stripped -请参阅,没有
INTERP
部分。与基线动态可执行文件比较:

⚓ readelf --segments /bin/ls Elf file type is EXEC (Executable file) Entry point 0x404b48 There are 9 program headers, starting at offset 64 Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flags Align PHDR 0x0000000000000040 0x0000000000400040 0x0000000000400040 0x00000000000001f8 0x00000000000001f8 R E 8 INTERP 0x0000000000000238 0x0000000000400238 0x0000000000400238 0x000000000000001c 0x000000000000001c R 1 [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2] LOAD 0x0000000000000000 0x0000000000400000 0x0000000000400000 0x00000000000193fc 0x00000000000193fc R E 200000 LOAD 0x000000000001a328 0x000000000061a328 0x000000000061a328 0x00000000000012d8 0x0000000000001ff8 RW 200000 DYNAMIC 0x000000000001ada8 0x000000000061ada8 0x000000000061ada8 0x0000000000000200 0x0000000000000200 RW 8 NOTE 0x0000000000000254 0x0000000000400254 0x0000000000400254 0x0000000000000044 0x0000000000000044 R 4 GNU_EH_FRAME 0x0000000000016650 0x0000000000416650 0x0000000000416650 0x0000000000000744 0x0000000000000744 R 4 GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 RW 10 GNU_RELRO 0x000000000001a328 0x000000000061a328 0x000000000061a328 0x0000000000000cd8 0x0000000000000cd8 R 1 Section to Segment mapping: Segment Sections... 00 01 .interp [...]
这个很好用。在docker或其他情况下,无故障。呜呼,难题解决了!希望这对其他人有所帮助:)

我在一个特殊的二进制文件上使用了完全相同的
strace
。让我们命名一个比二进制文件更简单的
foo.elf

在docker中运行时,在流控制到达elf入口点之前,在内核空间中运行
foo.elf
segfaults*。正如您所展示的:
execve
返回ENOMEM,然后
strace
进程本身通过
si_code=si_内核
接收奇怪的SIGSEGV

*更准确地说,segfaults不是由
foo.elf
进程引起的(该进程甚至从未开始运行),而是由其post-fork()父进程获得SIGSEGV

但是,
foo.elf
在主机系统上运行良好

令人费解


这就是我在我的案例中发现的。My
foo.elf
可执行文件是静态链接的:

⚓ file foo.elf foo.elf: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), statically linked, stripped -请参阅,没有
INTERP
部分。与基线动态可执行文件比较:

⚓ readelf --segments /bin/ls Elf file type is EXEC (Executable file) Entry point 0x404b48 There are 9 program headers, starting at offset 64 Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flags Align PHDR 0x0000000000000040 0x0000000000400040 0x0000000000400040 0x00000000000001f8 0x00000000000001f8 R E 8 INTERP 0x0000000000000238 0x0000000000400238 0x0000000000400238 0x000000000000001c 0x000000000000001c R 1 [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2] LOAD 0x0000000000000000 0x0000000000400000 0x0000000000400000 0x00000000000193fc 0x00000000000193fc R E 200000 LOAD 0x000000000001a328 0x000000000061a328 0x000000000061a328 0x00000000000012d8 0x0000000000001ff8 RW 200000 DYNAMIC 0x000000000001ada8 0x000000000061ada8 0x000000000061ada8 0x0000000000000200 0x0000000000000200 RW 8 NOTE 0x0000000000000254 0x0000000000400254 0x0000000000400254 0x0000000000000044 0x0000000000000044 R 4 GNU_EH_FRAME 0x0000000000016650 0x0000000000416650 0x0000000000416650 0x0000000000000744 0x0000000000000744 R 4 GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 RW 10 GNU_RELRO 0x000000000001a328 0x000000000061a328 0x000000000061a328 0x0000000000000cd8 0x0000000000000cd8 R 1 Section to Segment mapping: Segment Sections... 00 01 .interp [...] 这个很好用。在docker或其他情况下,无故障。呜呼,难题解决了!希望这对其他人有所帮助:)

⚓ readelf --file-header foo.elf ELF Header: Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 Class: ELF64 Data: 2's complement, little endian Version: 1 (current) OS/ABI: UNIX - System V ABI Version: 0 Type: DYN (Shared object file) Machine: Advanced Micro Devices X86-64 Version: 0x1 Entry point address: 0x14b5b0 Start of program headers: 64 (bytes into file) Start of section headers: 0 (bytes into file) Flags: 0x0 Size of this header: 64 (bytes) Size of program headers: 56 (bytes) Number of program headers: 3 Size of section headers: 64 (bytes) Number of section headers: 0 Section header string table index: 0
foo.elf.nopie: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, stripped