Skip to content
GitLab
  • Menu
Projects Groups Snippets
  • /
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
    • Contribute to GitLab
    • Switch to GitLab Next
  • Sign in / Register
  • QEMU QEMU
  • Project information
    • Project information
    • Activity
    • Labels
    • Members
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
    • Locked Files
  • Issues 643
    • Issues 643
    • List
    • Boards
    • Service Desk
    • Milestones
    • Requirements
  • CI/CD
    • CI/CD
    • Pipelines
    • Jobs
    • Schedules
    • Test Cases
  • Deployments
    • Deployments
    • Environments
    • Releases
  • Packages & Registries
    • Packages & Registries
    • Package Registry
    • Container Registry
    • Infrastructure Registry
  • Monitor
    • Monitor
    • Metrics
    • Incidents
  • Analytics
    • Analytics
    • Value stream
    • CI/CD
    • Insights
    • Issue
    • Repository
  • External wiki
    • External wiki
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
Collapse sidebar
  • QEMUQEMU
  • QEMUQEMU
  • Issues
  • #263
Closed
Open
Created May 11, 2021 by Qemu Janitor@qemu-janitorReporter

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

This bug has been copied automatically from: https://bugs.launchpad.net/qemu/+bug/1805913
Reported by 'Kan Li' on 2018-11-30 :

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 upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information
Assignee
Assign to
Time tracking