qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [Bug 1805913] [NEW] readdir() returns NULL (errno=EOVERFLOW) for 32-bit user-static qemu on 64-bit host
@ 2018-11-30  0:06 Ke Liu
  2018-12-01 13:44 ` [Qemu-devel] [Bug 1805913] " Kan Li
                   ` (18 more replies)
  0 siblings, 19 replies; 21+ messages in thread
From: Ke Liu @ 2018-11-30  0:06 UTC (permalink / raw)
  To: qemu-devel

Public bug reported:

This can be simply reproduced by compiling and running the attached C
code (readdir-bug.c) under 32-bit user-static qemu, such as qemu-arm-
static:

# Setup docker for user-static binfmt
docker run --rm --privileged multiarch/qemu-user-static:register --reset
# Compile the code and run (readdir for / is fine, so create a new directory /test).
docker run -v /path/to/qemu-arm-static:/usr/bin/qemu-arm-static -v /path/to/readdir-bug.c:/tmp/readdir-bug.c -it --rm arm32v7/ubuntu:18.10 bash -c '{ apt update && apt install -y gcc; } >&/dev/null && mkdir -p /test && cd /test && gcc /tmp/readdir-bug.c && ./a.out'
dir=0xff5b4150
readdir(dir)=(nil)
errno=75: Value too large for defined data type

Do remember to replace the /path/to/qemu-arm-static and /path/to
/readdir-bug.c to the actual paths of the files.

The root cause is in glibc:
https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/getdents.c;h=6d09a5be7057e2792be9150d3a2c7b293cf6fc34;hb=a5275ba5378c9256d18e582572b4315e8edfcbfb#l87

By C standard, the return type of readdir() is DIR*, in which the inode
number and offset are 32-bit integers, therefore, glibc calls
getdents64() and check if the inode number and offset fits the 32-bit
range, and reports EOVERFLOW if not.

The problem here is for 32-bit user-static qemu running on 64-bit host,
getdents64 simply passing through the inode number and offset from
underlying getdents64 syscall (from 64-bit kernel), which is very likely
to not fit into 32-bit range. On real hardware, the 32-bit kernel
creates 32-bit inode numbers, therefore works properly.

The glibc code makes sense to do the check to be conformant with C
standard, therefore ideally it should be a fix on qemu side. I admit
this is difficult because qemu has to maintain a mapping between
underlying 64-bit inode numbers and 32-bit inode numbers, which would
severely hurt the performance. I don't expect this could be fix anytime
soon (or even there would be a fix), but it would be worthwhile to
surface this issue.

** Affects: qemu
     Importance: Undecided
         Status: New


** Tags: linux user-static

** Attachment added: "readdir-bug.c"
   https://bugs.launchpad.net/bugs/1805913/+attachment/5217520/+files/readdir-bug.c

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

Title:
  readdir() returns NULL (errno=EOVERFLOW) for 32-bit user-static qemu
  on 64-bit host

Status in QEMU:
  New

Bug description:
  This can be simply reproduced by compiling and running the attached C
  code (readdir-bug.c) under 32-bit user-static qemu, such as qemu-arm-
  static:

  # Setup docker for user-static binfmt
  docker run --rm --privileged multiarch/qemu-user-static:register --reset
  # Compile the code and run (readdir for / is fine, so create a new directory /test).
  docker run -v /path/to/qemu-arm-static:/usr/bin/qemu-arm-static -v /path/to/readdir-bug.c:/tmp/readdir-bug.c -it --rm arm32v7/ubuntu:18.10 bash -c '{ apt update && apt install -y gcc; } >&/dev/null && mkdir -p /test && cd /test && gcc /tmp/readdir-bug.c && ./a.out'
  dir=0xff5b4150
  readdir(dir)=(nil)
  errno=75: Value too large for defined data type

  Do remember to replace the /path/to/qemu-arm-static and /path/to
  /readdir-bug.c to the actual paths of the files.

  The root cause is in glibc:
  https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/getdents.c;h=6d09a5be7057e2792be9150d3a2c7b293cf6fc34;hb=a5275ba5378c9256d18e582572b4315e8edfcbfb#l87

  By C standard, the return type of readdir() is DIR*, in which the
  inode number and offset are 32-bit integers, therefore, glibc calls
  getdents64() and check if the inode number and offset fits the 32-bit
  range, and reports EOVERFLOW if not.

  The problem here is for 32-bit user-static qemu running on 64-bit
  host, getdents64 simply passing through the inode number and offset
  from underlying getdents64 syscall (from 64-bit kernel), which is very
  likely to not fit into 32-bit range. On real hardware, the 32-bit
  kernel creates 32-bit inode numbers, therefore works properly.

  The glibc code makes sense to do the check to be conformant with C
  standard, therefore ideally it should be a fix on qemu side. I admit
  this is difficult because qemu has to maintain a mapping between
  underlying 64-bit inode numbers and 32-bit inode numbers, which would
  severely hurt the performance. I don't expect this could be fix
  anytime soon (or even there would be a fix), but it would be
  worthwhile to surface this issue.

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

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [Qemu-devel] [Bug 1805913] Re: readdir() returns NULL (errno=EOVERFLOW) for 32-bit user-static qemu on 64-bit host
  2018-11-30  0:06 [Qemu-devel] [Bug 1805913] [NEW] readdir() returns NULL (errno=EOVERFLOW) for 32-bit user-static qemu on 64-bit host Ke Liu
@ 2018-12-01 13:44 ` Kan Li
  2018-12-05 11:15 ` Alex Bennée
                   ` (17 subsequent siblings)
  18 siblings, 0 replies; 21+ messages in thread
From: Kan Li @ 2018-12-01 13:44 UTC (permalink / raw)
  To: qemu-devel

More notes: this bug hits glibc-2.28 and later. It works on glibc-2.27.
Therefore to reproduce it it needs ubuntu 18.10 or later. Seems like it
works for 18.04.

This bug affects all Java programs that (implicitly) uses File.list() or
File.listFiles(). Also it makes dash not expanding wildcard
/some/directory/* . However, bash works because it uses glob() instead
of readdir().

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

Title:
  readdir() returns NULL (errno=EOVERFLOW) for 32-bit user-static qemu
  on 64-bit host

Status in QEMU:
  New

Bug description:
  This can be simply reproduced by compiling and running the attached C
  code (readdir-bug.c) under 32-bit user-static qemu, such as qemu-arm-
  static:

  # Setup docker for user-static binfmt
  docker run --rm --privileged multiarch/qemu-user-static:register --reset
  # Compile the code and run (readdir for / is fine, so create a new directory /test).
  docker run -v /path/to/qemu-arm-static:/usr/bin/qemu-arm-static -v /path/to/readdir-bug.c:/tmp/readdir-bug.c -it --rm arm32v7/ubuntu:18.10 bash -c '{ apt update && apt install -y gcc; } >&/dev/null && mkdir -p /test && cd /test && gcc /tmp/readdir-bug.c && ./a.out'
  dir=0xff5b4150
  readdir(dir)=(nil)
  errno=75: Value too large for defined data type

  Do remember to replace the /path/to/qemu-arm-static and /path/to
  /readdir-bug.c to the actual paths of the files.

  The root cause is in glibc:
  https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/getdents.c;h=6d09a5be7057e2792be9150d3a2c7b293cf6fc34;hb=a5275ba5378c9256d18e582572b4315e8edfcbfb#l87

  By C standard, the return type of readdir() is DIR*, in which the
  inode number and offset are 32-bit integers, therefore, glibc calls
  getdents64() and check if the inode number and offset fits the 32-bit
  range, and reports EOVERFLOW if not.

  The problem here is for 32-bit user-static qemu running on 64-bit
  host, getdents64 simply passing through the inode number and offset
  from underlying getdents64 syscall (from 64-bit kernel), which is very
  likely to not fit into 32-bit range. On real hardware, the 32-bit
  kernel creates 32-bit inode numbers, therefore works properly.

  The glibc code makes sense to do the check to be conformant with C
  standard, therefore ideally it should be a fix on qemu side. I admit
  this is difficult because qemu has to maintain a mapping between
  underlying 64-bit inode numbers and 32-bit inode numbers, which would
  severely hurt the performance. I don't expect this could be fix
  anytime soon (or even there would be a fix), but it would be
  worthwhile to surface this issue.

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

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [Qemu-devel] [Bug 1805913] Re: readdir() returns NULL (errno=EOVERFLOW) for 32-bit user-static qemu on 64-bit host
  2018-11-30  0:06 [Qemu-devel] [Bug 1805913] [NEW] readdir() returns NULL (errno=EOVERFLOW) for 32-bit user-static qemu on 64-bit host Ke Liu
  2018-12-01 13:44 ` [Qemu-devel] [Bug 1805913] " Kan Li
@ 2018-12-05 11:15 ` Alex Bennée
  2019-04-16 13:20 ` diddly
                   ` (16 subsequent siblings)
  18 siblings, 0 replies; 21+ messages in thread
From: Alex Bennée @ 2018-12-05 11:15 UTC (permalink / raw)
  To: qemu-devel

** Tags removed: linux user-static
** Tags added: linux-user

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

Title:
  readdir() returns NULL (errno=EOVERFLOW) for 32-bit user-static qemu
  on 64-bit host

Status in QEMU:
  New

Bug description:
  This can be simply reproduced by compiling and running the attached C
  code (readdir-bug.c) under 32-bit user-static qemu, such as qemu-arm-
  static:

  # Setup docker for user-static binfmt
  docker run --rm --privileged multiarch/qemu-user-static:register --reset
  # Compile the code and run (readdir for / is fine, so create a new directory /test).
  docker run -v /path/to/qemu-arm-static:/usr/bin/qemu-arm-static -v /path/to/readdir-bug.c:/tmp/readdir-bug.c -it --rm arm32v7/ubuntu:18.10 bash -c '{ apt update && apt install -y gcc; } >&/dev/null && mkdir -p /test && cd /test && gcc /tmp/readdir-bug.c && ./a.out'
  dir=0xff5b4150
  readdir(dir)=(nil)
  errno=75: Value too large for defined data type

  Do remember to replace the /path/to/qemu-arm-static and /path/to
  /readdir-bug.c to the actual paths of the files.

  The root cause is in glibc:
  https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/getdents.c;h=6d09a5be7057e2792be9150d3a2c7b293cf6fc34;hb=a5275ba5378c9256d18e582572b4315e8edfcbfb#l87

  By C standard, the return type of readdir() is DIR*, in which the
  inode number and offset are 32-bit integers, therefore, glibc calls
  getdents64() and check if the inode number and offset fits the 32-bit
  range, and reports EOVERFLOW if not.

  The problem here is for 32-bit user-static qemu running on 64-bit
  host, getdents64 simply passing through the inode number and offset
  from underlying getdents64 syscall (from 64-bit kernel), which is very
  likely to not fit into 32-bit range. On real hardware, the 32-bit
  kernel creates 32-bit inode numbers, therefore works properly.

  The glibc code makes sense to do the check to be conformant with C
  standard, therefore ideally it should be a fix on qemu side. I admit
  this is difficult because qemu has to maintain a mapping between
  underlying 64-bit inode numbers and 32-bit inode numbers, which would
  severely hurt the performance. I don't expect this could be fix
  anytime soon (or even there would be a fix), but it would be
  worthwhile to surface this issue.

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

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [Qemu-devel] [Bug 1805913] Re: readdir() returns NULL (errno=EOVERFLOW) for 32-bit user-static qemu on 64-bit host
  2018-11-30  0:06 [Qemu-devel] [Bug 1805913] [NEW] readdir() returns NULL (errno=EOVERFLOW) for 32-bit user-static qemu on 64-bit host Ke Liu
  2018-12-01 13:44 ` [Qemu-devel] [Bug 1805913] " Kan Li
  2018-12-05 11:15 ` Alex Bennée
@ 2019-04-16 13:20 ` diddly
  2019-04-16 13:20   ` diddly
  2019-07-16 14:46 ` Alex Bennée
                   ` (15 subsequent siblings)
  18 siblings, 1 reply; 21+ messages in thread
From: diddly @ 2019-04-16 13:20 UTC (permalink / raw)
  To: qemu-devel

https://lkml.org/lkml/2018/12/27/155

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

Title:
  readdir() returns NULL (errno=EOVERFLOW) for 32-bit user-static qemu
  on 64-bit host

Status in QEMU:
  New

Bug description:
  This can be simply reproduced by compiling and running the attached C
  code (readdir-bug.c) under 32-bit user-static qemu, such as qemu-arm-
  static:

  # Setup docker for user-static binfmt
  docker run --rm --privileged multiarch/qemu-user-static:register --reset
  # Compile the code and run (readdir for / is fine, so create a new directory /test).
  docker run -v /path/to/qemu-arm-static:/usr/bin/qemu-arm-static -v /path/to/readdir-bug.c:/tmp/readdir-bug.c -it --rm arm32v7/ubuntu:18.10 bash -c '{ apt update && apt install -y gcc; } >&/dev/null && mkdir -p /test && cd /test && gcc /tmp/readdir-bug.c && ./a.out'
  dir=0xff5b4150
  readdir(dir)=(nil)
  errno=75: Value too large for defined data type

  Do remember to replace the /path/to/qemu-arm-static and /path/to
  /readdir-bug.c to the actual paths of the files.

  The root cause is in glibc:
  https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/getdents.c;h=6d09a5be7057e2792be9150d3a2c7b293cf6fc34;hb=a5275ba5378c9256d18e582572b4315e8edfcbfb#l87

  By C standard, the return type of readdir() is DIR*, in which the
  inode number and offset are 32-bit integers, therefore, glibc calls
  getdents64() and check if the inode number and offset fits the 32-bit
  range, and reports EOVERFLOW if not.

  The problem here is for 32-bit user-static qemu running on 64-bit
  host, getdents64 simply passing through the inode number and offset
  from underlying getdents64 syscall (from 64-bit kernel), which is very
  likely to not fit into 32-bit range. On real hardware, the 32-bit
  kernel creates 32-bit inode numbers, therefore works properly.

  The glibc code makes sense to do the check to be conformant with C
  standard, therefore ideally it should be a fix on qemu side. I admit
  this is difficult because qemu has to maintain a mapping between
  underlying 64-bit inode numbers and 32-bit inode numbers, which would
  severely hurt the performance. I don't expect this could be fix
  anytime soon (or even there would be a fix), but it would be
  worthwhile to surface this issue.

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

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [Qemu-devel] [Bug 1805913] Re: readdir() returns NULL (errno=EOVERFLOW) for 32-bit user-static qemu on 64-bit host
  2019-04-16 13:20 ` diddly
@ 2019-04-16 13:20   ` diddly
  0 siblings, 0 replies; 21+ messages in thread
From: diddly @ 2019-04-16 13:20 UTC (permalink / raw)
  To: qemu-devel

https://lkml.org/lkml/2018/12/27/155

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

Title:
  readdir() returns NULL (errno=EOVERFLOW) for 32-bit user-static qemu
  on 64-bit host

Status in QEMU:
  New

Bug description:
  This can be simply reproduced by compiling and running the attached C
  code (readdir-bug.c) under 32-bit user-static qemu, such as qemu-arm-
  static:

  # Setup docker for user-static binfmt
  docker run --rm --privileged multiarch/qemu-user-static:register --reset
  # Compile the code and run (readdir for / is fine, so create a new directory /test).
  docker run -v /path/to/qemu-arm-static:/usr/bin/qemu-arm-static -v /path/to/readdir-bug.c:/tmp/readdir-bug.c -it --rm arm32v7/ubuntu:18.10 bash -c '{ apt update && apt install -y gcc; } >&/dev/null && mkdir -p /test && cd /test && gcc /tmp/readdir-bug.c && ./a.out'
  dir=0xff5b4150
  readdir(dir)=(nil)
  errno=75: Value too large for defined data type

  Do remember to replace the /path/to/qemu-arm-static and /path/to
  /readdir-bug.c to the actual paths of the files.

  The root cause is in glibc:
  https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/getdents.c;h=6d09a5be7057e2792be9150d3a2c7b293cf6fc34;hb=a5275ba5378c9256d18e582572b4315e8edfcbfb#l87

  By C standard, the return type of readdir() is DIR*, in which the
  inode number and offset are 32-bit integers, therefore, glibc calls
  getdents64() and check if the inode number and offset fits the 32-bit
  range, and reports EOVERFLOW if not.

  The problem here is for 32-bit user-static qemu running on 64-bit
  host, getdents64 simply passing through the inode number and offset
  from underlying getdents64 syscall (from 64-bit kernel), which is very
  likely to not fit into 32-bit range. On real hardware, the 32-bit
  kernel creates 32-bit inode numbers, therefore works properly.

  The glibc code makes sense to do the check to be conformant with C
  standard, therefore ideally it should be a fix on qemu side. I admit
  this is difficult because qemu has to maintain a mapping between
  underlying 64-bit inode numbers and 32-bit inode numbers, which would
  severely hurt the performance. I don't expect this could be fix
  anytime soon (or even there would be a fix), but it would be
  worthwhile to surface this issue.

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


^ permalink raw reply	[flat|nested] 21+ messages in thread

* [Qemu-devel] [Bug 1805913] Re: readdir() returns NULL (errno=EOVERFLOW) for 32-bit user-static qemu on 64-bit host
  2018-11-30  0:06 [Qemu-devel] [Bug 1805913] [NEW] readdir() returns NULL (errno=EOVERFLOW) for 32-bit user-static qemu on 64-bit host Ke Liu
                   ` (2 preceding siblings ...)
  2019-04-16 13:20 ` diddly
@ 2019-07-16 14:46 ` Alex Bennée
  2019-08-01 13:00 ` diddly
                   ` (14 subsequent siblings)
  18 siblings, 0 replies; 21+ messages in thread
From: Alex Bennée @ 2019-07-16 14:46 UTC (permalink / raw)
  To: qemu-devel

** Tags added: syscall-abi

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

Title:
  readdir() returns NULL (errno=EOVERFLOW) for 32-bit user-static qemu
  on 64-bit host

Status in QEMU:
  New

Bug description:
  This can be simply reproduced by compiling and running the attached C
  code (readdir-bug.c) under 32-bit user-static qemu, such as qemu-arm-
  static:

  # Setup docker for user-static binfmt
  docker run --rm --privileged multiarch/qemu-user-static:register --reset
  # Compile the code and run (readdir for / is fine, so create a new directory /test).
  docker run -v /path/to/qemu-arm-static:/usr/bin/qemu-arm-static -v /path/to/readdir-bug.c:/tmp/readdir-bug.c -it --rm arm32v7/ubuntu:18.10 bash -c '{ apt update && apt install -y gcc; } >&/dev/null && mkdir -p /test && cd /test && gcc /tmp/readdir-bug.c && ./a.out'
  dir=0xff5b4150
  readdir(dir)=(nil)
  errno=75: Value too large for defined data type

  Do remember to replace the /path/to/qemu-arm-static and /path/to
  /readdir-bug.c to the actual paths of the files.

  The root cause is in glibc:
  https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/getdents.c;h=6d09a5be7057e2792be9150d3a2c7b293cf6fc34;hb=a5275ba5378c9256d18e582572b4315e8edfcbfb#l87

  By C standard, the return type of readdir() is DIR*, in which the
  inode number and offset are 32-bit integers, therefore, glibc calls
  getdents64() and check if the inode number and offset fits the 32-bit
  range, and reports EOVERFLOW if not.

  The problem here is for 32-bit user-static qemu running on 64-bit
  host, getdents64 simply passing through the inode number and offset
  from underlying getdents64 syscall (from 64-bit kernel), which is very
  likely to not fit into 32-bit range. On real hardware, the 32-bit
  kernel creates 32-bit inode numbers, therefore works properly.

  The glibc code makes sense to do the check to be conformant with C
  standard, therefore ideally it should be a fix on qemu side. I admit
  this is difficult because qemu has to maintain a mapping between
  underlying 64-bit inode numbers and 32-bit inode numbers, which would
  severely hurt the performance. I don't expect this could be fix
  anytime soon (or even there would be a fix), but it would be
  worthwhile to surface this issue.

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


^ permalink raw reply	[flat|nested] 21+ messages in thread

* [Qemu-devel] [Bug 1805913] Re: readdir() returns NULL (errno=EOVERFLOW) for 32-bit user-static qemu on 64-bit host
  2018-11-30  0:06 [Qemu-devel] [Bug 1805913] [NEW] readdir() returns NULL (errno=EOVERFLOW) for 32-bit user-static qemu on 64-bit host Ke Liu
                   ` (3 preceding siblings ...)
  2019-07-16 14:46 ` Alex Bennée
@ 2019-08-01 13:00 ` diddly
  2019-08-01 13:32 ` Peter Maydell
                   ` (13 subsequent siblings)
  18 siblings, 0 replies; 21+ messages in thread
From: diddly @ 2019-08-01 13:00 UTC (permalink / raw)
  To: qemu-devel

After studying linux-user/syscall.c a bit, would it be possible to work
around this issue by doing something like the following:

Add a new #define EMULATE_GETDENTS64_WITH_GETDENTS, and enable this iff
we have getdents, and the target is 32, while the host is 64 bits.
Something similar, but complementary is done with
EMULATE_GETDENTS_WITH_GETDENTS64.

In that case, when userspace calls getdents64, we implement a
"conversion" (similar to getdents #if logic), which calls the host's
getdents and converts the data structures back to their 64-bit variants
before handing back to user-space.

I'm likely over-simplifying a problem that I don't fully understand, but
would happily work on a patch if someone higher up the food chain could
fill in the gaps.

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

Title:
  readdir() returns NULL (errno=EOVERFLOW) for 32-bit user-static qemu
  on 64-bit host

Status in QEMU:
  New

Bug description:
  This can be simply reproduced by compiling and running the attached C
  code (readdir-bug.c) under 32-bit user-static qemu, such as qemu-arm-
  static:

  # Setup docker for user-static binfmt
  docker run --rm --privileged multiarch/qemu-user-static:register --reset
  # Compile the code and run (readdir for / is fine, so create a new directory /test).
  docker run -v /path/to/qemu-arm-static:/usr/bin/qemu-arm-static -v /path/to/readdir-bug.c:/tmp/readdir-bug.c -it --rm arm32v7/ubuntu:18.10 bash -c '{ apt update && apt install -y gcc; } >&/dev/null && mkdir -p /test && cd /test && gcc /tmp/readdir-bug.c && ./a.out'
  dir=0xff5b4150
  readdir(dir)=(nil)
  errno=75: Value too large for defined data type

  Do remember to replace the /path/to/qemu-arm-static and /path/to
  /readdir-bug.c to the actual paths of the files.

  The root cause is in glibc:
  https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/getdents.c;h=6d09a5be7057e2792be9150d3a2c7b293cf6fc34;hb=a5275ba5378c9256d18e582572b4315e8edfcbfb#l87

  By C standard, the return type of readdir() is DIR*, in which the
  inode number and offset are 32-bit integers, therefore, glibc calls
  getdents64() and check if the inode number and offset fits the 32-bit
  range, and reports EOVERFLOW if not.

  The problem here is for 32-bit user-static qemu running on 64-bit
  host, getdents64 simply passing through the inode number and offset
  from underlying getdents64 syscall (from 64-bit kernel), which is very
  likely to not fit into 32-bit range. On real hardware, the 32-bit
  kernel creates 32-bit inode numbers, therefore works properly.

  The glibc code makes sense to do the check to be conformant with C
  standard, therefore ideally it should be a fix on qemu side. I admit
  this is difficult because qemu has to maintain a mapping between
  underlying 64-bit inode numbers and 32-bit inode numbers, which would
  severely hurt the performance. I don't expect this could be fix
  anytime soon (or even there would be a fix), but it would be
  worthwhile to surface this issue.

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


^ permalink raw reply	[flat|nested] 21+ messages in thread

* [Qemu-devel] [Bug 1805913] Re: readdir() returns NULL (errno=EOVERFLOW) for 32-bit user-static qemu on 64-bit host
  2018-11-30  0:06 [Qemu-devel] [Bug 1805913] [NEW] readdir() returns NULL (errno=EOVERFLOW) for 32-bit user-static qemu on 64-bit host Ke Liu
                   ` (4 preceding siblings ...)
  2019-08-01 13:00 ` diddly
@ 2019-08-01 13:32 ` Peter Maydell
  2020-01-30  8:19 ` Philippe Vaucher
                   ` (12 subsequent siblings)
  18 siblings, 0 replies; 21+ messages in thread
From: Peter Maydell @ 2019-08-01 13:32 UTC (permalink / raw)
  To: qemu-devel

Unfortunately there is no kernel API which we can use on the host to say
"give me inodes and offsets which will fit into a 32 bit field". The
'getdents' syscall uses the "unsigned long" type for the d_ino and d_off
fields, so on a 64-bit host these will be the same size as the ino64_t
and off64_t used by 'getdents64', and you will still have the "trying to
fit a quart into a pint pot" problem.

The only way to fix this is to fix the host kernel to provide the API
QEMU needs for this (see discussion in the kernel thread linked to in
comment #5).

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

Title:
  readdir() returns NULL (errno=EOVERFLOW) for 32-bit user-static qemu
  on 64-bit host

Status in QEMU:
  New

Bug description:
  This can be simply reproduced by compiling and running the attached C
  code (readdir-bug.c) under 32-bit user-static qemu, such as qemu-arm-
  static:

  # Setup docker for user-static binfmt
  docker run --rm --privileged multiarch/qemu-user-static:register --reset
  # Compile the code and run (readdir for / is fine, so create a new directory /test).
  docker run -v /path/to/qemu-arm-static:/usr/bin/qemu-arm-static -v /path/to/readdir-bug.c:/tmp/readdir-bug.c -it --rm arm32v7/ubuntu:18.10 bash -c '{ apt update && apt install -y gcc; } >&/dev/null && mkdir -p /test && cd /test && gcc /tmp/readdir-bug.c && ./a.out'
  dir=0xff5b4150
  readdir(dir)=(nil)
  errno=75: Value too large for defined data type

  Do remember to replace the /path/to/qemu-arm-static and /path/to
  /readdir-bug.c to the actual paths of the files.

  The root cause is in glibc:
  https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/getdents.c;h=6d09a5be7057e2792be9150d3a2c7b293cf6fc34;hb=a5275ba5378c9256d18e582572b4315e8edfcbfb#l87

  By C standard, the return type of readdir() is DIR*, in which the
  inode number and offset are 32-bit integers, therefore, glibc calls
  getdents64() and check if the inode number and offset fits the 32-bit
  range, and reports EOVERFLOW if not.

  The problem here is for 32-bit user-static qemu running on 64-bit
  host, getdents64 simply passing through the inode number and offset
  from underlying getdents64 syscall (from 64-bit kernel), which is very
  likely to not fit into 32-bit range. On real hardware, the 32-bit
  kernel creates 32-bit inode numbers, therefore works properly.

  The glibc code makes sense to do the check to be conformant with C
  standard, therefore ideally it should be a fix on qemu side. I admit
  this is difficult because qemu has to maintain a mapping between
  underlying 64-bit inode numbers and 32-bit inode numbers, which would
  severely hurt the performance. I don't expect this could be fix
  anytime soon (or even there would be a fix), but it would be
  worthwhile to surface this issue.

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


^ permalink raw reply	[flat|nested] 21+ messages in thread

* [Bug 1805913] Re: readdir() returns NULL (errno=EOVERFLOW) for 32-bit user-static qemu on 64-bit host
  2018-11-30  0:06 [Qemu-devel] [Bug 1805913] [NEW] readdir() returns NULL (errno=EOVERFLOW) for 32-bit user-static qemu on 64-bit host Ke Liu
                   ` (5 preceding siblings ...)
  2019-08-01 13:32 ` Peter Maydell
@ 2020-01-30  8:19 ` Philippe Vaucher
  2020-01-30  8:20 ` Philippe Vaucher
                   ` (11 subsequent siblings)
  18 siblings, 0 replies; 21+ messages in thread
From: Philippe Vaucher @ 2020-01-30  8:19 UTC (permalink / raw)
  To: qemu-devel

Is there a workaround for this? I tried:

- Building on an XFS partition.
- Building from ubuntu:16.04 so the host has glib <2.27.

It looks like the only way is to have the chroot with glib <2.27, and in
alpine images glib is at minimum 2.56.

If the bug is fixed in glib maybe I can install glib from master? I'm
trying to build multi-arch docker images and this bug is what prevents
me from providing arm/v7 images for the raspberry pi.

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

Title:
  readdir() returns NULL (errno=EOVERFLOW) for 32-bit user-static qemu
  on 64-bit host

Status in QEMU:
  New

Bug description:
  This can be simply reproduced by compiling and running the attached C
  code (readdir-bug.c) under 32-bit user-static qemu, such as qemu-arm-
  static:

  # Setup docker for user-static binfmt
  docker run --rm --privileged multiarch/qemu-user-static:register --reset
  # Compile the code and run (readdir for / is fine, so create a new directory /test).
  docker run -v /path/to/qemu-arm-static:/usr/bin/qemu-arm-static -v /path/to/readdir-bug.c:/tmp/readdir-bug.c -it --rm arm32v7/ubuntu:18.10 bash -c '{ apt update && apt install -y gcc; } >&/dev/null && mkdir -p /test && cd /test && gcc /tmp/readdir-bug.c && ./a.out'
  dir=0xff5b4150
  readdir(dir)=(nil)
  errno=75: Value too large for defined data type

  Do remember to replace the /path/to/qemu-arm-static and /path/to
  /readdir-bug.c to the actual paths of the files.

  The root cause is in glibc:
  https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/getdents.c;h=6d09a5be7057e2792be9150d3a2c7b293cf6fc34;hb=a5275ba5378c9256d18e582572b4315e8edfcbfb#l87

  By C standard, the return type of readdir() is DIR*, in which the
  inode number and offset are 32-bit integers, therefore, glibc calls
  getdents64() and check if the inode number and offset fits the 32-bit
  range, and reports EOVERFLOW if not.

  The problem here is for 32-bit user-static qemu running on 64-bit
  host, getdents64 simply passing through the inode number and offset
  from underlying getdents64 syscall (from 64-bit kernel), which is very
  likely to not fit into 32-bit range. On real hardware, the 32-bit
  kernel creates 32-bit inode numbers, therefore works properly.

  The glibc code makes sense to do the check to be conformant with C
  standard, therefore ideally it should be a fix on qemu side. I admit
  this is difficult because qemu has to maintain a mapping between
  underlying 64-bit inode numbers and 32-bit inode numbers, which would
  severely hurt the performance. I don't expect this could be fix
  anytime soon (or even there would be a fix), but it would be
  worthwhile to surface this issue.

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


^ permalink raw reply	[flat|nested] 21+ messages in thread

* [Bug 1805913] Re: readdir() returns NULL (errno=EOVERFLOW) for 32-bit user-static qemu on 64-bit host
  2018-11-30  0:06 [Qemu-devel] [Bug 1805913] [NEW] readdir() returns NULL (errno=EOVERFLOW) for 32-bit user-static qemu on 64-bit host Ke Liu
                   ` (6 preceding siblings ...)
  2020-01-30  8:19 ` Philippe Vaucher
@ 2020-01-30  8:20 ` Philippe Vaucher
  2020-01-30 10:47 ` diddly
                   ` (10 subsequent siblings)
  18 siblings, 0 replies; 21+ messages in thread
From: Philippe Vaucher @ 2020-01-30  8:20 UTC (permalink / raw)
  To: qemu-devel

Sorry, meant `< 2.28` above.

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

Title:
  readdir() returns NULL (errno=EOVERFLOW) for 32-bit user-static qemu
  on 64-bit host

Status in QEMU:
  New

Bug description:
  This can be simply reproduced by compiling and running the attached C
  code (readdir-bug.c) under 32-bit user-static qemu, such as qemu-arm-
  static:

  # Setup docker for user-static binfmt
  docker run --rm --privileged multiarch/qemu-user-static:register --reset
  # Compile the code and run (readdir for / is fine, so create a new directory /test).
  docker run -v /path/to/qemu-arm-static:/usr/bin/qemu-arm-static -v /path/to/readdir-bug.c:/tmp/readdir-bug.c -it --rm arm32v7/ubuntu:18.10 bash -c '{ apt update && apt install -y gcc; } >&/dev/null && mkdir -p /test && cd /test && gcc /tmp/readdir-bug.c && ./a.out'
  dir=0xff5b4150
  readdir(dir)=(nil)
  errno=75: Value too large for defined data type

  Do remember to replace the /path/to/qemu-arm-static and /path/to
  /readdir-bug.c to the actual paths of the files.

  The root cause is in glibc:
  https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/getdents.c;h=6d09a5be7057e2792be9150d3a2c7b293cf6fc34;hb=a5275ba5378c9256d18e582572b4315e8edfcbfb#l87

  By C standard, the return type of readdir() is DIR*, in which the
  inode number and offset are 32-bit integers, therefore, glibc calls
  getdents64() and check if the inode number and offset fits the 32-bit
  range, and reports EOVERFLOW if not.

  The problem here is for 32-bit user-static qemu running on 64-bit
  host, getdents64 simply passing through the inode number and offset
  from underlying getdents64 syscall (from 64-bit kernel), which is very
  likely to not fit into 32-bit range. On real hardware, the 32-bit
  kernel creates 32-bit inode numbers, therefore works properly.

  The glibc code makes sense to do the check to be conformant with C
  standard, therefore ideally it should be a fix on qemu side. I admit
  this is difficult because qemu has to maintain a mapping between
  underlying 64-bit inode numbers and 32-bit inode numbers, which would
  severely hurt the performance. I don't expect this could be fix
  anytime soon (or even there would be a fix), but it would be
  worthwhile to surface this issue.

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


^ permalink raw reply	[flat|nested] 21+ messages in thread

* [Bug 1805913] Re: readdir() returns NULL (errno=EOVERFLOW) for 32-bit user-static qemu on 64-bit host
  2018-11-30  0:06 [Qemu-devel] [Bug 1805913] [NEW] readdir() returns NULL (errno=EOVERFLOW) for 32-bit user-static qemu on 64-bit host Ke Liu
                   ` (7 preceding siblings ...)
  2020-01-30  8:20 ` Philippe Vaucher
@ 2020-01-30 10:47 ` diddly
  2020-02-02 20:11 ` Philippe Vaucher
                   ` (9 subsequent siblings)
  18 siblings, 0 replies; 21+ messages in thread
From: diddly @ 2020-01-30 10:47 UTC (permalink / raw)
  To: qemu-devel

There has been some motion on this by Aladjev Andrew.  I will butcher
the explanation of his approach if I try, but it is described in the
following bugs.  I have no idea of the schedule, or even possibility of
adoption; it seems to still be in proof-of-concept phase.

GLIBC bug (see last several posts)
https://sourceware.org/bugzilla/show_bug.cgi?id=23960

Kernel bugzilla (last two posts)
https://bugzilla.kernel.org/show_bug.cgi?id=205957

** Bug watch added: Sourceware.org Bugzilla #23960
   https://sourceware.org/bugzilla/show_bug.cgi?id=23960

** Bug watch added: Linux Kernel Bug Tracker #205957
   https://bugzilla.kernel.org/show_bug.cgi?id=205957

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

Title:
  readdir() returns NULL (errno=EOVERFLOW) for 32-bit user-static qemu
  on 64-bit host

Status in QEMU:
  New

Bug description:
  This can be simply reproduced by compiling and running the attached C
  code (readdir-bug.c) under 32-bit user-static qemu, such as qemu-arm-
  static:

  # Setup docker for user-static binfmt
  docker run --rm --privileged multiarch/qemu-user-static:register --reset
  # Compile the code and run (readdir for / is fine, so create a new directory /test).
  docker run -v /path/to/qemu-arm-static:/usr/bin/qemu-arm-static -v /path/to/readdir-bug.c:/tmp/readdir-bug.c -it --rm arm32v7/ubuntu:18.10 bash -c '{ apt update && apt install -y gcc; } >&/dev/null && mkdir -p /test && cd /test && gcc /tmp/readdir-bug.c && ./a.out'
  dir=0xff5b4150
  readdir(dir)=(nil)
  errno=75: Value too large for defined data type

  Do remember to replace the /path/to/qemu-arm-static and /path/to
  /readdir-bug.c to the actual paths of the files.

  The root cause is in glibc:
  https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/getdents.c;h=6d09a5be7057e2792be9150d3a2c7b293cf6fc34;hb=a5275ba5378c9256d18e582572b4315e8edfcbfb#l87

  By C standard, the return type of readdir() is DIR*, in which the
  inode number and offset are 32-bit integers, therefore, glibc calls
  getdents64() and check if the inode number and offset fits the 32-bit
  range, and reports EOVERFLOW if not.

  The problem here is for 32-bit user-static qemu running on 64-bit
  host, getdents64 simply passing through the inode number and offset
  from underlying getdents64 syscall (from 64-bit kernel), which is very
  likely to not fit into 32-bit range. On real hardware, the 32-bit
  kernel creates 32-bit inode numbers, therefore works properly.

  The glibc code makes sense to do the check to be conformant with C
  standard, therefore ideally it should be a fix on qemu side. I admit
  this is difficult because qemu has to maintain a mapping between
  underlying 64-bit inode numbers and 32-bit inode numbers, which would
  severely hurt the performance. I don't expect this could be fix
  anytime soon (or even there would be a fix), but it would be
  worthwhile to surface this issue.

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


^ permalink raw reply	[flat|nested] 21+ messages in thread

* [Bug 1805913] Re: readdir() returns NULL (errno=EOVERFLOW) for 32-bit user-static qemu on 64-bit host
  2018-11-30  0:06 [Qemu-devel] [Bug 1805913] [NEW] readdir() returns NULL (errno=EOVERFLOW) for 32-bit user-static qemu on 64-bit host Ke Liu
                   ` (8 preceding siblings ...)
  2020-01-30 10:47 ` diddly
@ 2020-02-02 20:11 ` Philippe Vaucher
  2020-02-02 21:01 ` Marcin Konarski
                   ` (8 subsequent siblings)
  18 siblings, 0 replies; 21+ messages in thread
From: Philippe Vaucher @ 2020-02-02 20:11 UTC (permalink / raw)
  To: qemu-devel

Ah, great thanks. It looks like there are patches that fix qemu,
although the setup looks a bit complex. I'll report if I get something
going.

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

Title:
  readdir() returns NULL (errno=EOVERFLOW) for 32-bit user-static qemu
  on 64-bit host

Status in QEMU:
  New

Bug description:
  This can be simply reproduced by compiling and running the attached C
  code (readdir-bug.c) under 32-bit user-static qemu, such as qemu-arm-
  static:

  # Setup docker for user-static binfmt
  docker run --rm --privileged multiarch/qemu-user-static:register --reset
  # Compile the code and run (readdir for / is fine, so create a new directory /test).
  docker run -v /path/to/qemu-arm-static:/usr/bin/qemu-arm-static -v /path/to/readdir-bug.c:/tmp/readdir-bug.c -it --rm arm32v7/ubuntu:18.10 bash -c '{ apt update && apt install -y gcc; } >&/dev/null && mkdir -p /test && cd /test && gcc /tmp/readdir-bug.c && ./a.out'
  dir=0xff5b4150
  readdir(dir)=(nil)
  errno=75: Value too large for defined data type

  Do remember to replace the /path/to/qemu-arm-static and /path/to
  /readdir-bug.c to the actual paths of the files.

  The root cause is in glibc:
  https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/getdents.c;h=6d09a5be7057e2792be9150d3a2c7b293cf6fc34;hb=a5275ba5378c9256d18e582572b4315e8edfcbfb#l87

  By C standard, the return type of readdir() is DIR*, in which the
  inode number and offset are 32-bit integers, therefore, glibc calls
  getdents64() and check if the inode number and offset fits the 32-bit
  range, and reports EOVERFLOW if not.

  The problem here is for 32-bit user-static qemu running on 64-bit
  host, getdents64 simply passing through the inode number and offset
  from underlying getdents64 syscall (from 64-bit kernel), which is very
  likely to not fit into 32-bit range. On real hardware, the 32-bit
  kernel creates 32-bit inode numbers, therefore works properly.

  The glibc code makes sense to do the check to be conformant with C
  standard, therefore ideally it should be a fix on qemu side. I admit
  this is difficult because qemu has to maintain a mapping between
  underlying 64-bit inode numbers and 32-bit inode numbers, which would
  severely hurt the performance. I don't expect this could be fix
  anytime soon (or even there would be a fix), but it would be
  worthwhile to surface this issue.

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


^ permalink raw reply	[flat|nested] 21+ messages in thread

* [Bug 1805913] Re: readdir() returns NULL (errno=EOVERFLOW) for 32-bit user-static qemu on 64-bit host
  2018-11-30  0:06 [Qemu-devel] [Bug 1805913] [NEW] readdir() returns NULL (errno=EOVERFLOW) for 32-bit user-static qemu on 64-bit host Ke Liu
                   ` (9 preceding siblings ...)
  2020-02-02 20:11 ` Philippe Vaucher
@ 2020-02-02 21:01 ` Marcin Konarski
  2020-02-06 13:34 ` Philippe Vaucher
                   ` (7 subsequent siblings)
  18 siblings, 0 replies; 21+ messages in thread
From: Marcin Konarski @ 2020-02-02 21:01 UTC (permalink / raw)
  To: qemu-devel

This problem affected my virtual environment which I used (via qemu-
static) to build my project for RaspberryPI platform. After I upgraded
my virtual Raspbian to buster release `readdir` stopped working (as
described in this thread) due to mapping of 64 inode numbers to qemu
32bit ARM land. I needed this builder working and I found a workaround
in some obscure (2nd page of google result) blog.

Before the work around my virtual Raspbian was just a directory on one
of my ext4 partitions. To fix the issue I created image file with dd,
formatted with mkfs.ext4 it with `dir_index` option disabled and moved
my virual Raspbian onto that newly created filesystem. This fixed the
issue for me and my builder started again.

I am posting it here so `dir_index` trick can be easier to found for
others in this situation.

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

Title:
  readdir() returns NULL (errno=EOVERFLOW) for 32-bit user-static qemu
  on 64-bit host

Status in QEMU:
  New

Bug description:
  This can be simply reproduced by compiling and running the attached C
  code (readdir-bug.c) under 32-bit user-static qemu, such as qemu-arm-
  static:

  # Setup docker for user-static binfmt
  docker run --rm --privileged multiarch/qemu-user-static:register --reset
  # Compile the code and run (readdir for / is fine, so create a new directory /test).
  docker run -v /path/to/qemu-arm-static:/usr/bin/qemu-arm-static -v /path/to/readdir-bug.c:/tmp/readdir-bug.c -it --rm arm32v7/ubuntu:18.10 bash -c '{ apt update && apt install -y gcc; } >&/dev/null && mkdir -p /test && cd /test && gcc /tmp/readdir-bug.c && ./a.out'
  dir=0xff5b4150
  readdir(dir)=(nil)
  errno=75: Value too large for defined data type

  Do remember to replace the /path/to/qemu-arm-static and /path/to
  /readdir-bug.c to the actual paths of the files.

  The root cause is in glibc:
  https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/getdents.c;h=6d09a5be7057e2792be9150d3a2c7b293cf6fc34;hb=a5275ba5378c9256d18e582572b4315e8edfcbfb#l87

  By C standard, the return type of readdir() is DIR*, in which the
  inode number and offset are 32-bit integers, therefore, glibc calls
  getdents64() and check if the inode number and offset fits the 32-bit
  range, and reports EOVERFLOW if not.

  The problem here is for 32-bit user-static qemu running on 64-bit
  host, getdents64 simply passing through the inode number and offset
  from underlying getdents64 syscall (from 64-bit kernel), which is very
  likely to not fit into 32-bit range. On real hardware, the 32-bit
  kernel creates 32-bit inode numbers, therefore works properly.

  The glibc code makes sense to do the check to be conformant with C
  standard, therefore ideally it should be a fix on qemu side. I admit
  this is difficult because qemu has to maintain a mapping between
  underlying 64-bit inode numbers and 32-bit inode numbers, which would
  severely hurt the performance. I don't expect this could be fix
  anytime soon (or even there would be a fix), but it would be
  worthwhile to surface this issue.

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


^ permalink raw reply	[flat|nested] 21+ messages in thread

* [Bug 1805913] Re: readdir() returns NULL (errno=EOVERFLOW) for 32-bit user-static qemu on 64-bit host
  2018-11-30  0:06 [Qemu-devel] [Bug 1805913] [NEW] readdir() returns NULL (errno=EOVERFLOW) for 32-bit user-static qemu on 64-bit host Ke Liu
                   ` (10 preceding siblings ...)
  2020-02-02 21:01 ` Marcin Konarski
@ 2020-02-06 13:34 ` Philippe Vaucher
  2020-03-26 20:16 ` Peter Maydell
                   ` (6 subsequent siblings)
  18 siblings, 0 replies; 21+ messages in thread
From: Philippe Vaucher @ 2020-02-06 13:34 UTC (permalink / raw)
  To: qemu-devel

Thanks Marcin. I tested your solution but by me it still gets stuck at
the same point. Here's what I did:

$ tune2fs -O ^dir_index /dev/sda1
$ tune2fs -l /dev/sda1
tune2fs 1.44.2 (14-May-2018)
Filesystem volume name:   <none>
Last mounted on:          /
Filesystem UUID:          c8fee0cb-a610-4fa5-aab8-c5c765678133
Filesystem magic number:  0xEF53
Filesystem revision #:    1 (dynamic)
Filesystem features:      has_journal ext_attr resize_inode filetype needs_recovery extent 64bit flex_bg sparse_super large_file huge_file dir_nlink extra_isize metadata_csum
Filesystem flags:         signed_directory_hash 
Default mount options:    user_xattr acl
Filesystem state:         clean
(snip)

But then my build still get stuck on:

clock_gettime(CLOCK_REALTIME, {tv_sec=1580996038, tv_nsec=781126598}) = 0
getdents64(5, /* 0 entries */, 2048)    = 0
lseek(5, 0, SEEK_SET)                   = 0
getdents64(5, /* 5 entries */, 2048)    = 144
tgkill(29974, 29977, SIGRT_2)           = -1 EAGAIN (Resource temporarily unavailable)
clock_gettime(CLOCK_REALTIME, {tv_sec=1580996038, tv_nsec=781461434}) = 0
getdents64(5, /* 0 entries */, 2048)    = 0
lseek(5, 0, SEEK_SET)                   = 0
getdents64(5, /* 5 entries */, 2048)    = 144
tgkill(29974, 29977, SIGRT_2)           = -1 EAGAIN (Resource temporarily unavailable

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

Title:
  readdir() returns NULL (errno=EOVERFLOW) for 32-bit user-static qemu
  on 64-bit host

Status in QEMU:
  New

Bug description:
  This can be simply reproduced by compiling and running the attached C
  code (readdir-bug.c) under 32-bit user-static qemu, such as qemu-arm-
  static:

  # Setup docker for user-static binfmt
  docker run --rm --privileged multiarch/qemu-user-static:register --reset
  # Compile the code and run (readdir for / is fine, so create a new directory /test).
  docker run -v /path/to/qemu-arm-static:/usr/bin/qemu-arm-static -v /path/to/readdir-bug.c:/tmp/readdir-bug.c -it --rm arm32v7/ubuntu:18.10 bash -c '{ apt update && apt install -y gcc; } >&/dev/null && mkdir -p /test && cd /test && gcc /tmp/readdir-bug.c && ./a.out'
  dir=0xff5b4150
  readdir(dir)=(nil)
  errno=75: Value too large for defined data type

  Do remember to replace the /path/to/qemu-arm-static and /path/to
  /readdir-bug.c to the actual paths of the files.

  The root cause is in glibc:
  https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/getdents.c;h=6d09a5be7057e2792be9150d3a2c7b293cf6fc34;hb=a5275ba5378c9256d18e582572b4315e8edfcbfb#l87

  By C standard, the return type of readdir() is DIR*, in which the
  inode number and offset are 32-bit integers, therefore, glibc calls
  getdents64() and check if the inode number and offset fits the 32-bit
  range, and reports EOVERFLOW if not.

  The problem here is for 32-bit user-static qemu running on 64-bit
  host, getdents64 simply passing through the inode number and offset
  from underlying getdents64 syscall (from 64-bit kernel), which is very
  likely to not fit into 32-bit range. On real hardware, the 32-bit
  kernel creates 32-bit inode numbers, therefore works properly.

  The glibc code makes sense to do the check to be conformant with C
  standard, therefore ideally it should be a fix on qemu side. I admit
  this is difficult because qemu has to maintain a mapping between
  underlying 64-bit inode numbers and 32-bit inode numbers, which would
  severely hurt the performance. I don't expect this could be fix
  anytime soon (or even there would be a fix), but it would be
  worthwhile to surface this issue.

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


^ permalink raw reply	[flat|nested] 21+ messages in thread

* [Bug 1805913] Re: readdir() returns NULL (errno=EOVERFLOW) for 32-bit user-static qemu on 64-bit host
  2018-11-30  0:06 [Qemu-devel] [Bug 1805913] [NEW] readdir() returns NULL (errno=EOVERFLOW) for 32-bit user-static qemu on 64-bit host Ke Liu
                   ` (11 preceding siblings ...)
  2020-02-06 13:34 ` Philippe Vaucher
@ 2020-03-26 20:16 ` Peter Maydell
  2020-03-27 15:19 ` Manuel Reimer
                   ` (5 subsequent siblings)
  18 siblings, 0 replies; 21+ messages in thread
From: Peter Maydell @ 2020-03-26 20:16 UTC (permalink / raw)
  To: qemu-devel

** 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/1805913

Title:
  readdir() returns NULL (errno=EOVERFLOW) for 32-bit user-static qemu
  on 64-bit host

Status in QEMU:
  Confirmed

Bug description:
  This can be simply reproduced by compiling and running the attached C
  code (readdir-bug.c) under 32-bit user-static qemu, such as qemu-arm-
  static:

  # Setup docker for user-static binfmt
  docker run --rm --privileged multiarch/qemu-user-static:register --reset
  # Compile the code and run (readdir for / is fine, so create a new directory /test).
  docker run -v /path/to/qemu-arm-static:/usr/bin/qemu-arm-static -v /path/to/readdir-bug.c:/tmp/readdir-bug.c -it --rm arm32v7/ubuntu:18.10 bash -c '{ apt update && apt install -y gcc; } >&/dev/null && mkdir -p /test && cd /test && gcc /tmp/readdir-bug.c && ./a.out'
  dir=0xff5b4150
  readdir(dir)=(nil)
  errno=75: Value too large for defined data type

  Do remember to replace the /path/to/qemu-arm-static and /path/to
  /readdir-bug.c to the actual paths of the files.

  The root cause is in glibc:
  https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/getdents.c;h=6d09a5be7057e2792be9150d3a2c7b293cf6fc34;hb=a5275ba5378c9256d18e582572b4315e8edfcbfb#l87

  By C standard, the return type of readdir() is DIR*, in which the
  inode number and offset are 32-bit integers, therefore, glibc calls
  getdents64() and check if the inode number and offset fits the 32-bit
  range, and reports EOVERFLOW if not.

  The problem here is for 32-bit user-static qemu running on 64-bit
  host, getdents64 simply passing through the inode number and offset
  from underlying getdents64 syscall (from 64-bit kernel), which is very
  likely to not fit into 32-bit range. On real hardware, the 32-bit
  kernel creates 32-bit inode numbers, therefore works properly.

  The glibc code makes sense to do the check to be conformant with C
  standard, therefore ideally it should be a fix on qemu side. I admit
  this is difficult because qemu has to maintain a mapping between
  underlying 64-bit inode numbers and 32-bit inode numbers, which would
  severely hurt the performance. I don't expect this could be fix
  anytime soon (or even there would be a fix), but it would be
  worthwhile to surface this issue.

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


^ permalink raw reply	[flat|nested] 21+ messages in thread

* [Bug 1805913] Re: readdir() returns NULL (errno=EOVERFLOW) for 32-bit user-static qemu on 64-bit host
  2018-11-30  0:06 [Qemu-devel] [Bug 1805913] [NEW] readdir() returns NULL (errno=EOVERFLOW) for 32-bit user-static qemu on 64-bit host Ke Liu
                   ` (12 preceding siblings ...)
  2020-03-26 20:16 ` Peter Maydell
@ 2020-03-27 15:19 ` Manuel Reimer
  2020-03-27 16:00 ` Peter Maydell
                   ` (4 subsequent siblings)
  18 siblings, 0 replies; 21+ messages in thread
From: Manuel Reimer @ 2020-03-27 15:19 UTC (permalink / raw)
  To: qemu-devel

I seem to have found another workaround. Knowing now what causes this my
guess was: If I make the qemu-arm-static on the host a 32 bit binary and
get "multilib" running to make my 64 bit Linux installation run this,
then in theory this incompatibility should not happen. If it would, then
32 bit x86 applications whould run into the same problem.

And at least according to my tries, I did so far, this seems to be the
case. I was able to reproduce this with svn (no checkout possible from
32 bit armv7h). If the qemu-arm-static binary is a 32 bit x86
application, then SVN checkouts work well now.

So until there is a better solution it seems to be a good idea to make
the emulation layer run through multilib for 32 bit target
architectures, so the host kernel can switch to its 32 bit backwards
compatibility mode.

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

Title:
  readdir() returns NULL (errno=EOVERFLOW) for 32-bit user-static qemu
  on 64-bit host

Status in QEMU:
  Confirmed

Bug description:
  This can be simply reproduced by compiling and running the attached C
  code (readdir-bug.c) under 32-bit user-static qemu, such as qemu-arm-
  static:

  # Setup docker for user-static binfmt
  docker run --rm --privileged multiarch/qemu-user-static:register --reset
  # Compile the code and run (readdir for / is fine, so create a new directory /test).
  docker run -v /path/to/qemu-arm-static:/usr/bin/qemu-arm-static -v /path/to/readdir-bug.c:/tmp/readdir-bug.c -it --rm arm32v7/ubuntu:18.10 bash -c '{ apt update && apt install -y gcc; } >&/dev/null && mkdir -p /test && cd /test && gcc /tmp/readdir-bug.c && ./a.out'
  dir=0xff5b4150
  readdir(dir)=(nil)
  errno=75: Value too large for defined data type

  Do remember to replace the /path/to/qemu-arm-static and /path/to
  /readdir-bug.c to the actual paths of the files.

  The root cause is in glibc:
  https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/getdents.c;h=6d09a5be7057e2792be9150d3a2c7b293cf6fc34;hb=a5275ba5378c9256d18e582572b4315e8edfcbfb#l87

  By C standard, the return type of readdir() is DIR*, in which the
  inode number and offset are 32-bit integers, therefore, glibc calls
  getdents64() and check if the inode number and offset fits the 32-bit
  range, and reports EOVERFLOW if not.

  The problem here is for 32-bit user-static qemu running on 64-bit
  host, getdents64 simply passing through the inode number and offset
  from underlying getdents64 syscall (from 64-bit kernel), which is very
  likely to not fit into 32-bit range. On real hardware, the 32-bit
  kernel creates 32-bit inode numbers, therefore works properly.

  The glibc code makes sense to do the check to be conformant with C
  standard, therefore ideally it should be a fix on qemu side. I admit
  this is difficult because qemu has to maintain a mapping between
  underlying 64-bit inode numbers and 32-bit inode numbers, which would
  severely hurt the performance. I don't expect this could be fix
  anytime soon (or even there would be a fix), but it would be
  worthwhile to surface this issue.

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


^ permalink raw reply	[flat|nested] 21+ messages in thread

* [Bug 1805913] Re: readdir() returns NULL (errno=EOVERFLOW) for 32-bit user-static qemu on 64-bit host
  2018-11-30  0:06 [Qemu-devel] [Bug 1805913] [NEW] readdir() returns NULL (errno=EOVERFLOW) for 32-bit user-static qemu on 64-bit host Ke Liu
                   ` (13 preceding siblings ...)
  2020-03-27 15:19 ` Manuel Reimer
@ 2020-03-27 16:00 ` Peter Maydell
  2020-04-03 22:43 ` Eicke Herbertz
                   ` (3 subsequent siblings)
  18 siblings, 0 replies; 21+ messages in thread
From: Peter Maydell @ 2020-03-27 16:00 UTC (permalink / raw)
  To: qemu-devel

Yes, using a 32-bit host QEMU process will also work. You might run into
a few guest programs that don't work with that -- a 64-bit QEMU process
allows us to give the guest the full address space it might need, while
a 32-bit QEMU process means that QEMU itself must share with the guest,
so if the guest uses a lot of virtual memory or is picky about where it
maps things then it might fail to mmap() things where it wants them. But
it's probably overall the least-bad workaround at the current time.

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

Title:
  readdir() returns NULL (errno=EOVERFLOW) for 32-bit user-static qemu
  on 64-bit host

Status in QEMU:
  Confirmed

Bug description:
  This can be simply reproduced by compiling and running the attached C
  code (readdir-bug.c) under 32-bit user-static qemu, such as qemu-arm-
  static:

  # Setup docker for user-static binfmt
  docker run --rm --privileged multiarch/qemu-user-static:register --reset
  # Compile the code and run (readdir for / is fine, so create a new directory /test).
  docker run -v /path/to/qemu-arm-static:/usr/bin/qemu-arm-static -v /path/to/readdir-bug.c:/tmp/readdir-bug.c -it --rm arm32v7/ubuntu:18.10 bash -c '{ apt update && apt install -y gcc; } >&/dev/null && mkdir -p /test && cd /test && gcc /tmp/readdir-bug.c && ./a.out'
  dir=0xff5b4150
  readdir(dir)=(nil)
  errno=75: Value too large for defined data type

  Do remember to replace the /path/to/qemu-arm-static and /path/to
  /readdir-bug.c to the actual paths of the files.

  The root cause is in glibc:
  https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/getdents.c;h=6d09a5be7057e2792be9150d3a2c7b293cf6fc34;hb=a5275ba5378c9256d18e582572b4315e8edfcbfb#l87

  By C standard, the return type of readdir() is DIR*, in which the
  inode number and offset are 32-bit integers, therefore, glibc calls
  getdents64() and check if the inode number and offset fits the 32-bit
  range, and reports EOVERFLOW if not.

  The problem here is for 32-bit user-static qemu running on 64-bit
  host, getdents64 simply passing through the inode number and offset
  from underlying getdents64 syscall (from 64-bit kernel), which is very
  likely to not fit into 32-bit range. On real hardware, the 32-bit
  kernel creates 32-bit inode numbers, therefore works properly.

  The glibc code makes sense to do the check to be conformant with C
  standard, therefore ideally it should be a fix on qemu side. I admit
  this is difficult because qemu has to maintain a mapping between
  underlying 64-bit inode numbers and 32-bit inode numbers, which would
  severely hurt the performance. I don't expect this could be fix
  anytime soon (or even there would be a fix), but it would be
  worthwhile to surface this issue.

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


^ permalink raw reply	[flat|nested] 21+ messages in thread

* [Bug 1805913] Re: readdir() returns NULL (errno=EOVERFLOW) for 32-bit user-static qemu on 64-bit host
  2018-11-30  0:06 [Qemu-devel] [Bug 1805913] [NEW] readdir() returns NULL (errno=EOVERFLOW) for 32-bit user-static qemu on 64-bit host Ke Liu
                   ` (14 preceding siblings ...)
  2020-03-27 16:00 ` Peter Maydell
@ 2020-04-03 22:43 ` Eicke Herbertz
  2021-04-20  8:11 ` Thomas Huth
                   ` (2 subsequent siblings)
  18 siblings, 0 replies; 21+ messages in thread
From: Eicke Herbertz @ 2020-04-03 22:43 UTC (permalink / raw)
  To: qemu-devel

After reading through the discussion on the mailing list, as it's all about ext4, I got curious...
I'm testing with qemu-user-static and regulary build arm images in a tmpfs. This show similar behaviour and readdir() fails. However, running in the same root copied onto a btrfs, it seems fine.
Maybe this is an even less bad workaround for some folks?

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

Title:
  readdir() returns NULL (errno=EOVERFLOW) for 32-bit user-static qemu
  on 64-bit host

Status in QEMU:
  Confirmed

Bug description:
  This can be simply reproduced by compiling and running the attached C
  code (readdir-bug.c) under 32-bit user-static qemu, such as qemu-arm-
  static:

  # Setup docker for user-static binfmt
  docker run --rm --privileged multiarch/qemu-user-static:register --reset
  # Compile the code and run (readdir for / is fine, so create a new directory /test).
  docker run -v /path/to/qemu-arm-static:/usr/bin/qemu-arm-static -v /path/to/readdir-bug.c:/tmp/readdir-bug.c -it --rm arm32v7/ubuntu:18.10 bash -c '{ apt update && apt install -y gcc; } >&/dev/null && mkdir -p /test && cd /test && gcc /tmp/readdir-bug.c && ./a.out'
  dir=0xff5b4150
  readdir(dir)=(nil)
  errno=75: Value too large for defined data type

  Do remember to replace the /path/to/qemu-arm-static and /path/to
  /readdir-bug.c to the actual paths of the files.

  The root cause is in glibc:
  https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/getdents.c;h=6d09a5be7057e2792be9150d3a2c7b293cf6fc34;hb=a5275ba5378c9256d18e582572b4315e8edfcbfb#l87

  By C standard, the return type of readdir() is DIR*, in which the
  inode number and offset are 32-bit integers, therefore, glibc calls
  getdents64() and check if the inode number and offset fits the 32-bit
  range, and reports EOVERFLOW if not.

  The problem here is for 32-bit user-static qemu running on 64-bit
  host, getdents64 simply passing through the inode number and offset
  from underlying getdents64 syscall (from 64-bit kernel), which is very
  likely to not fit into 32-bit range. On real hardware, the 32-bit
  kernel creates 32-bit inode numbers, therefore works properly.

  The glibc code makes sense to do the check to be conformant with C
  standard, therefore ideally it should be a fix on qemu side. I admit
  this is difficult because qemu has to maintain a mapping between
  underlying 64-bit inode numbers and 32-bit inode numbers, which would
  severely hurt the performance. I don't expect this could be fix
  anytime soon (or even there would be a fix), but it would be
  worthwhile to surface this issue.

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


^ permalink raw reply	[flat|nested] 21+ messages in thread

* [Bug 1805913] Re: readdir() returns NULL (errno=EOVERFLOW) for 32-bit user-static qemu on 64-bit host
  2018-11-30  0:06 [Qemu-devel] [Bug 1805913] [NEW] readdir() returns NULL (errno=EOVERFLOW) for 32-bit user-static qemu on 64-bit host Ke Liu
                   ` (15 preceding siblings ...)
  2020-04-03 22:43 ` Eicke Herbertz
@ 2021-04-20  8:11 ` Thomas Huth
  2021-04-20  9:16 ` Peter Maydell
  2021-05-11  5:36 ` Thomas Huth
  18 siblings, 0 replies; 21+ messages in thread
From: Thomas Huth @ 2021-04-20  8:11 UTC (permalink / raw)
  To: qemu-devel

The QEMU project is currently considering to move its bug tracking to another system. For this we need to know which bugs are still valid and which could be closed already. Thus we are setting older bugs to "Incomplete" now.
If you still think this bug report here is valid, then please switch the state back to "New" within the next 60 days, otherwise this report will be marked as "Expired". Or mark it as "Fix Released" if the problem has been solved with a newer version of QEMU already. Thank you and sorry for the inconvenience.

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

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

Title:
  readdir() returns NULL (errno=EOVERFLOW) for 32-bit user-static qemu
  on 64-bit host

Status in QEMU:
  Incomplete

Bug description:
  This can be simply reproduced by compiling and running the attached C
  code (readdir-bug.c) under 32-bit user-static qemu, such as qemu-arm-
  static:

  # Setup docker for user-static binfmt
  docker run --rm --privileged multiarch/qemu-user-static:register --reset
  # Compile the code and run (readdir for / is fine, so create a new directory /test).
  docker run -v /path/to/qemu-arm-static:/usr/bin/qemu-arm-static -v /path/to/readdir-bug.c:/tmp/readdir-bug.c -it --rm arm32v7/ubuntu:18.10 bash -c '{ apt update && apt install -y gcc; } >&/dev/null && mkdir -p /test && cd /test && gcc /tmp/readdir-bug.c && ./a.out'
  dir=0xff5b4150
  readdir(dir)=(nil)
  errno=75: Value too large for defined data type

  Do remember to replace the /path/to/qemu-arm-static and /path/to
  /readdir-bug.c to the actual paths of the files.

  The root cause is in glibc:
  https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/getdents.c;h=6d09a5be7057e2792be9150d3a2c7b293cf6fc34;hb=a5275ba5378c9256d18e582572b4315e8edfcbfb#l87

  By C standard, the return type of readdir() is DIR*, in which the
  inode number and offset are 32-bit integers, therefore, glibc calls
  getdents64() and check if the inode number and offset fits the 32-bit
  range, and reports EOVERFLOW if not.

  The problem here is for 32-bit user-static qemu running on 64-bit
  host, getdents64 simply passing through the inode number and offset
  from underlying getdents64 syscall (from 64-bit kernel), which is very
  likely to not fit into 32-bit range. On real hardware, the 32-bit
  kernel creates 32-bit inode numbers, therefore works properly.

  The glibc code makes sense to do the check to be conformant with C
  standard, therefore ideally it should be a fix on qemu side. I admit
  this is difficult because qemu has to maintain a mapping between
  underlying 64-bit inode numbers and 32-bit inode numbers, which would
  severely hurt the performance. I don't expect this could be fix
  anytime soon (or even there would be a fix), but it would be
  worthwhile to surface this issue.

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


^ permalink raw reply	[flat|nested] 21+ messages in thread

* [Bug 1805913] Re: readdir() returns NULL (errno=EOVERFLOW) for 32-bit user-static qemu on 64-bit host
  2018-11-30  0:06 [Qemu-devel] [Bug 1805913] [NEW] readdir() returns NULL (errno=EOVERFLOW) for 32-bit user-static qemu on 64-bit host Ke Liu
                   ` (16 preceding siblings ...)
  2021-04-20  8:11 ` Thomas Huth
@ 2021-04-20  9:16 ` Peter Maydell
  2021-05-11  5:36 ` Thomas Huth
  18 siblings, 0 replies; 21+ messages in thread
From: Peter Maydell @ 2021-04-20  9:16 UTC (permalink / raw)
  To: qemu-devel

This is still a bug, and still blocked on the kernel providing APIs to QEMU to request 32-bit directory entries. Linus Walleij proposed a kernel patch to add a suitable fcntl flag but as far as I'm aware it didn't get in so far:
 https://lore.kernel.org/qemu-devel/20201117233928.255671-1-linus.walleij@linaro.org/


** Changed in: qemu
       Status: Incomplete => 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/1805913

Title:
  readdir() returns NULL (errno=EOVERFLOW) for 32-bit user-static qemu
  on 64-bit host

Status in QEMU:
  Confirmed

Bug description:
  This can be simply reproduced by compiling and running the attached C
  code (readdir-bug.c) under 32-bit user-static qemu, such as qemu-arm-
  static:

  # Setup docker for user-static binfmt
  docker run --rm --privileged multiarch/qemu-user-static:register --reset
  # Compile the code and run (readdir for / is fine, so create a new directory /test).
  docker run -v /path/to/qemu-arm-static:/usr/bin/qemu-arm-static -v /path/to/readdir-bug.c:/tmp/readdir-bug.c -it --rm arm32v7/ubuntu:18.10 bash -c '{ apt update && apt install -y gcc; } >&/dev/null && mkdir -p /test && cd /test && gcc /tmp/readdir-bug.c && ./a.out'
  dir=0xff5b4150
  readdir(dir)=(nil)
  errno=75: Value too large for defined data type

  Do remember to replace the /path/to/qemu-arm-static and /path/to
  /readdir-bug.c to the actual paths of the files.

  The root cause is in glibc:
  https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/getdents.c;h=6d09a5be7057e2792be9150d3a2c7b293cf6fc34;hb=a5275ba5378c9256d18e582572b4315e8edfcbfb#l87

  By C standard, the return type of readdir() is DIR*, in which the
  inode number and offset are 32-bit integers, therefore, glibc calls
  getdents64() and check if the inode number and offset fits the 32-bit
  range, and reports EOVERFLOW if not.

  The problem here is for 32-bit user-static qemu running on 64-bit
  host, getdents64 simply passing through the inode number and offset
  from underlying getdents64 syscall (from 64-bit kernel), which is very
  likely to not fit into 32-bit range. On real hardware, the 32-bit
  kernel creates 32-bit inode numbers, therefore works properly.

  The glibc code makes sense to do the check to be conformant with C
  standard, therefore ideally it should be a fix on qemu side. I admit
  this is difficult because qemu has to maintain a mapping between
  underlying 64-bit inode numbers and 32-bit inode numbers, which would
  severely hurt the performance. I don't expect this could be fix
  anytime soon (or even there would be a fix), but it would be
  worthwhile to surface this issue.

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


^ permalink raw reply	[flat|nested] 21+ messages in thread

* [Bug 1805913] Re: readdir() returns NULL (errno=EOVERFLOW) for 32-bit user-static qemu on 64-bit host
  2018-11-30  0:06 [Qemu-devel] [Bug 1805913] [NEW] readdir() returns NULL (errno=EOVERFLOW) for 32-bit user-static qemu on 64-bit host Ke Liu
                   ` (17 preceding siblings ...)
  2021-04-20  9:16 ` Peter Maydell
@ 2021-05-11  5:36 ` Thomas Huth
  18 siblings, 0 replies; 21+ messages in thread
From: Thomas Huth @ 2021-05-11  5:36 UTC (permalink / raw)
  To: qemu-devel

This is an automated cleanup. This bug report has been moved to QEMU's
new bug tracker on gitlab.com and thus gets marked as 'expired' now.
Please continue with the discussion here:

 https://gitlab.com/qemu-project/qemu/-/issues/263


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

** Bug watch added: gitlab.com/qemu-project/qemu/-/issues #263
   https://gitlab.com/qemu-project/qemu/-/issues/263

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

Title:
  readdir() returns NULL (errno=EOVERFLOW) for 32-bit user-static qemu
  on 64-bit host

Status in QEMU:
  Expired

Bug description:
  This can be simply reproduced by compiling and running the attached C
  code (readdir-bug.c) under 32-bit user-static qemu, such as qemu-arm-
  static:

  # Setup docker for user-static binfmt
  docker run --rm --privileged multiarch/qemu-user-static:register --reset
  # Compile the code and run (readdir for / is fine, so create a new directory /test).
  docker run -v /path/to/qemu-arm-static:/usr/bin/qemu-arm-static -v /path/to/readdir-bug.c:/tmp/readdir-bug.c -it --rm arm32v7/ubuntu:18.10 bash -c '{ apt update && apt install -y gcc; } >&/dev/null && mkdir -p /test && cd /test && gcc /tmp/readdir-bug.c && ./a.out'
  dir=0xff5b4150
  readdir(dir)=(nil)
  errno=75: Value too large for defined data type

  Do remember to replace the /path/to/qemu-arm-static and /path/to
  /readdir-bug.c to the actual paths of the files.

  The root cause is in glibc:
  https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/getdents.c;h=6d09a5be7057e2792be9150d3a2c7b293cf6fc34;hb=a5275ba5378c9256d18e582572b4315e8edfcbfb#l87

  By C standard, the return type of readdir() is DIR*, in which the
  inode number and offset are 32-bit integers, therefore, glibc calls
  getdents64() and check if the inode number and offset fits the 32-bit
  range, and reports EOVERFLOW if not.

  The problem here is for 32-bit user-static qemu running on 64-bit
  host, getdents64 simply passing through the inode number and offset
  from underlying getdents64 syscall (from 64-bit kernel), which is very
  likely to not fit into 32-bit range. On real hardware, the 32-bit
  kernel creates 32-bit inode numbers, therefore works properly.

  The glibc code makes sense to do the check to be conformant with C
  standard, therefore ideally it should be a fix on qemu side. I admit
  this is difficult because qemu has to maintain a mapping between
  underlying 64-bit inode numbers and 32-bit inode numbers, which would
  severely hurt the performance. I don't expect this could be fix
  anytime soon (or even there would be a fix), but it would be
  worthwhile to surface this issue.

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


^ permalink raw reply	[flat|nested] 21+ messages in thread

end of thread, other threads:[~2021-05-11  6:20 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-11-30  0:06 [Qemu-devel] [Bug 1805913] [NEW] readdir() returns NULL (errno=EOVERFLOW) for 32-bit user-static qemu on 64-bit host Ke Liu
2018-12-01 13:44 ` [Qemu-devel] [Bug 1805913] " Kan Li
2018-12-05 11:15 ` Alex Bennée
2019-04-16 13:20 ` diddly
2019-04-16 13:20   ` diddly
2019-07-16 14:46 ` Alex Bennée
2019-08-01 13:00 ` diddly
2019-08-01 13:32 ` Peter Maydell
2020-01-30  8:19 ` Philippe Vaucher
2020-01-30  8:20 ` Philippe Vaucher
2020-01-30 10:47 ` diddly
2020-02-02 20:11 ` Philippe Vaucher
2020-02-02 21:01 ` Marcin Konarski
2020-02-06 13:34 ` Philippe Vaucher
2020-03-26 20:16 ` Peter Maydell
2020-03-27 15:19 ` Manuel Reimer
2020-03-27 16:00 ` Peter Maydell
2020-04-03 22:43 ` Eicke Herbertz
2021-04-20  8:11 ` Thomas Huth
2021-04-20  9:16 ` Peter Maydell
2021-05-11  5:36 ` Thomas Huth

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).