The problem here is not the mmap(), it is that you are mapping it as
only PROT_WRITE and not also PROT_READ. With the native kernel, syscalls
which only write to a buffer and do not read from it (like read(2)) only
require write permissions on that memory. QEMU's implementation requires
both write and read permission.

This is a QEMU bug, but not a major one, because in practice no guest
binaries set up memory that is only writable and can't be read (what
would they do with the data that they wrote into that memory?). You can
work around it in your test program by using mmap(..., PROT_READ |
PROT_WRITE, ...), which will allow it to work in QEMU.

(Technical QEMU internal notes for other developers: the issue here is
that we do permissions checks in syscall.c using lock_user(VERIFY_WRITE,
...) etc, but in access_ok() we treat VERIFY_WRITE as "implies read
access" when we're choosing the permissions flags to pass to
page_check_range(). To fix this we would have to check all the places we
use VERIFY_WRITE to identify which should be "only need write" and which
are "need both read and write".)


** Summary changed:

- qemu-arm-static read() doesn't accept mmap address as destination
+ qemu linux-user requires read permissions on memory passed to syscalls that 
should only need write access

** Changed in: qemu
       Status: New => Confirmed

-- 
You received this bug notification because you are a member of qemu-
devel-ml, which is subscribed to QEMU.
https://bugs.launchpad.net/bugs/1779955

Title:
  qemu linux-user requires read permissions on memory passed to syscalls
  that should only need write access

Status in QEMU:
  Confirmed

Bug description:
  When read() function takes an mmap'ed address as output buffer, it
  returns EFAULT. The expected behavior is it should just work.

  The following code works for qemu-system-arm, but not for qemu-arm-
  static.

  QEMU version affected: latest release 2.12.0.

  Steps to reproduce (please substitute /path/to/qemu-arm-static with
  the path of the binary, and /tmp/a.cpp with the example source code
  attached):

  # First register binfmt_misc
  [hidden]$ docker run --rm --privileged multiarch/qemu-user-static:register 
--reset

  # Compile the code and run
  [hidden]$ docker run --rm -it -v /tmp/a.cpp:/tmp/a.cpp -v 
/path/to/qemu-arm-static:/usr/bin/qemu-arm-static arm32v7/ubuntu:18.04 bash -c 
'{ apt update -y && apt install -y g++; } >& /dev/null && g++ -std=c++14 
/tmp/a.cpp -o /tmp/a.out && echo hehe > /tmp/haha.txt && /tmp/a.out'
  ofd=3
  ftruncate=0
  mmap=0xff3f5000
  fd=4
  0xff3f5023 -1 14

  The expected result in qemu-system-arm as well as natively on x86_64 host:
  hidden$ ./a.out
  ofd=3
  ftruncate=0
  mmap=0xb6fb7000
  fd=4
  0xb6fb7023 5 0

To manage notifications about this bug go to:
https://bugs.launchpad.net/qemu/+bug/1779955/+subscriptions

Reply via email to