FUSE 直通

简介

FUSE (用户空间文件系统) 直通是一种旨在提高 FUSE 文件系统 I/O 操作性能的功能。 通常,FUSE 操作涉及内核和用户空间 FUSE 守护进程之间的通信,这可能会产生开销。 直通允许对 FUSE 文件执行的某些操作绕过用户空间守护进程,并由内核直接在底层“后备文件”上执行。

这是通过 FUSE 守护程序向 FUSE 内核模块注册文件描述符(指向较低文件系统上的后备文件)来实现的。 然后,内核接收此注册后备文件的标识符 (backing_id)。 当随后打开 FUSE 文件时,FUSE 守护程序可以在其对 OPEN 请求的响应中包含此 backing_id 并设置 FOPEN_PASSTHROUGH 标志。 这为特定操作建立了直接链接。

目前,直通支持的操作包括 read(2)/write(2)(通过 read_iter/write_iter)、splice(2)mmap(2)

启用直通

要使用 FUSE 直通:

  1. 必须编译启用 CONFIG_FUSE_PASSTHROUGH 的 FUSE 文件系统。

  2. FUSE 守护程序必须在 FUSE_INIT 握手期间协商 FUSE_PASSTHROUGH 功能并指定其所需的 max_stack_depth

  3. (特权)FUSE 守护程序在其连接文件描述符(例如,/dev/fuse)上使用 FUSE_DEV_IOC_BACKING_OPEN ioctl 来注册后备文件描述符并获取 backing_id

  4. 在处理 FUSE 文件的 OPENCREATE 请求时,守护程序在 fuse_open_out::open_flags 中设置 FOPEN_PASSTHROUGH 标志,并在 fuse_open_out::backing_id 中提供相应的 backing_id

  5. 当不再需要将后备文件用于直通设置时,FUSE 守护程序应最终调用 FUSE_DEV_IOC_BACKING_CLOSE 并提供 backing_id 以释放内核对后备文件的引用。

权限要求

目前,设置直通功能要求 FUSE 守护进程具有 CAP_SYS_ADMIN 功能。 此要求源于一些正在积极讨论和处理的安全和资源管理方面的考虑因素。 以下详细说明了此限制的主要原因。

资源核算和可见性

直通的核心机制涉及 FUSE 守护程序打开指向后备文件的文件描述符,并通过 FUSE_DEV_IOC_BACKING_OPEN ioctl 向 FUSE 内核模块注册该文件描述符。 此 ioctl 返回与内核内部 struct fuse_backing 对象关联的 backing_id,该对象保存对后备 struct file 的引用。

一个重要的担忧是,FUSE 守护程序可以在注册后关闭其自己的指向后备文件的文件描述符。 但是,只要 struct filebacking_id 关联(或者随后,与处于直通模式的打开的 FUSE 文件关联),内核仍将通过 struct fuse_backing 对象保持对 struct file 的引用。

对于非特权 FUSE 守护进程,此行为会导致两个主要问题:

  1. 对 lsof 和其他检查工具不可见:一旦 FUSE 守护程序关闭其文件描述符,内核保留的已打开后备文件将变为“隐藏”。 诸如 lsof 之类的标准工具(通常检查进程文件描述符表)将无法识别系统代表 FUSE 文件系统仍打开该文件。 这使得系统管理员难以跟踪资源使用情况或调试与打开的文件相关的问题(例如,防止卸载)。

  2. 绕过 RLIMIT_NOFILE:FUSE 守护程序进程受到资源限制,包括打开的文件描述符的最大数量 (RLIMIT_NOFILE)。 如果非特权守护程序可以注册后备文件,然后关闭其自己的 FD,则它可能会导致内核持有无限数量的已打开 struct file 引用,而这些引用不会计入守护程序的 RLIMIT_NOFILE。 这可能会因耗尽系统范围内的文件资源而导致拒绝服务 (DoS)。

CAP_SYS_ADMIN 要求充当针对这些问题的安全措施,将此强大功能限制为可信进程。

注意io_uring 通过公开其“固定文件”来解决此类似问题,这些文件通过 fdinfo 可见,并在注册用户的 RLIMIT_NOFILE 下进行核算。

文件系统堆叠和关闭循环

另一个担忧与非特权用户可以设置直通时创建复杂且有问题的文件系统堆叠场景的可能性有关。 FUSE 直通文件系统可能会使用位于以下位置的后备文件:

  • 同一 FUSE 文件系统上。

  • 在另一个文件系统(如 OverlayFS)上,该文件系统本身可能具有作为 FUSE 文件系统的上层或下层。

这些配置可能会创建依赖循环,尤其是在文件系统关闭或卸载序列期间,从而导致死锁或系统不稳定。 这在概念上类似于 LOOP_SET_FD ioctl 相关的风险,它也需要 CAP_SYS_ADMIN

为了缓解这种情况,FUSE 直通已经结合了基于文件系统堆叠深度(sb->s_stack_depthfc->max_stack_depth)的检查。 例如,在 FUSE_INIT 握手期间,FUSE 守护程序可以协商其支持的 max_stack_depth。 通过 FUSE_DEV_IOC_BACKING_OPEN 注册后备文件时,内核会检查后备文件的文件系统堆叠深度是否在允许的限制内。

CAP_SYS_ADMIN 要求提供了额外的安全层,确保只有特权用户才能创建这些潜在的复杂堆叠安排。

一般安全态势

作为一项通用原则,对于允许用户空间指示内核基于用户提供的文件描述符代表其执行直接操作的新内核功能,从更高的权限要求(如 CAP_SYS_ADMIN)开始是一种保守且常见的安全实践。 这允许在使用和测试该功能的同时,进一步评估和解决安全影响。