elf_loader fails when trying to execute MAMBO with qemu
umarcor opened this issue · 3 comments
When trying to execute MAMBO (compiled for aarch64) in a x86_64 machine with qemu-user
and qemu-user-binfmt
, I get the following error with any of the test programs in subdir test
:
$ ./dbm test/mmap_munmap
dbm: elf_loader/elf_loader.c:127: load_elf: Assertion `tmpmem != MAP_FAILED' failed.
qemu: uncaught target signal 6 (Aborted) - core dumped
Aborted (core dumped)
$ ./dbm test/mprotect_exec
dbm: elf_loader/elf_loader.c:127: load_elf: Assertion `tmpmem != MAP_FAILED' failed.
qemu: uncaught target signal 6 (Aborted) - core dumped
Aborted (core dumped)
$ ./dbm test/self_modifying
dbm: elf_loader/elf_loader.c:127: load_elf: Assertion `tmpmem != MAP_FAILED' failed.
qemu: uncaught target signal 6 (Aborted) - core dumped
Aborted (core dumped)
$ ./dbm test/signals
dbm: elf_loader/elf_loader.c:127: load_elf: Assertion `tmpmem != MAP_FAILED' failed.
qemu: uncaught target signal 6 (Aborted) - core dumped
Aborted (core dumped)
$ ./dbm test/load_store
dbm: elf_loader/elf_loader.c:127: load_elf: Assertion `tmpmem != MAP_FAILED' failed.
qemu: uncaught target signal 6 (Aborted) - core dumped
Aborted (core dumped)
$ file dbm
dbm: ELF 64-bit LSB executable, ARM aarch64, version 1 (GNU/Linux), statically linked, for GNU/Linux 3.7.0, BuildID[sha1]=6fdc5668b8be289035afb34d6b94f8a2073a6f89, with debug_info, not stripped
$ file test/mmap_munmap
test/mmap_munmap: ELF 64-bit LSB executable, ARM aarch64, version 1 (GNU/Linux), statically linked, for GNU/Linux 3.7.0, BuildID[sha1]=f455bb2d4e1611bda4d4208be72e372f78a9fabd, not stripped
$ file test/mprotect_exec
test/mprotect_exec: ELF 64-bit LSB executable, ARM aarch64, version 1 (GNU/Linux), statically linked, for GNU/Linux 3.7.0, BuildID[sha1]=9e04f900f9c66b5a1d44ae05654c9ba28deda6ff, not stripped
$ file test/self_modifying
test/self_modifying: ELF 64-bit LSB executable, ARM aarch64, version 1 (GNU/Linux), statically linked, for GNU/Linux 3.7.0, BuildID[sha1]=38e0550f60883f8c8629968321fb86f935a0ac76, with debug_info, not stripped
$ file test/signals
test/signals: ELF 64-bit LSB executable, ARM aarch64, version 1 (GNU/Linux), statically linked, for GNU/Linux 3.7.0, BuildID[sha1]=26880b03cee6e95beb2ad95c3956b523a51a0a84, with debug_info, not stripped
$ file test/load_store
test/load_store: ELF 64-bit LSB executable, ARM aarch64, version 1 (GNU/Linux), statically linked, for GNU/Linux 3.7.0, BuildID[sha1]=ec50e8372d12854f55cd56989062d16de12a295e, with debug_info, not stripped
If I copy the same binaries to an ARM machine, all of them work as expected.
I tried compiling MAMBO and the tests both natively in an ARM machine and cross-compiling them for aarch64 in a x86_64 host. The results are the same.
Moreover, when trying to run the tests without MAMBO, mmap_munmap
produces the same error, but not the others:
$ ./test/mmap_munmap
mmap_munmap: mmap_munmap.c:33: main: Assertion `alloc == MAP_FAILED' failed.
qemu: uncaught target signal 6 (Aborted) - core dumped
Aborted (core dumped)
$ ./test/mprotect_exec
main()
$ ./test/self_modifying
This should be printed
This should also be printed
$ ./test/signals
Simple signal handler: success
Signal after flushing the code cache: success
Test sigsuspend: success
Test against race conditions between code generation and signals: success
Test for missed signals: success
Test signal handling in fragments containing CB(N)Z: success
Test signal handling in fragments containing TB(N)Z: success
Test handling of a synchronous SIGTRAP signal: success
Test handling of a synchronous SIGILL signal: success
Test receiving SIGILL when no handler is installed
qemu: uncaught target signal 4 (Illegal instruction) - core dumped
Illegal instruction (core dumped)
$ ./test/load_store
start: a64
end: a64
@lgeek, any hint about how to debug this?
Last time I've tried to run MAMBO using qemu user mode emulation, I've ran into numerous qemu bugs. Use native hardware or system mode emulation. The assertion at elf_loader/elf_loader.c:127
should never fail when running natively. I'm curious to see what's causing it to fail in qemu, but I don't have a debug build available at the moment.
$ ./test/mmap_munmap
mmap_munmap: mmap_munmap.c:33: main: Assertion `alloc == MAP_FAILED' failed.
qemu: uncaught target signal 6 (Aborted) - core dumped
Aborted (core dumped)
That's a qemu bug. Please report it to them. According to the mmap
manual:
If len is zero, mmap() shall fail and no mapping shall be established.
Indeed, I stripped down mmap_munmap
to:
#include <stdlib.h>
#include <assert.h>
#include <sys/mman.h>
#include <errno.h>
#include <stdio.h>
int main() {
// Failing allocation
void *alloc = mmap(NULL, 0, PROT_EXEC | PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
printf("alloc: %d\n", alloc);
printf("MAP_FAILED: %d\n", MAP_FAILED);
printf("errno: %d\n", errno);
assert(alloc == MAP_FAILED);
return 0;
}
I cross compiled in x86_64:
aarch64-linux-gnu-gcc -static -std=gnu99 -lpthread test/mmap_qemu.c -o mmap_qemu
This is the output in x86_64:
$ ./mmap_qemu
alloc: 0
MAP_FAILED: -1
errno: 0
mmap_qemu: test/mmap_qemu.c:15: main: Assertion `alloc == MAP_FAILED' failed.
qemu: uncaught target signal 6 (Aborted) - core dumped
Aborted (core dumped)
This is the output in a Jetson TX1:
$ ./mmap_qemu
alloc: -1
MAP_FAILED: -1
errno: 22
So, as you said, qemu is not handling mmap properly. It is returning a success (0
) when it should be returning a failure (-1
, MAP_FAILED
). I reported it to them: https://bugs.launchpad.net/ubuntu/+source/qemu/+bug/1783362
I'm closing this for now. Thanks!
A little update just to let you know that a fix for the reported bug was already committed to master: