mpartel / bindfs

Mount a directory elsewhere with changed permissions.
https://bindfs.org/
GNU General Public License v2.0
448 stars 64 forks source link

FreeBSD: getcwd returns bogus results with mounted subdirectories #153

Closed gzetzsche closed 5 months ago

gzetzsche commented 5 months ago

On FreeBSD (tested on 14.0), if you bindfs a directory where other filesystems are mounted below, then getcwd gives bogus results in those subdirectories. Example:

root@freebsd:~ # mount -t nullfs other/ dir/subdir/
root@freebsd:~ # bindfs dir/ mnt/
root@freebsd:~ # cd dir/subdir/
root@freebsd:~/dir/subdir # ./a.out  
/root/dir/subdir
root@freebsd:~/dir/subdir # cd ..
root@freebsd:~/dir # cd ..
root@freebsd:~ # cd mnt/subdir/
root@freebsd:~/mnt/subdir # ./a.out  
vgu`S"
root@freebsd:~/mnt/subdir #  

Here, a.out is the following C program:

#include <unistd.h>
#include <stdio.h>

int main()
{
        char p[100];
        getcwd(p,100);
        printf("%s\n", p);
}

The issue can also be reproduced without compiling a C program:

root@freebsd:~/mnt/subdir # python3
Python 3.9.18 (main, Apr  9 2024, 01:10:56)
[Clang 16.0.6 (https://github.com/llvm/llvm-project.git llvmorg-16.0.6-0-g7cbf1 on freebsd14
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> os.getcwd()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
FileNotFoundError: [Errno 2] No such file or directory
>>> 

(but then it's not obvious that the problem lies in what getcwd() does. Sometimes, os.getcwd() executes, but yields a string where the subdirectory is just replaced by ..)

The above situation occurs, e.g. when using bindfs to mount a tree of ZFS datasets, where the sub-datasets are mounted in subdirectories. Compared to FreeBSD's own nullfs, bindfs has the advantage of crossing filesystem boundaries.

gzetzsche commented 5 months ago

This was with the packages fusefs-bindfs-1.17.6_1 and fusefs-libs3-3.16.2.

mpartel commented 5 months ago

Strange. Did you find the cause?

gzetzsche commented 5 months ago

Oh, I must have closed this issue by accident---there was no change with the problem described above.

gzetzsche commented 5 months ago

I tested a bit more: getcwd() actually returns NULL and sets errno to ENOENT (No such file or directory).

mpartel commented 5 months ago

This also happens with libfuse's example passthrough FS, so this looks like a FUSE bug, not a bindfs bug.