Please find submitted a patch for getdents (this system call stands for "get directory entries", it is passed a file descriptor pointing to a directory and returns a struct with info on the entries in that directory.) This patch is against qemu-2.10 series but continues to apply cleanly on current as of April 15 2018. If you are running a 32-bit binary on 64-bit target current qemu will convert he getdents struct, but running a 64-bit binary on 32-bit target it passes the struct straight through causing incorrect behavior (file type is in the middle of the 64-bit struct and at the end of the 32-bit one).
My use case for this has been running aapt (from Android SDK) and whatever other misc x86-64 bins android studio runs when building on a 32-bit ARM (I previously had run these x86-64 bins on 32-bit Intel). After an android build tools update, aapt began erroring out until I applied this patch. Peter Maydell has raised a concern about possible buffer overflows in this code (which was meant to handle 32-bit app on 64-bit system, not 64-bit on 32-bit). I must admit I haven't gone through the dirent-copying code with a fine-toothed comb... it appeared to work for my use case. That said, the code seems to be careful about using offsetof() rather than making any assumptions. In addition, the dirent-copying code appears to have an assert that would crash qemu if it was going to write past the end of the dirent buffer -- always nice to have plenty of sanity checks! --Thanks! Henry Wertz Signed-off-by: Henry Wertz <hwert...@gmail.com>
*** linux-user/syscall.c~ 2017-03-04 10:31:14.000000000 -0600 --- linux-user/syscall.c 2017-03-07 17:08:24.615399116 -0600 *************** *** 9913,9921 **** #endif #ifdef TARGET_NR_getdents case TARGET_NR_getdents: #ifdef __NR_getdents ! #if TARGET_ABI_BITS == 32 && HOST_LONG_BITS == 64 { struct target_dirent *target_dirp; struct linux_dirent *dirp; abi_long count = arg3; --- 9913,9921 ---- #endif #ifdef TARGET_NR_getdents case TARGET_NR_getdents: #ifdef __NR_getdents ! #if TARGET_ABI_BITS != HOST_LONG_BITS { struct target_dirent *target_dirp; struct linux_dirent *dirp; abi_long count = arg3;