serenity
serenity copied to clipboard
Symlink: linking to a non-existing file results in unexpected behaviour
Creating a symlink to a non-existing file results in unexpected behaviour.
$ ln -s /tmp/a-non-existing-file /home/anon/symlink
$ ls -al /home/anon
symlink -> /tmp/a-non-existing-file
$ echo 123 > /home/anon/symlink
$ ls /tmp/
/tmp/symlink
Observed behaviour
The file /tmp/symlink
is created
Expected behaviour
The file /tmp/a-non-existing-file
is created.
This is what happens in linux/macos.
Bug is here:
https://github.com/SerenityOS/serenity/blob/589ebbc24eb3acc86f50043f896414fe190a5229/Kernel/FileSystem/VirtualFileSystem.cpp#L321-L325
parent_custody
is the path to the parent directory of the resolved symlink, while path
still points to original /home/anon/symlink
entry. When concatenation happens it produce the bogus path.
The problem is probably originating from the caller site:
https://github.com/SerenityOS/serenity/blob/589ebbc24eb3acc86f50043f896414fe190a5229/Kernel/FileSystem/VirtualFileSystem.cpp#L213-L218
were resolve_path
should also return the new path.
It seems the problem is pathological. Tying to do a realpath
on symlink
is result in an error, instead of showing the destination path.
Problem his deeper than expected, it is possible to create files with any name in the target link path:
$ ln -s /tmp/a-non-existing-file /home/anon/symlink
$ echo 123 > /home/anon/symlink/foo
$ ls /tmp/
/tmp/foo
There is also something off with moving symlinks that point to a directory. It should rename the symlink. But it copies the directory.
$ cd /tmp/
$ mkdir dir
$ touch dir/file
$ ln -s dir symlink
$ ls -al
drwxr-xr-x dir
lrw-r--r-- symlink -> dir
$ mv symlink symlink2
$ ls -al
drwxr-xr-x dir
drwxr-xr-x symlink2 <-- its a directory now!
It does work correctly for symlinks pointing to a file.
For cross-device symlinks it can't even unlink the original file:
$ cd /home/anon/
$ ln -s /tmp/dir symlink
$ ls -al
lrw-r--r-- symlink -> /tmp/dir
$ mv symlink symlink2
mv: unlink 'symlink/': Is a directory
$ ls -al
lrw-r--r-- symlink -> /tmp/dir
drwxr-xr-x symlink2