dash not expanding glob wildcards in chroot
I have the exact same symptoms on my machine, even though I am working on a different project (based on docker, not on QEMU), so I cannot prove that it is the issue in your case, but it probably is.
I have a build which is sometimes working, and sometimes failing, because the wildcard does not always get expanded (I am doing ls /tmp/linux*deb
).
Strace shows that for the failing case, a call to getdents is returning -1 EOVERFLOW (Value too large for defined data type)
Working case:
[pid 29791] open("/tmp", O_RDONLY|O_NONBLOCK|O_LARGEFILE|O_DIRECTORY|O_CLOEXEC) = 3
[pid 29791] fstat64(3, {st_mode=S_IFDIR|S_ISVTX|0777, st_size=4096, ...}) = 0
[pid 29791] getdents(3, /* 3 entries */, 32768) = 60
[pid 29791] getdents(3, /* 0 entries */, 32768) = 0
[pid 29791] close(3) = 0
Failing case:
[pid 25606] open("/tmp", O_RDONLY|O_NONBLOCK|O_LARGEFILE|O_DIRECTORY|O_CLOEXEC) = 3
[pid 25606] fstat64(3, {st_mode=S_IFDIR|S_ISVTX|0777, st_size=100, ...}) = 0
[pid 25606] getdents(3, /* 1 entries */, 32768) = 16
[pid 25606] getdents(3, 0x585a831c, 32768) = -1 EOVERFLOW (Value too large for defined data type)
[pid 25606] close(3) = 0
I found a couple of bug-reports referencing the issue (getdents returns a 64 bits value, but the caller expects a 32 bits value in this case):
- https://github.com/moby/moby/issues/39732
- https://bugs.launchpad.net/qemu/+bug/1805913
- https://bugzilla.kernel.org/show_bug.cgi?id=205957
Cause
As Étienne found out (please, upvote them for the research effort), the root cause seems to be a change in glibc 2.28.
getdents64
on 64-bit Linux can returnd_off
values that don't fit in a 32-bitint
. On 32-bit systems it only returns 32-bit values.qemu-user
that emulates a 32-bit system on 64-bit Linux just passes the syscall through, so a 32-bit userland process can get overflowing values.- glibc 2.28 has a change that makes
readdir
always usegetdents64
and error out ifd_off
doesn't fit. On real 32-bit systems, this must not be causing problems because glibc went through with it. (Previously it calledgetdents
on 32-bit systems, this returns 32-bit values and the kernel does any truncating.)
Fix (or the lack thereof)
This glibc bug is currently tracking progress on this issue. It'll take its time to be fixed and eventually deployed to your distribution.
Workarounds
- The simplest workaround I can see is running these builds on a system with a 32-bit Linux kernel.
- If you can downgrade the glibc version (in the chroot!) to 2.27 that would fix the problem, but that might cause dependency problems and will alter the image you're building.
- One can also apply one of the many patches in the linked threads, but that will require compiling (and probably detaching from your package manager) either your kernel, glibc or (probably the easiest) QEMU.