GNU bug report logs - #74766
mv cannot move a file from a Linux "portal" file system

Previous Next

Package: coreutils;

Reported by: Bruno Haible <bruno <at> clisp.org>

Date: Tue, 10 Dec 2024 14:00:02 UTC

Severity: normal

To reply to this bug, email your comments to 74766 AT debbugs.gnu.org.

Toggle the display of automated, internal messages from the tracker.

View this report as an mbox folder, status mbox, maintainer mbox


Report forwarded to bug-coreutils <at> gnu.org:
bug#74766; Package coreutils. (Tue, 10 Dec 2024 14:00:02 GMT) Full text and rfc822 format available.

Acknowledgement sent to Bruno Haible <bruno <at> clisp.org>:
New bug report received and forwarded. Copy sent to bug-coreutils <at> gnu.org. (Tue, 10 Dec 2024 14:00:02 GMT) Full text and rfc822 format available.

Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Bruno Haible <bruno <at> clisp.org>
To: bug-coreutils <at> gnu.org
Subject: mv cannot move a file from a Linux "portal" file system
Date: Tue, 10 Dec 2024 14:59:22 +0100
Hi,

On Linux (Linux 5.15.0) I have a file /run/user/1000/doc/1316905f/jas-key.gpg
(created by visiting https://savannah.gnu.org/users/jas in Firefox and clicking
the "Download GPG Key" in that page).

It appears to be a regular file:

$ ls -l /run/user/1000/doc/1316905f/jas-key.gpg
-rw-rw-r-- 1 bruno bruno 7335 Dec 10 14:41 /run/user/1000/doc/1316905f/jas-key.gpg

It sits on a file system of type "portal":

$ (cd /run/user/1000/doc/1316905f/ && df -m .)
Filesystem     1M-blocks    Used Available Use% Mounted on
portal           1290923 1218257      7019 100% /run/user/1000/doc

I'm using 'mv' from GNU coreutils:

$ LC_ALL=C mv --version
mv (GNU coreutils) 9.4
...

Moving the file to an ext4 file system fails:

$ mv /run/user/1000/doc/1316905f/jas-key.gpg .
mv: cannot open '/run/user/1000/doc/1316905f/jas-key.gpg' for reading: Too many levels of symbolic links

Look at the system calls:

$ strace mv /run/user/1000/doc/1316905f/jas-key.gpg .
execve("/arch/local/x86_64-linux/bin/mv", ["mv", "/run/user/1000/doc/1316905f/jas-"..., "."], 0x7ffd1f57d410 /* 89 vars */) = 0
brk(NULL)                               = 0x14a8000
arch_prctl(0x3001 /* ARCH_??? */, 0x7ffcdeb8fe90) = -1 EINVAL (Invalid argument)
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f0e9e8f3000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=134075, ...}, AT_EMPTY_PATH) = 0
mmap(NULL, 134075, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f0e9e8d2000
close(3)                                = 0
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libselinux.so.1", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\0\0\0\0\0\0\0\0"..., 832) = 832
newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=166280, ...}, AT_EMPTY_PATH) = 0
mmap(NULL, 177672, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f0e9e8a6000
mprotect(0x7f0e9e8ac000, 139264, PROT_NONE) = 0
mmap(0x7f0e9e8ac000, 106496, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x6000) = 0x7f0e9e8ac000
mmap(0x7f0e9e8c6000, 28672, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x20000) = 0x7f0e9e8c6000
mmap(0x7f0e9e8ce000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x27000) = 0x7f0e9e8ce000
mmap(0x7f0e9e8d0000, 5640, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f0e9e8d0000
close(3)                                = 0
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libacl.so.1", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\0\0\0\0\0\0\0\0"..., 832) = 832
newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=34888, ...}, AT_EMPTY_PATH) = 0
mmap(NULL, 36896, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f0e9e89c000
mprotect(0x7f0e9e89e000, 24576, PROT_NONE) = 0
mmap(0x7f0e9e89e000, 16384, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x2000) = 0x7f0e9e89e000
mmap(0x7f0e9e8a2000, 4096, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x6000) = 0x7f0e9e8a2000
mmap(0x7f0e9e8a4000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x7000) = 0x7f0e9e8a4000
close(3)                                = 0
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libattr.so.1", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\0\0\0\0\0\0\0\0"..., 832) = 832
newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=26696, ...}, AT_EMPTY_PATH) = 0
mmap(NULL, 28696, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f0e9e894000
mmap(0x7f0e9e896000, 12288, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x2000) = 0x7f0e9e896000
mmap(0x7f0e9e899000, 4096, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x5000) = 0x7f0e9e899000
mmap(0x7f0e9e89a000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x5000) = 0x7f0e9e89a000
close(3)                                = 0
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0P\237\2\0\0\0\0\0"..., 832) = 832
pread64(3, "\6\0\0\0\4\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0"..., 784, 64) = 784
pread64(3, "\4\0\0\0 \0\0\0\5\0\0\0GNU\0\2\0\0\300\4\0\0\0\3\0\0\0\0\0\0\0"..., 48, 848) = 48
pread64(3, "\4\0\0\0\24\0\0\0\3\0\0\0GNU\0I\17\357\204\3$\f\221\2039x\324\224\323\236S"..., 68, 896) = 68
newfstatat(3, "", {st_mode=S_IFREG|0755, st_size=2220400, ...}, AT_EMPTY_PATH) = 0
pread64(3, "\6\0\0\0\4\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0"..., 784, 64) = 784
mmap(NULL, 2264656, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f0e9e66b000
mprotect(0x7f0e9e693000, 2023424, PROT_NONE) = 0
mmap(0x7f0e9e693000, 1658880, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x28000) = 0x7f0e9e693000
mmap(0x7f0e9e828000, 360448, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1bd000) = 0x7f0e9e828000
mmap(0x7f0e9e881000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x215000) = 0x7f0e9e881000
mmap(0x7f0e9e887000, 52816, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f0e9e887000
close(3)                                = 0
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libpcre2-8.so.0", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\0\0\0\0\0\0\0\0"..., 832) = 832
newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=613064, ...}, AT_EMPTY_PATH) = 0
mmap(NULL, 615184, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f0e9e5d4000
mmap(0x7f0e9e5d6000, 438272, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x2000) = 0x7f0e9e5d6000
mmap(0x7f0e9e641000, 163840, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x6d000) = 0x7f0e9e641000
mmap(0x7f0e9e669000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x94000) = 0x7f0e9e669000
close(3)                                = 0
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f0e9e5d2000
arch_prctl(ARCH_SET_FS, 0x7f0e9e5d3340) = 0
set_tid_address(0x7f0e9e5d3610)         = 3802617
set_robust_list(0x7f0e9e5d3620, 24)     = 0
rseq(0x7f0e9e5d3ce0, 0x20, 0, 0x53053053) = 0
mprotect(0x7f0e9e881000, 16384, PROT_READ) = 0
mprotect(0x7f0e9e669000, 4096, PROT_READ) = 0
mprotect(0x7f0e9e89a000, 4096, PROT_READ) = 0
mprotect(0x7f0e9e8a4000, 4096, PROT_READ) = 0
mprotect(0x7f0e9e8ce000, 4096, PROT_READ) = 0
mprotect(0x423000, 4096, PROT_READ)     = 0
mprotect(0x7f0e9e92d000, 8192, PROT_READ) = 0
prlimit64(0, RLIMIT_STACK, NULL, {rlim_cur=8192*1024, rlim_max=RLIM64_INFINITY}) = 0
munmap(0x7f0e9e8d2000, 134075)          = 0
statfs("/sys/fs/selinux", 0x7ffcdeb8fed0) = -1 ENOENT (No such file or directory)
statfs("/selinux", 0x7ffcdeb8fed0)      = -1 ENOENT (No such file or directory)
getrandom("\xc1\x7e\x88\x97\xcb\xb4\x9e\x85", 8, GRND_NONBLOCK) = 8
brk(NULL)                               = 0x14a8000
brk(0x14c9000)                          = 0x14c9000
openat(AT_FDCWD, "/proc/filesystems", O_RDONLY|O_CLOEXEC) = 3
newfstatat(3, "", {st_mode=S_IFREG|0444, st_size=0, ...}, AT_EMPTY_PATH) = 0
read(3, "nodev\tsysfs\nnodev\ttmpfs\nnodev\tbd"..., 1024) = 505
read(3, "", 1024)                       = 0
close(3)                                = 0
access("/etc/selinux/config", F_OK)     = -1 ENOENT (No such file or directory)
geteuid()                               = 1000
ioctl(0, TCGETS, {B38400 opost isig icanon echo ...}) = 0
renameat2(AT_FDCWD, "/run/user/1000/doc/1316905f/jas-key.gpg", AT_FDCWD, ".", RENAME_NOREPLACE) = -1 EXDEV (Invalid cross-device link)
renameat2(AT_FDCWD, "/run/user/1000/doc/1316905f/jas-key.gpg", AT_FDCWD, "jas-key.gpg", RENAME_NOREPLACE) = -1 EXDEV (Invalid cross-device link)
newfstatat(AT_FDCWD, "/run/user/1000/doc/1316905f/jas-key.gpg", {st_mode=S_IFREG|0664, st_size=7335, ...}, AT_SYMLINK_NOFOLLOW) = 0
newfstatat(AT_FDCWD, "jas-key.gpg", 0x7ffcdeb8fb30, AT_SYMLINK_NOFOLLOW) = -1 ENOENT (No such file or directory)
unlinkat(AT_FDCWD, "jas-key.gpg", 0)    = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/run/user/1000/doc/1316905f/jas-key.gpg", O_RDONLY|O_NOFOLLOW) = -1 ELOOP (Too many levels of symbolic links)
write(2, "mv: ", 4mv: )                     = 4
write(2, "cannot open '/run/user/1000/doc/"..., 65cannot open '/run/user/1000/doc/1316905f/jas-key.gpg' for reading) = 65
write(2, ": Too many levels of symbolic li"..., 35: Too many levels of symbolic links) = 35
write(2, "\n", 1
)                       = 1
lseek(0, 0, SEEK_CUR)                   = -1 ESPIPE (Illegal seek)
close(0)                                = 0
close(1)                                = 0
close(2)                                = 0
exit_group(1)                           = ?
+++ exited with 1 +++

I don't understand the result of the openat() system call.

$ cp /run/user/1000/doc/1316905f/jas-key.gpg .
works fine.

Bruno







Information forwarded to bug-coreutils <at> gnu.org:
bug#74766; Package coreutils. (Tue, 10 Dec 2024 18:12:02 GMT) Full text and rfc822 format available.

Message #8 received at 74766 <at> debbugs.gnu.org (full text, mbox):

From: Paul Eggert <eggert <at> cs.ucla.edu>
To: Bruno Haible <bruno <at> clisp.org>
Cc: 74766 <at> debbugs.gnu.org
Subject: Re: bug#74766: mv cannot move a file from a Linux "portal" file system
Date: Tue, 10 Dec 2024 10:11:21 -0800
On 2024-12-10 05:59, Bruno Haible via GNU coreutils Bug Reports wrote:

> newfstatat(AT_FDCWD, "/run/user/1000/doc/1316905f/jas-key.gpg", {st_mode=S_IFREG|0664, st_size=7335, ...}, AT_SYMLINK_NOFOLLOW) = 0

This means /run/user/1000/doc/1316905f/jas-key.gpg is a regular file and 
its name can be resolved without symlink loops.


> openat(AT_FDCWD, "/run/user/1000/doc/1316905f/jas-key.gpg", O_RDONLY|O_NOFOLLOW) = -1 ELOOP (Too many levels of symbolic links)

This means /run/user/1000/doc/1316905f/jas-key.gpg is a symlink, or 
there is a symlink loop when resolving /run or /run/user or ... or 
/run/user/1000/doc/1316905f. Which obviously contradicts the newfstatat 
results.


> I don't understand the result of the openat() system call.

Yes, it looks like a filesystem bug. I see a similar bug reported (but 
incorrectly diagnosed) here:

https://github.com/flatpak/xdg-desktop-portal/issues/1117


> $ cp /run/user/1000/doc/1316905f/jas-key.gpg .
> works fine.

Presumably this is because cp uses "openat(AT_FDCWD, 
"/run/user/1000/doc/1316905f/jas-key.gpg", O_RDONLY)", i.e., cp doesn't 
use the O_NOFOLLOW flag and so it sidesteps the filesystem bug.

Assuming it's a FUSE portal filesystem, the bug could be either in the 
Linux FUSE kernel module, or (more likely) in the user-space code. I 
assume you are using GVFS, and I reproduced a similar problem, so I 
filed a bug report with the GVFS folks here:

https://gitlab.gnome.org/GNOME/gvfs/-/issues/774

I don't see how coreutils could easily work around these filesystem bugs.




Information forwarded to bug-coreutils <at> gnu.org:
bug#74766; Package coreutils. (Tue, 10 Dec 2024 18:24:01 GMT) Full text and rfc822 format available.

Message #11 received at 74766 <at> debbugs.gnu.org (full text, mbox):

From: Bruno Haible <bruno <at> clisp.org>
To: Paul Eggert <eggert <at> cs.ucla.edu>
Cc: 74766 <at> debbugs.gnu.org
Subject: Re: bug#74766: mv cannot move a file from a Linux "portal" file system
Date: Tue, 10 Dec 2024 19:23:05 +0100
Thanks for the investigations.

Paul Eggert wrote:
> Assuming it's a FUSE portal filesystem, the bug could be either in the 
> Linux FUSE kernel module, or (more likely) in the user-space code. I 
> assume you are using GVFS

Yes, indeed:
$ mount
...
portal on /run/user/1000/doc type fuse.portal (rw,nosuid,nodev,relatime,user_id=1000,group_id=1000)
...

> and I reproduced a similar problem, so I 
> filed a bug report with the GVFS folks here:
> 
> https://gitlab.gnome.org/GNOME/gvfs/-/issues/774

Thanks!

Bruno







This bug report was last modified 188 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.