$ mkdir mnt
$ bindfs /tmp mnt
fusermount: option allow_other only allowed if 'user_allow_other' is set in /etc/fuse.conf
$ bindfs --no-allow-other /tmp mnt
$ mkdir /tmp/mnt2
$ bindfs --no-allow-other /tmp mnt/mnt2
fusermount: bad mount point /home/alan/mnt/mnt2: Permission denied
fusermount
失败,因为它以不同的用户身份运行。
$ sudo ls mnt/
ls: cannot open directory 'mnt/': Permission denied
fusermount
是 set-uid root
。这是必需的,因为非特权用户无法使用mount()
系统调用。
$ ls -l $(which fusermount)
-rwsr-xr-x. 1 root root 32848 Feb 7 2018 /usr/bin/fusermount
^ set-uid bit
但是。据报道,FUSE 可以在 NFS 主目录中使用。即使主目录具有模式700
- 只能由拥有用户访问。NFS 服务器默认为root_squash
,这意味着“root 用户将具有与用户nobody 相同的访问权限”。
为什么这两种情况不同?
我在 Fedora 28 上进行测试。关于 NFS 的报告来自 Ubuntu 18.04。这些分布在年龄上非常相似,但可能存在一些差异。
首先,考虑 FUSE 的实现
no_allow_others
。它要求有效的、真实的和保存的 UID(用户 ID)都匹配。(对于 GID 也是如此)。这是故意阻止 set-UID 程序访问挂载。
https://github.com/torvalds/linux/blob/v4.18/fs/fuse/dir.c#L1024
现在让我们追踪是什么
fusermount
。我们可以试试看和
第一个遇到致命错误“Permission denied”,因为 set-UID root 在
strace
. 第二个成功了,但是不能显示路径等字符串参数。我认为这两个跟踪显示相同的一般代码路径,直到致命错误。这意味着我们可以使用strace
结果来填充缺失的字符串参数。结果中的最后一个调用
strace
是:有趣的!
"."
表示当前目录。所以fusermount
一定已经在挂载点上运行了......不知何故。此技巧有时可用于访问当前无法使用绝对路径访问的目录。如果我们向上滚动,我们可以看到
fusermount
确实更改到了这个目录。它还与一些与 UID 相关(和 GID 相关)的系统调用一起跳舞。strace
会话中的 UID 结果是“错误的” 。perf trace
我们可以在会话中更好地看到 UID 舞蹈部分。(为了便于阅读,我删除了最左边的列)。这些
setfsuid()
调用在fusermount.cdrop_privs()
的andrestore_privs()
函数中。该
chdir()
调用被偷偷地隐藏在被调用的函数中check_perm()
。结论
为什么这适用于 NFS?答:因为 NFS 会查看已设置为非根 UID的
fsuid
(and )。fsgid
为什么这在 FUSE 上不起作用,除非你有
allow_others
?答:因为 FUSE 检查的是“真实”的 UID,而不是fsuid
.