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;

Reply via email to