[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Bug 1805913] Re: readdir() returns NULL (errno=EOVERFLOW) for 32-bit us
From: |
Philippe Vaucher |
Subject: |
[Bug 1805913] Re: readdir() returns NULL (errno=EOVERFLOW) for 32-bit user-static qemu on 64-bit host |
Date: |
Thu, 06 Feb 2020 13:34:48 -0000 |
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