AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / unix / 问题 / 463076
Accepted
sourcejedi
sourcejedi
Asked: 2018-08-17 13:29:15 +0800 CST2018-08-17 13:29:15 +0800 CST 2018-08-17 13:29:15 +0800 CST

为什么非特权用户不能嵌套 FUSE 挂载,但他们可以使用 root_squash 在 NFS 中挂载 FUSE?

  • 772
$ 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。这些分布在年龄上非常相似,但可能存在一些差异。

nfs fuse
  • 1 1 个回答
  • 1995 Views

1 个回答

  • Voted
  1. Best Answer
    sourcejedi
    2018-08-17T13:29:15+08:002018-08-17T13:29:15+08:00

    首先,考虑 FUSE 的实现no_allow_others。

    它要求有效的、真实的和保存的 UID(用户 ID)都匹配。(对于 GID 也是如此)。这是故意阻止 set-UID 程序访问挂载。

    https://github.com/torvalds/linux/blob/v4.18/fs/fuse/dir.c#L1024

    调用用户控制的文件系统为文件系统
    守护进程提供了对当前进程的类似 ptrace 的功能。这
    意味着,文件系统守护进程能够记录执行的确切
    文件系统操作,并且还可以
    以其他不可能的方式控制请求者进程的行为。例如
    ,它可以将操作延迟任意时间长度,从而允许
    针对请求者的 DoS。

    现在让我们追踪是什么fusermount。我们可以试试看

    strace -f bindfs ...
    

    和

    sudo perf trace -o trace.txt -a sleep 2; sleep 1; bindfs ...
    

    第一个遇到致命错误“Permission denied”,因为 set-UID root 在strace. 第二个成功了,但是不能显示路径等字符串参数。我认为这两个跟踪显示相同的一般代码路径,直到致命错误。这意味着我们可以使用strace结果来填充缺失的字符串参数。

    结果中的最后一个调用strace是:

    [pid 30609] mount("/home/alan-sysop/mnt", ".", "fuse", MS_NOSUID|MS_NODEV, "default_permissions,fd=5,rootmod"...) = -1 EPERM (Operation not permitted)
    

    有趣的! "."表示当前目录。所以fusermount一定已经在挂载点上运行了......不知何故。此技巧有时可用于访问当前无法使用绝对路径访问的目录。

    如果我们向上滚动,我们可以看到fusermount确实更改到了这个目录。它还与一些与 UID 相关(和 GID 相关)的系统调用一起跳舞。

    [pid 30609] getuid()                    = 1000
    [pid 30609] setfsuid(1000)              = 1000
    [pid 30609] getgid()                    = 1000
    [pid 30609] setfsgid(1000)              = 1000
    [pid 30609] openat(AT_FDCWD, "/etc/fuse.conf", O_RDONLY) = 6
    ...
    [pid 30609] lstat("/home/alan-sysop/mnt", {st_mode=S_IFDIR|0775, st_size=4096, ...}) = 0
    [pid 30609] getuid()                    = 1000
    [pid 30609] chdir("/home/alan-sysop/mnt") = 0
    [pid 30609] lstat(".", {st_mode=S_IFDIR|0775, st_size=4096, ...}) = 0
    [pid 30609] access(".", W_OK)           = 0
    [pid 30609] getuid()                    = 1000
    [pid 30609] setfsuid(1000)              = 1000
    [pid 30609] setfsgid(1000)              = 1000
    

    strace会话中的 UID 结果是“错误的” 。perf trace我们可以在会话中更好地看到 UID 舞蹈部分。(为了便于阅读,我删除了最左边的列)。

    getuid(                                                               ) = 1000
    setfsuid(uid: 1000                                                    ) = 0
    getgid(                                                               ) = 1000
    setfsgid(gid: 1000                                                    ) = 1000
    openat(dfd: CWD, filename: 0xa428e2bc                                 ) = 6
        ...
    close(fd: 6                                                           ) = 0
    lstat(filename: 0xa63882a0, statbuf: 0x7ffe7bd4f6d0                   ) = 0
    getuid(                                                               ) = 1000
    chdir(filename: 0xa63882a0                                            ) = 0
    lstat(filename: 0xa428eca5, statbuf: 0x7ffe7bd4f6d0                   ) = 0
    access(filename: 0xa428eca5, mode: W                                  ) = 0
    getuid(                                                               ) = 1000
    setfsuid(                                                             ) = 1000
    setfsgid(gid: 1000                                                    ) = 1000
    getuid(                                                               ) = 1000
    

    这些setfsuid()调用在fusermount.cdrop_privs()的andrestore_privs()函数中。

    该chdir()调用被偷偷地隐藏在被调用的函数中check_perm()。

    结论

    为什么这适用于 NFS?答:因为 NFS 会查看已设置为非根 UID的fsuid(and )。fsgid

    为什么这在 FUSE 上不起作用,除非你有allow_others?答:因为 FUSE 检查的是“真实”的 UID,而不是fsuid.

    • 0

相关问题

  • WD MyCloud NFS 挂载到华硕 Merlin 路由器:NFS 挂载故障排除:“没有这样的设备”

  • 如何查询 sar(sysstat) 超过一天的数据点

  • 将 root 挂载为 overlayfs

  • systemd-networkd 启动后 nfs 启动挂起

  • 无法在 Alpine Linux LXC 上启动 NFS 服务器

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    如何将 GPG 私钥和公钥导出到文件

    • 4 个回答
  • Marko Smith

    ssh 无法协商:“找不到匹配的密码”,正在拒绝 cbc

    • 4 个回答
  • Marko Smith

    我们如何运行存储在变量中的命令?

    • 5 个回答
  • Marko Smith

    如何配置 systemd-resolved 和 systemd-networkd 以使用本地 DNS 服务器来解析本地域和远程 DNS 服务器来解析远程域?

    • 3 个回答
  • Marko Smith

    如何卸载内核模块“nvidia-drm”?

    • 13 个回答
  • Marko Smith

    dist-upgrade 后 Kali Linux 中的 apt-get update 错误 [重复]

    • 2 个回答
  • Marko Smith

    如何从 systemctl 服务日志中查看最新的 x 行

    • 5 个回答
  • Marko Smith

    Nano - 跳转到文件末尾

    • 8 个回答
  • Marko Smith

    grub 错误:你需要先加载内核

    • 4 个回答
  • Marko Smith

    如何下载软件包而不是使用 apt-get 命令安装它?

    • 7 个回答
  • Martin Hope
    rocky 如何将 GPG 私钥和公钥导出到文件 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Wong Jia Hau ssh-add 返回:“连接代理时出错:没有这样的文件或目录” 2018-08-24 23:28:13 +0800 CST
  • Martin Hope
    Evan Carroll systemctl 状态显示:“状态:降级” 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim 我们如何运行存储在变量中的命令? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S 为什么 /dev/null 是一个文件?为什么它的功能不作为一个简单的程序来实现? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 如何从 systemctl 服务日志中查看最新的 x 行 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - 跳转到文件末尾 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla 为什么真假这么大? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST
  • Martin Hope
    Bagas Sanjaya 为什么 Linux 使用 LF 作为换行符? 2017-12-20 05:48:21 +0800 CST

热门标签

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve