google / mount-zip

FUSE file system for ZIP archives
GNU General Public License v3.0
159 stars 16 forks source link

`/usr/bin/env` reports `File name too long` error on overlayfs since 1.0.8 #24

Closed modten closed 7 months ago

modten commented 7 months ago

Hi, we use mount-zip to mount multiple zip archives in the almalinux9.3 Docker image, and then use overlayfs to merge the two file directories.

If we set the environment variable PATH to include the directory merged by overlayfs, any shell script starting with /usr/bin/env will report a File name too long error.

I tested multiple versions and found that this problem may have been introduced starting from 1.0.8. Full test records, undocumented versions were not tested:

mount-zip-1.0.14(libzip-1.7.3)
mount-zip-1.0.13(libzip-1.10.1)
mount-zip-1.0.8(libzip-1.10.1)
mount-zip-1.0.7(libzip-1.10.1) is OK
mount-zip-1.0.6(libzip-1.7.3) is OK
mount-zip-1.0.4(libzip-1.7.3) is OK

Since we need to run in the almalinux-micro image, we package all the so files and run mount-zip by specifying LD_LIBRARY_PATH.

Here are the steps to reproduce:

# host
docker run --user root --entrypoint bash --privileged --platform=linux/amd64 --name=mz -it almalinux:9.3-minimal

# container
mkdir -p /layers /opt/layers

# host
docker cp ./mount-zip mz:/usr/local/mount-zip
docker cp ./node-v20.11.1-linux-x64 mz:/usr/local/node20.11.1
docker cp ./a.zip mz:/layers/a.zip
docker cp ./b.zip mz:/layers/b.zip

# container
export PATH=/opt/layers/bin:$PATH
/usr/local/mount-zip/mount-zip -o allow_other /layers/a.zip /mnt/a
ls -l /mnt/a
/usr/local/mount-zip/mount-zip -o allow_other /layers/b.zip /mnt/b
ls -l /mnt/b
/usr/local/mount-zip/mount -t overlay -o lowerdir=/mnt/a:/mnt/b overlay /opt/layers
/usr/local/mount-zip/mount-zip --version
npm --version
env: ‘node’: File name too long
├── bin
│   ├── mount
│   └── mount-zip
├── lib
│   ├── libblkid.so.1
│   ├── libbz2.so.1
│   ├── libcrypto.so.3
│   ├── libfuse.so.2
│   ├── libicudata.so.67
│   ├── libicui18n.so.67
│   ├── libicuuc.so.67
│   ├── liblzma.so.5
│   ├── libmount.so.1
│   ├── libz.so.1
│   ├── libzip.so.5
│   └── libzstd.so.1
├── mount
├── mount-zip

mount-zip script

#!/bin/sh

LD_LIBRARY_PATH="/usr/local/mount-zip/lib" "/usr/local/mount-zip/bin/mount-zip" $@

/usr/local/mount-zip/mount-zip --version

mount-zip version: 1.0.13
libzip version: 1.10.1
FUSE library version: 2.9.9
using FUSE kernel interface version 7.19
fdegros commented 7 months ago

The POSIX error code for "File name too long" is ENAMETOOLONG. This error code is nowhere to be found in mount-zip's code (see here). And I'm not aware of any code path in mount-zip that would allow it to return this error code via its FUSE interface.

So, which layer of your software stack is actually returning the error? This is not clear to me.

Can you see this error being returned or logged by mount-zip when it is run in foreground mode with the -f option?

modten commented 7 months ago

Hi @fdegros , thanks for your reply. I can now reproduce the issue on my archlinux pc. mount-zip has no returned error.

> ~/mount-zip > mount-zip --version
mount-zip version: 1.0.6
libzip version: 1.10.1
FUSE library version: 2.9.9
fusermount version: 2.9.9
using FUSE kernel interface version 7.19
> ~/mount-zip > mount-zip -o allow_other a.zip ./mount/a
> ~/mount-zip > mount-zip -o allow_other b.zip ./mount/b
> ~/mount-zip > ls -l ./mount/a 
总计 1
-rw-r--r-- 1 root root 2  4月24日 20:45 a.txt
> ~/mount-zip > ls -l ./mount/b
总计 1
-rw-r--r-- 1 root root 2  4月24日 20:45 b.txt
> ~/mount-zip > sudo mount -t overlay -o lowerdir=mount/a:mount/b overlay merge 
> ~/mount-zip > ls ./merge 
a.txt  b.txt
> ~/mount-zip > mount-zip --version
mount-zip version: 1.0.12
libzip version: 1.10.1
FUSE library version: 2.9.9
fusermount version: 2.9.9
using FUSE kernel interface version 7.19
> ~/mount-zip > mount-zip -o allow_other a.zip ./mount/a        
> ~/mount-zip > mount-zip -o allow_other b.zip ./mount/b
> ~/mount-zip > ls -l ./mount/a ./mount/b 
./mount/a:
total 1
-rw-r--r-- 1 root root 2 Apr 24 20:45 a.txt

./mount/b:
total 1
-rw-r--r-- 1 root root 2 Apr 24 20:45 b.txt
> ~/mount-zip > sudo mount -t overlay -o lowerdir=mount/a:mount/b overlay merge 
> ~/mount-zip > ls ./merge 
ls: reading directory './merge': File name too long
fdegros commented 7 months ago

Thanks. I can reproduce the issue.

This seems to be related to the implementation of the statvfs call. In particular, the field f_namemax of struct statvfs is not getting set.

modten commented 7 months ago

I can confirm that the latest commit has resolved the issue, thanks.