[overlay] [fuse] Potential bug with large file support for FUSE based lowerdir

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hello all,

I have stumbled into what I suspect may be a bug in the overlayfs/fuse stack.

The repro script looks like this:
```sh
#!/bin/bash

set -xe

for i in large1 large2;
do
  if [ -f $i.squashfs ]; then
    continue
  fi
  mkdir -p $i
  pushd $i || exit 1
  yes $i | head -c 4GB > test.file
  popd || exit 1
  mksquashfs $i $i.squashfs
done

rm -rf work
mkdir -p work/{lower0,lower1,lower2,upper,work,mnt}

squashfuse -o allow_other large1.squashfs work/lower1
squashfuse -o allow_other large2.squashfs work/lower2

trap "set +e; fusermount -u $(realpath work/lower1); fusermount -u $(realpath work/lower2); sudo umount --verbose -l $(realpath work/mnt)" EXIT

sudo mount \
  -t overlay \
  -o lowerdir=work/lower2:work/lower1:work/lower0,upperdir=work/upper,workdir=work/work\
  overlay \
  work/mnt

pushd work/mnt
dd if=/dev/zero of=test.file bs=4k count=80
popd
```

When writing to the file I see the following error:
```
test.file: Value too large for defined data type
```

The file can be read just fine, stat works.
Mounting the squashfs with sudo and a loop device does not have this problem.

Now, dmesg shows:
```
[Jan31 08:38] overlayfs: failed to retrieve lower fileattr (/test.file, err=-75)
```
Which matches the overflow strace error:
```
openat(AT_FDCWD, "test.file", O_WRONLY|O_CREAT|O_TRUNC, 0666) = -1 EOVERFLOW (Value too large for defined data type)
```

I have traced the function to fail in copy_up.c, which eventually calls `fuse_open_common` which then calls `generic_file_open` directly.

The comment implies that `O_LARGEFILE` is only forced when called in a syscall:
```c
/*
 * Called when an inode is about to be open.
 * We use this to disallow opening large files on 32bit systems if
 * the caller didn't specify O_LARGEFILE.  On 64bit systems we force
 * on this flag in sys_open.
 */
int generic_file_open(struct inode * inode, struct file * filp)
{
        if (!(filp->f_flags & O_LARGEFILE) && i_size_read(inode) > MAX_NON_LFS)
                return -EOVERFLOW;
        return 0;
}
```

I was wondering if there is a bug in the overlayfs/fuse stack which does not set `O_LARGEFILE` when reading the lower dir file.

The same failure can be reproduced with `archivemount` so I suspect other FUSE based filesystems may be affected.
Note that writing over small files (<2GB) works fine as expected.

Attached:
* `ovl_copy_up_inode_fail.log` - squashfuse + overlay
* `ovl_copy_up_inode_ok_loop` - squash loop device + overlay

My machine is pretty old `5.15.0-89-generic` on Ubuntu, we have also seen this on `6.6.12-1-lts` Arch but I suspect this may still exist on HEAD based on the code.

Please let me know if am I doing something wrong here or if this could be a legitimate bug.

Kind regards,
Lukasz
IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium. Thank you.





[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [NTFS 3]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [NTFS 3]     [Samba]     [Device Mapper]     [CEPH Development]

  Powered by Linux