Segfault in qemu user emulation of Android binary

0

I'm running qemu on an Ubuntu 18.04 x64 host and trying to do user emulation of dynamic binaries built for Android (for aarch64 or i386) using the Android NDK, but I always get a segfault. For example:

Build
$ i686-linux-android28-clang hello_world.c -o hello_world
Check dependecies and paths
$ file ./hello_world

./hello_world: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /system/bin/linker, not stripped

$ readelf -d ./hello_world

Dynamic section at offset 0xef4 contains 24 entries:
  Tag        Type                         Name/Value
 0x00000003 (PLTGOT)                     0x1fdc
 0x00000002 (PLTRELSZ)                   48 (bytes)
 0x00000017 (JMPREL)                     0x318
 0x00000014 (PLTREL)                     REL
 0x00000015 (DEBUG)                      0x0
 0x00000006 (SYMTAB)                     0x200
 0x0000000b (SYMENT)                     16 (bytes)
 0x00000005 (STRTAB)                     0x270
 0x0000000a (STRSZ)                      96 (bytes)
 0x6ffffef5 (GNU_HASH)                   0x2d0
 0x00000001 (NEEDED)                     Shared library: [libdl.so]
 0x00000001 (NEEDED)                     Shared library: [libc.so]
 ...
Copy into an unpacked Android emulator image of Pixel 2 Android 9 i386.
$ ls ~/android_28_img/
acct        cache    d             dev   init.environ.rc       init.usb.rc       metadata  oem      sbin     sys         vendor
bin         charger  data          etc   init.rc               init.zygote32.rc  mnt       proc     sdcard   system
bugreports  config   default.prop  init  init.usb.configfs.rc  lost+found        odm       product  storage  ueventd.rc

$ sudo cp ./hello_world ~/android_28_img/system/bin
Copy static qemu there, too
$ sudo cp /usr/bin/qemu-i386-static ~/android_28_img/system/bin
Run emulator various ways
$ sudo chroot /home/user/android_28_img ./system/bin/qemu-i386-static /system/bin/hello_world
qemu: uncaught target signal 11 (Segmentation fault) - core dumped
Segmentation fault

$ qemu-i386 -L /home/user/android_38_img ./system/bin/hello_world
qemu: uncaught target signal 11 (Segmentation fault) - core dumped
Segmentation fault
strace
$ sudo chroot /home/user/android_28_img ./system/bin/qemu-i386-static -strace /system/bin/hello_world
60785 set_thread_area(0xffffa3f0) = 0
60785 mmap2(NULL,20480,PROT_NONE,MAP_PRIVATE|MAP_ANONYMOUS,-1,0) = 0xff6a5000
60785 madvise(-9809920,20480,12,-9809920,-8432404,-23672) = 0
60785 prctl(1398164801,0,-9809920,20480,-8681506,-23528) = -1 errno=22 (Invalid argument)
60785 mprotect(0xff6a6000,12288,PROT_READ|PROT_WRITE) = 0
60785 prctl(1398164801,0,-9805824,12288,-8681440,-23528) = -1 errno=22 (Invalid argument)
60785 set_tid_address(-8432484,0,20480,-9781248,-8432492,-23480) = 60785
60785 faccessat(AT_FDCWD,"/dev/urandom",R_OK,AT_SYMLINK_NOFOLLOW|0xff7f601c) = -1 errno=2 (No such file or directory)
60785 futex(0xff7f2a44,FUTEX_PRIVATE_FLAG|FUTEX_WAKE,2147483647,NULL,NULL,0) = 0
60785 sched_getscheduler(0,0,-8432496,-8432492,-8432492,-23528) = 0
60785 mmap2(NULL,20480,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS,-1,0) = 0xff6a0000
60785 madvise(-9830400,20480,12,-9830400,-8432404,-23688) = 0
60785 mprotect(0xff6a0000,4096,PROT_NONE) = 0
60785 sigaltstack(0xffffa3e8,(nil)) = 0
60785 prctl(1398164801,0,-9826304,16384,-8681429,-23528) = -1 errno=22 (Invalid argument)
60785 prctl(1398164801,0,-9830400,4096,-8681409,-23528) = -1 errno=22 (Invalid argument)
60785 mprotect(0xff7eb000,24576,PROT_READ) = 0
60785 mprotect(0xff7f4000,4096,PROT_READ) = 0
60785 mprotect(0xff7f4000,4096,PROT_READ|PROT_WRITE) = 0
60785 mprotect(0xff7f4000,4096,PROT_READ) = 0
60785 mmap2(NULL,4096,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS,-1,0) = 0xff69f000
60785 madvise(-9834496,4096,12,-9834496,-8432404,-23848) = 0
60785 prctl(1398164801,0,-9834496,4096,-8680817,-23704) = -1 errno=22 (Invalid argument)
60785 mprotect(0xff69f000,4096,PROT_READ) = 0
60785 mprotect(0xff69f000,4096,PROT_READ|PROT_WRITE) = 0
60785 mprotect(0xff69f000,4096,PROT_READ) = 0
60785 mprotect(0xff69f000,4096,PROT_READ|PROT_WRITE) = 0
60785 mprotect(0xff69f000,4096,PROT_READ) = 0
60785 mprotect(0xff69f000,4096,PROT_READ|PROT_WRITE) = 0
60785 mprotect(0xff69f000,4096,PROT_READ) = 0
60785 mprotect(0xff69f000,4096,PROT_READ|PROT_WRITE) = 0
60785 mprotect(0xff69f000,4096,PROT_READ) = 0
60785 mprotect(0xff69f000,4096,PROT_READ|PROT_WRITE) = 0
60785 mprotect(0xff69f000,4096,PROT_READ) = 0
60785 mprotect(0xff69f000,4096,PROT_READ|PROT_WRITE) = 0
60785 mprotect(0xff69f000,4096,PROT_READ) = 0
60785 mprotect(0xff69f000,4096,PROT_READ|PROT_WRITE) = 0
60785 mprotect(0xff69f000,4096,PROT_READ) = 0
60785 mprotect(0xff69f000,4096,PROT_READ|PROT_WRITE) = 0
60785 mprotect(0xff69f000,4096,PROT_READ) = 0
60785 mprotect(0xff69f000,4096,PROT_READ|PROT_WRITE) = 0
60785 mprotect(0xff69f000,4096,PROT_READ) = 0
60785 mprotect(0xff69f000,4096,PROT_READ|PROT_WRITE) = 0
60785 mprotect(0xff69f000,4096,PROT_READ) = 0
60785 mprotect(0xff69f000,4096,PROT_READ|PROT_WRITE) = 0
60785 mprotect(0xff69f000,4096,PROT_READ) = 0
60785 mprotect(0xff69f000,4096,PROT_READ|PROT_WRITE) = 0

60785 mprotect(0xff69f000,4096,PROT_READ) = 0
60785 mmap2(NULL,4096,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS,-1,0) = 0xff69e000
60785 madvise(-9838592,4096,12,-9838592,-8432404,-24136) = 0
60785 prctl(1398164801,0,-9838592,4096,-8693379,-23944) = -1 errno=22 (Invalid argument)
60785 mmap2(NULL,12,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS,-1,0) = 0xff69d000
60785 madvise(-9842688,12,12,-9842688,-8432404,-24280) = 0
60785 prctl(1398164801,0,-9842688,12,-8693213,-24136) = -1 errno=22 (Invalid argument)
60785 getrandom(-23744,40,1,40,-23744,-23768) = 40
60785 mmap2(NULL,1096,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS,-1,0) = 0xff69c000
60785 madvise(-9846784,1096,12,-9846784,-8432404,-23896) = 0
60785 prctl(1398164801,0,-9846784,1096,-8682952,-23752) = -1 errno=22 (Invalid argument)
60785 mmap2(NULL,4096,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS,-1,0) = 0xff69b000
60785 madvise(-9850880,4096,12,-9850880,-8432404,-24072) = 0
60785 prctl(1398164801,0,-9850880,4096,-8693379,-23880) = -1 errno=22 (Invalid argument)
60785 mmap2(NULL,12,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS,-1,0) = 0xff69a000
60785 madvise(-9854976,12,12,-9854976,-8432404,-24216) = 0
60785 prctl(1398164801,0,-9854976,12,-8693213,-24072) = -1 errno=22 (Invalid argument)
60785 mmap2(NULL,4096,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS,-1,0) = 0xff699000
60785 madvise(-9859072,4096,12,-9859072,-8432404,-23640) = 0
60785 prctl(1398164801,0,-9859072,4096,-8728674,-23496) = -1 errno=22 (Invalid argument)
60785 mprotect(0xff699000,4096,PROT_READ|PROT_WRITE) = 0
--- SIGSEGV {si_signo=SIGSEGV, si_code=1, si_addr=0x0000014e} ---
qemu: uncaught target signal 11 (Segmentation fault) - core dumped
Segmentation fault
Looking at crash dump
$ sudo apport-unpack /var/crash/_usr_bin_qemu-i386.101461.crash ~/crash-unpacked/
$ gdb /usr/bin/qemu-i386 ~/crash-unpacked/CoreDump

$ gdb /usr/bin/qemu-i386 ~/crash-unpacked/CoreDump
GNU gdb (Ubuntu 8.1-0ubuntu3.2) 8.1.0.20180409-git
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
pwndbg: loaded 175 commands. Type pwndbg [filter] for a list.
pwndbg: created $rebase, $ida gdb functions (can be used with print/break)
Reading symbols from /usr/bin/qemu-i386...(no debugging symbols found)...done.
[New LWP 61385]
[New LWP 61386]
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Core was generated by `qemu-i386 -L /home/user/android_28_img ./system/bin/hello_world'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x00007f0853f7b2e6 in __GI___sigsuspend (set=0x7ffdb0445f48) at ../sysdeps/unix/sysv/linux/sigsuspend.c:26
26  ../sysdeps/unix/sysv/linux/sigsuspend.c: No such file or directory.
[Current thread is 1 (Thread 0x7f0855413e00 (LWP 61385))]
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
─────────────────────────────────────────────────────────────────[ REGISTERS ]──────────────────────────────────────────────────────────────────
 RAX  0xfffffffffffffdfe
 RBX  0x7ffdb0445f48 ◂— 0xfffffffe7ffffbff
 RCX  0x7f0853f7b2e6 (sigsuspend+70) ◂— cmp    rax, -0x1000 /* 'H=' */
 RDX  0x0
 RDI  0x7ffdb0445f48 ◂— 0xfffffffe7ffffbff
 RSI  0x8
 R8   0x0
 R9   0xb
 R10  0x8
 R11  0x293
 R12  0x7ffdb0445f40 ◂— 0x0
 R13  0x5581b1e9c210 ◂— 0xefc9
 R14  0xb
 R15  0x0
 RBP  0xb
 RSP  0x7ffdb0445f10 ◂— 0xb /* '\x0b' */
 RIP  0x7f0853f7b2e6 (sigsuspend+70) ◂— cmp    rax, -0x1000 /* 'H=' */
───────────────────────────────────────────────────────────────────[ DISASM ]───────────────────────────────────────────────────────────────────
 ► 0x7f0853f7b2e6 <sigsuspend+70>     cmp    rax, -0x1000
   0x7f0853f7b2ec <sigsuspend+76>     ja     sigsuspend+122 <0x7f0853f7b31a>
    ↓
   0x7f0853f7b31a <sigsuspend+122>    mov    rcx, qword ptr [rip + 0x3abb47]
   0x7f0853f7b321 <sigsuspend+129>    neg    eax
   0x7f0853f7b323 <sigsuspend+131>    mov    dword ptr fs:[rcx], eax
   0x7f0853f7b326 <sigsuspend+134>    mov    eax, 0xffffffff
   0x7f0853f7b32b <sigsuspend+139>    jmp    sigsuspend+78 <0x7f0853f7b2ee>
    ↓
   0x7f0853f7b2ee <sigsuspend+78>     mov    edi, edx
   0x7f0853f7b2f0 <sigsuspend+80>     mov    dword ptr [rsp + 0xc], eax
   0x7f0853f7b2f4 <sigsuspend+84>     call   __libc_disable_asynccancel <0x7f085406c8f0>
 
   0x7f0853f7b2f9 <sigsuspend+89>     mov    eax, dword ptr [rsp + 0xc]
───────────────────────────────────────────────────────────────────[ STACK ]────────────────────────────────────────────────────────────────────
00:0000│ rsp      0x7ffdb0445f10 ◂— 0xb /* '\x0b' */
01:0008│          0x7ffdb0445f18 ◂— 0xdb8b156e6a07500
02:0010│          0x7ffdb0445f20 —▸ 0x7ffdb0445f48 ◂— 0xfffffffe7ffffbff
03:0018│          0x7ffdb0445f28 —▸ 0x5581ae7bbb14 ◂— call   0x5581ae770710
04:0020│          0x7ffdb0445f30 ◂— 0x0
05:0028│          0x7ffdb0445f38 ◂— 0xffffffffffffffff
06:0030│ r12      0x7ffdb0445f40 ◂— 0x0
07:0038│ rbx rdi  0x7ffdb0445f48 ◂— 0xfffffffe7ffffbff
─────────────────────────────────────────────────────────────────[ BACKTRACE ]──────────────────────────────────────────────────────────────────
 ► f 0     7f0853f7b2e6 sigsuspend+70
   f 1     5581ae7bbb14
   f 2     5581ae7bc6b8
   f 3     5581ae7bd4db process_pending_signals+363
   f 4     5581ae7a06e8 cpu_loop+504
   f 5     5581ae773504 main+1860
   f 6     7f0853f5db97 __libc_start_main+231
I get the same behavior building and emulating for aarch64 and using the libraries from an unpacked Galaxy S9 image.
android
segmentation-fault
emulation
qemu
asked on Stack Overflow Aug 25, 2020 by user6065948

1 Answer

0

Probably the Android binary is trying to use a kernel feature QEMU doesn't implement, or else it is doing something unexpected -- mostly QEMU's user-emulation mode is tested on normal Linux userspace binaries, not Android ones. For instance you can see in the strace() a lot of failing prctl() calls: one good start on debugging this would be to figure out what they are trying to do and check whether QEMU implments them.

You might also find it useful to use QEMU's built-in debug stub and attach an x86-aware gdb to it: then you can step through the execution of the guest code and see what it is doing when it goes wrong.

Finally, you don't mention which QEMU version you're using -- if it is not the latest version, it's always worth trying the latest to check whether it's something that's already been fixed. (In particular any version of QEMU before about 4.0 has some really bad bugs to do with multithreading and signals in its user-mode emulation.)

answered on Stack Overflow Aug 27, 2020 by Peter Maydell

User contributions licensed under CC BY-SA 3.0