Go New Mount API — Complete GuideGo 语言 New Mount API 完全指南

fsopen · fsconfig · fsmount · move_mount — Linux 5.2+ Mount Syscalls in Practicefsopen · fsconfig · fsmount · move_mount — Linux 5.2+ 新挂载系统调用实战

Based on Linux 6.x kernel source  |  2026-07基于 Linux 6.x 内核源码  |  2026-07

1. Overview1. 概述

Linux 5.2 introduced a brand-new filesystem mounting API, replacing the traditional mount(2) with a set of file-descriptor-based system calls. The new API addresses several core pain points of the old mount():

  • Single-page limit: Old mount() had to squeeze all options into a single 4 KB page; the new API passes one parameter at a time.
  • Error diagnostics: The context fd supports read() to retrieve detailed error messages.
  • Secure isolation: You can create a "detached" mount object without attaching it to any path, and operate on it via file descriptor.
  • Flexible reconfiguration: fspick() + FSCONFIG_CMD_RECONFIGURE allows online modification of existing mount parameters.

Linux 5.2 引入了全新的文件系统挂载 API,用一组以文件描述符为基础的系统调用取代了传统的 mount(2)。新 API 解决了老 mount() 的几个核心痛点:

  • 单页限制:老 mount() 的选项必须全部塞进一个 4KB 的页面;新 API 每次只传一个参数。
  • 错误诊断:新 API 的上下文 fd 上可以 read() 读取详细的错误消息。
  • 安全隔离:可以在不挂载到任何路径的情况下创建"游离的"挂载对象,然后用文件描述符直接操作。
  • 灵活重配置:通过 fspick() + FSCONFIG_CMD_RECONFIGURE 在线修改已有挂载的参数。
Kernel version requirements: Linux 5.2+ (fsopen/fsmount), Linux 5.8+ (fspick + subset=pid). Some parameters require later versions — see individual filesystem sections. 内核版本要求:Linux 5.2+(fsopen/fsmount),Linux 5.8+(fspick + subset=pid)。部分文件系统的参数在更高版本才支持,见各文件系统说明。
📖 Primary Reference: This guide draws heavily from github.com/brauner/man-pages-md — the authoritative Markdown man pages for the new mount API maintained by Christian Brauner (Linux kernel maintainer for VFS & mount) and Aleksa Sarai (runc maintainer, author of filepath-securejoin). This repository provides fsopen(2), fsconfig(2), fsmount(2), fspick(2), move_mount(2), open_tree(2), and mount_setattr(2) — all converted from the upstream Linux man-pages project with pandoc. 📖 主要参考来源:本指南大量参考了 github.com/brauner/man-pages-md — 由 Christian Brauner(Linux 内核 VFS & mount 子系统维护者)和 Aleksa Sarai(runc 维护者,filepath-securejoin 作者)维护的新 mount API 权威 Markdown 手册。该仓库提供了 fsopen(2)、fsconfig(2)、fsmount(2)、fspick(2)、move_mount(2)、open_tree(2) 和 mount_setattr(2) 的全部手册——均为从上游 Linux man-pages 项目用 pandoc 转换而来。

Workflow Comparison工作流对比

Traditional mount(2)传统 mount(2)New API (fsopen series)新 API(fsopen 系列)
mount("proc", "/proc",
      "proc", 0,
      "hidepid=2,subset=pid")
fsfd = fsopen("proc")
fsconfig(fsfd, SET_STRING, "hidepid", "invisible")
fsconfig(fsfd, SET_STRING, "subset", "pid")
fsconfig(fsfd, CMD_CREATE)
mntfd = fsmount(fsfd)
move_mount(mntfd, "", FDCWD, "/proc")

2. Quick Start: Your First Go Program2. 快速上手:你的第一个 Go 程序

main.go — Mount tmpfs with the new APImain.go — 用新 API 挂载 tmpfs
package main

import (
    "fmt"
    "os"

    "golang.org/x/sys/unix"
)

func main() {
    // 1. Open tmpfs filesystem context
    fsfd, err := unix.Fsopen("tmpfs", unix.FSOPEN_CLOEXEC)
    if err != nil {
        fmt.Fprintf(os.Stderr, "fsopen(tmpfs): %v\n", err)
        os.Exit(1)
    }
    defer unix.Close(fsfd)

    // 2. Set parameters
    if err := unix.FsconfigSetString(fsfd, "size", "100M"); err != nil {
        fmt.Fprintf(os.Stderr, "fsconfig size: %v\n", err)
        os.Exit(1)
    }
    if err := unix.FsconfigSetString(fsfd, "mode", "1777"); err != nil {
        fmt.Fprintf(os.Stderr, "fsconfig mode: %v\n", err)
        os.Exit(1)
    }

    // 3. Create the filesystem instance
    if err := unix.FsconfigCreate(fsfd); err != nil {
        fmt.Fprintf(os.Stderr, "fsconfig create: %v\n", err)
        os.Exit(1)
    }

    // 4. Create a mount object
    mntfd, err := unix.Fsmount(fsfd, unix.FSMOUNT_CLOEXEC, 0)
    if err != nil {
        fmt.Fprintf(os.Stderr, "fsmount: %v\n", err)
        os.Exit(1)
    }
    defer unix.Close(mntfd)

    // 5. Attach to target path
    if err := unix.MoveMount(mntfd, "", unix.AT_FDCWD, "/mnt/mytmp",
        unix.MOVE_MOUNT_F_EMPTY_PATH); err != nil {
        fmt.Fprintf(os.Stderr, "move_mount: %v\n", err)
        os.Exit(1)
    }

    fmt.Println("tmpfs mounted at /mnt/mytmp")
}

3.1 fsopen — Open a Filesystem Context3.1 fsopen — 打开文件系统上下文

Creates a blank filesystem configuration context for subsequent parameter setting and mounting.

创建一个空白的文件系统配置上下文,用于后续的参数设置和挂载。

func unix.Fsopen(fsName string, flags int) (fd int, err error)
Parameter参数Description说明
fsNameFilesystem type name, e.g. "proc", "tmpfs", "ext4", etc.文件系统类型名,如 "proc""tmpfs""ext4"
flags0 or unix.FSOPEN_CLOEXEC

Requires CAP_SYS_ADMIN.

需要 CAP_SYS_ADMIN 权限。

3.2 fsconfig — Configure Parameters & Issue Commands3.2 fsconfig — 配置参数 & 执行命令

// Set a string parameter
func unix.FsconfigSetString(fd int, key, value string) error

// Set a boolean flag
func unix.FsconfigSetFlag(fd int, key string) error

// Set a file descriptor parameter
func unix.FsconfigSetFd(fd int, key string, fdValue int) error

// Set a binary blob parameter
func unix.FsconfigSetBinary(fd int, key string, value []byte) error

// Create the filesystem instance
func unix.FsconfigCreate(fd int) error

// Reconfigure an existing instance
func unix.FsconfigReconfigure(fd int) error
Go Function函数Underlying cmd底层 cmdPurpose用途
FsconfigSetString(fd, k, v)FSCONFIG_SET_STRINGSet a string parameter设置字符串参数
FsconfigSetFlag(fd, k)FSCONFIG_SET_FLAGSet a boolean flag设置布尔标志
FsconfigSetFd(fd, k, f)FSCONFIG_SET_FDPass a file descriptor传入文件描述符
FsconfigSetBinary(fd, k, v)FSCONFIG_SET_BINARYPass binary data传入二进制数据
FsconfigCreate(fd)FSCONFIG_CMD_CREATECreate the superblock创建超级块
FsconfigReconfigure(fd)FSCONFIG_CMD_RECONFIGUREOnline reconfiguration在线重配置

3.3 fsmount — Create a Mount Object3.3 fsmount — 创建挂载对象

func unix.Fsmount(fsfd int, flags int, mountAttrs int) (mntfd int, err error)
Parameter参数Description说明
fsfdContext fd returned by fsopen/fspickfsopen/fspick 返回的上下文 fd
flags0 or unix.FSMOUNT_CLOEXEC
mountAttrsMount attributes: MOUNT_ATTR_RDONLY, MOUNT_ATTR_NOSUID, MOUNT_ATTR_NODEV, MOUNT_ATTR_NOEXEC, MOUNT_ATTR_NOATIME, MOUNT_ATTR_RELATIME, etc.挂载属性:MOUNT_ATTR_RDONLYMOUNT_ATTR_NOSUIDMOUNT_ATTR_NODEVMOUNT_ATTR_NOEXECMOUNT_ATTR_NOATIMEMOUNT_ATTR_RELATIME

3.4 move_mount — Attach to Target3.4 move_mount — 挂载到目标

func unix.MoveMount(fromFd int, fromPath string, toFd int, toPath string, flags int) error

Most common usage (mount from mntfd):

最常见的用法(从 mntfd 挂载):

unix.MoveMount(mntfd, "", unix.AT_FDCWD, "/mnt/target",
    unix.MOVE_MOUNT_F_EMPTY_PATH)

3.5 fspick — Pick an Existing Instance3.5 fspick — 选择已有实例

Used for online reconfiguration of an existing mount's parameters (no unmount needed). Available since Linux 5.8.

用于在线重配置一个已有挂载点的参数(无需卸载重挂)。从 Linux 5.8 开始可用。

func unix.Fspick(dirfd int, pathName string, flags int) (fd int, err error)

4.1 proc — Process Information Filesystem4.1 proc — 进程信息文件系统

fstype namefstype 名"proc"
Typical mount常规挂载点/proc

Parameters

参数表

ParameterTypeGo CallAccepted Values / Notes接受值 / 说明
hidepidstringFsconfigSetString "off" / "0" — Everyone can see all PIDs (default).
"noaccess" / "1" — Users can only access their own PID dirs.
"invisible" / "2" — Same as 1, plus other users' dirs are hidden entirely.
"ptraceable" / "4" — Only show processes the caller can ptrace (5.8+).
"off" / "0" — 所有人可见(默认)
"noaccess" / "1" — 只能访问自己的 PID 目录
"invisible" / "2" — 同上,且其他用户目录不可见
"ptraceable" / "4" — 只显示可 ptrace 的进程 (5.8+)
subsetstringFsconfigSetString "pid" — Show only process directories, hide kcore & other system files (5.8+). "pid" — 只显示进程目录,隐藏 kcore 等系统文件 (5.8+)
gidu32FsconfigSetString Group ID exempt from hidepid restrictions (e.g. monitoring daemon's group). 不受 hidepid 限制的组 ID(如监控 daemon 所在的组)
pidnsstring / fdFsconfigSetString / FsconfigSetFd PID namespace path, e.g. /proc/1234/ns/pid (newer kernels). PID 命名空间路径,如 /proc/1234/ns/pid(较新内核)
Go: Mount secure /procGo: 挂载安全的 /proc
func mountProc(target string) error {
    fsfd, err := unix.Fsopen("proc", unix.FSOPEN_CLOEXEC)
    if err != nil { return fmt.Errorf("fsopen(proc): %w", err) }
    defer unix.Close(fsfd)

    unix.FsconfigSetString(fsfd, "hidepid", "invisible")
    unix.FsconfigSetString(fsfd, "subset", "pid")
    unix.FsconfigSetString(fsfd, "gid", "1000") // proc group
    if err := unix.FsconfigCreate(fsfd); err != nil {
        return fmt.Errorf("fsconfig create: %w", err)
    }

    mntfd, err := unix.Fsmount(fsfd, unix.FSMOUNT_CLOEXEC,
        unix.MOUNT_ATTR_NOSUID|unix.MOUNT_ATTR_NODEV|unix.MOUNT_ATTR_NOEXEC)
    if err != nil { return fmt.Errorf("fsmount: %w", err) }
    defer unix.Close(mntfd)

    return unix.MoveMount(mntfd, "", unix.AT_FDCWD, target,
        unix.MOVE_MOUNT_F_EMPTY_PATH)
}

4.2 tmpfs — In-Memory Filesystem4.2 tmpfs — 内存文件系统

fstype namefstype 名"tmpfs"

Parameters

参数表

ParameterTypeGo CallAccepted Values / Notes接受值 / 说明
sizestringFsconfigSetStringMax size, supports k/m/g/% (default 50% RAM)最大大小,支持 k/m/g/%(默认 50% RAM)
nr_blocksstringFsconfigSetStringNumber of blocks (PAGE_SIZE units), supports k/m/g块数(PAGE_SIZE 单位),支持 k/m/g
nr_inodesstringFsconfigSetStringMax inodes, 0 = unlimited最大 inode 数,0 为不限制
modeu32octFsconfigSetStringOctal permissions, e.g. "1777"八进制权限,如 "1777"
uidu32FsconfigSetStringRoot directory UID根目录 UID
gidu32FsconfigSetStringRoot directory GID根目录 GID
inode32flagFsconfigSetFlagUse 32-bit inode numbers使用 32 位 inode 号
inode64flagFsconfigSetFlagUse 64-bit inode numbers使用 64 位 inode 号
noswapflagFsconfigSetFlagDisable swap (6.4+)禁止 swap (6.4+)
hugeenumFsconfigSetString"never" / "always" / "within_size" / "advise"
mpolstringFsconfigSetStringNUMA memory policy (requires CONFIG_NUMA)NUMA 内存策略(需 CONFIG_NUMA)
quotaflagFsconfigSetFlagEnable quotas (CONFIG_TMPFS_QUOTA)启用配额(CONFIG_TMPFS_QUOTA)
usrquotaflagFsconfigSetFlagEnable user quotas启用用户配额
grpquotaflagFsconfigSetFlagEnable group quotas启用组配额
Go: Mount tmpfs with quotasGo: 挂载 tmpfs 带配额
func mountTmpfs(target, size, mode string) error {
    fsfd, err := unix.Fsopen("tmpfs", unix.FSOPEN_CLOEXEC)
    if err != nil { return err }
    defer unix.Close(fsfd)

    unix.FsconfigSetString(fsfd, "size", size)
    unix.FsconfigSetString(fsfd, "mode", mode)
    unix.FsconfigSetString(fsfd, "nr_inodes", "100000")
    unix.FsconfigSetFlag(fsfd, "noswap")

    if err := unix.FsconfigCreate(fsfd); err != nil {
        return fmt.Errorf("create tmpfs: %w", err)
    }

    mntfd, err := unix.Fsmount(fsfd, unix.FSMOUNT_CLOEXEC, unix.MOUNT_ATTR_NOSUID)
    if err != nil { return err }
    defer unix.Close(mntfd)

    return unix.MoveMount(mntfd, "", unix.AT_FDCWD, target,
        unix.MOVE_MOUNT_F_EMPTY_PATH)
}

4.3 devpts — Pseudo-Terminal Filesystem4.3 devpts — 伪终端文件系统

fstype namefstype 名"devpts"
Typical mount常规挂载点/dev/pts

Parameters

参数表

ParameterTypeGo CallNotes说明
newinstanceflagFsconfigSetFlagCreate independent devpts instance (essential for containers)创建独立的 devpts 实例(容器必备)
gidgidFsconfigSetStringPTY slave device groupPTY 从设备所属组
uiduidFsconfigSetStringPTY slave device ownerPTY 从设备所属用户
modeu32octFsconfigSetStringPTY slave permissions, e.g. "0620"PTY 从设备权限(如 "0620"
ptmxmodeu32octFsconfigSetStringptmx node permissionsptmx 节点权限
maxs32FsconfigSetStringMaximum number of PTYs最大 PTY 数量
Go: Mount devpts (container scenario)Go: 挂载 devpts(容器场景)
func mountDevpts(target string) error {
    fsfd, err := unix.Fsopen("devpts", unix.FSOPEN_CLOEXEC)
    if err != nil { return err }
    defer unix.Close(fsfd)

    unix.FsconfigSetFlag(fsfd, "newinstance")
    unix.FsconfigSetString(fsfd, "gid", "5")     // tty group
    unix.FsconfigSetString(fsfd, "mode", "0620")
    unix.FsconfigSetString(fsfd, "ptmxmode", "0000")
    unix.FsconfigSetString(fsfd, "max", "1024")

    if err := unix.FsconfigCreate(fsfd); err != nil { return err }

    mntfd, err := unix.Fsmount(fsfd, unix.FSMOUNT_CLOEXEC,
        unix.MOUNT_ATTR_NOSUID|unix.MOUNT_ATTR_NOEXEC)
    if err != nil { return err }
    defer unix.Close(mntfd)

    return unix.MoveMount(mntfd, "", unix.AT_FDCWD, target,
        unix.MOVE_MOUNT_F_EMPTY_PATH)
}

4.4 mqueue — POSIX Message Queues4.4 mqueue — POSIX 消息队列

fstype namefstype 名"mqueue"
Typical mount常规挂载点/dev/mqueue
No parameters. mqueue accepts no mount parameters — just create directly. 无参数。mqueue 不接受任何挂载参数,直接创建即可。
func mountMqueue(target string) error {
    fsfd, _ := unix.Fsopen("mqueue", unix.FSOPEN_CLOEXEC)
    defer unix.Close(fsfd)
    unix.FsconfigCreate(fsfd)
    mntfd, _ := unix.Fsmount(fsfd, unix.FSMOUNT_CLOEXEC, unix.MOUNT_ATTR_NOSUID)
    defer unix.Close(mntfd)
    return unix.MoveMount(mntfd, "", unix.AT_FDCWD, target,
        unix.MOVE_MOUNT_F_EMPTY_PATH)
}

4.5 sysfs — Kernel Device Model4.5 sysfs — 内核设备模型

No parameters. sysfs accepts no mount parameters. 无参数。sysfs 不接受任何挂载参数。
func mountSysfs(target string) error {
    fsfd, _ := unix.Fsopen("sysfs", unix.FSOPEN_CLOEXEC)
    defer unix.Close(fsfd)
    unix.FsconfigCreate(fsfd)
    mntfd, _ := unix.Fsmount(fsfd, unix.FSMOUNT_CLOEXEC,
        unix.MOUNT_ATTR_NOSUID|unix.MOUNT_ATTR_NODEV|unix.MOUNT_ATTR_NOEXEC)
    defer unix.Close(mntfd)
    return unix.MoveMount(mntfd, "", unix.AT_FDCWD, target,
        unix.MOVE_MOUNT_F_EMPTY_PATH)
}

4.6 cgroup2 — Unified Control Group v24.6 cgroup2 — 统一控制组 v2

fstype namefstype 名"cgroup2"
Typical mount常规挂载点/sys/fs/cgroup

Parameters — all flag type (FsconfigSetFlag)

参数表 — 全部为 flag 类型(FsconfigSetFlag)

ParameterTypeGo CallNotes说明
nsdelegateflagFsconfigSetFlagAllow delegation to namespaces允许委托给命名空间
favordynmodsflagFsconfigSetFlagPrefer dynamic cgroups优先动态 cgroup
memory_localeventsflagFsconfigSetFlagLocalize memory controller events内存事件本地化
memory_recursiveprotflagFsconfigSetFlagRecursive memory.min protection递归保护内存 minimum
memory_hugetlb_accountingflagFsconfigSetFlagEnable hugetlb memory accountinghugetlb 内存记账
pids_localeventsflagFsconfigSetFlagLocalize PID controller eventsPID 控制器事件本地化
Go: Mount cgroup2 (container runtime)Go: 挂载 cgroup2(容器运行时)
func mountCgroup2(target string) error {
    fsfd, err := unix.Fsopen("cgroup2", unix.FSOPEN_CLOEXEC)
    if err != nil { return err }
    defer unix.Close(fsfd)

    unix.FsconfigSetFlag(fsfd, "nsdelegate")
    unix.FsconfigSetFlag(fsfd, "memory_recursiveprot")

    if err := unix.FsconfigCreate(fsfd); err != nil {
        return fmt.Errorf("create cgroup2: %w", err)
    }

    mntfd, err := unix.Fsmount(fsfd, unix.FSMOUNT_CLOEXEC,
        unix.MOUNT_ATTR_NOSUID|unix.MOUNT_ATTR_NODEV|unix.MOUNT_ATTR_NOEXEC)
    if err != nil { return err }
    defer unix.Close(mntfd)

    return unix.MoveMount(mntfd, "", unix.AT_FDCWD, target,
        unix.MOVE_MOUNT_F_EMPTY_PATH)
}

4.7 debugfs — Kernel Debug Filesystem4.7 debugfs — 内核调试文件系统

ParameterTypeGo CallNotes说明
uiduidFsconfigSetStringRoot directory UID根目录 UID
gidgidFsconfigSetStringRoot directory GID根目录 GID
modeu32octFsconfigSetStringRoot directory permissions根目录权限

4.8 tracefs — Kernel Tracing Filesystem4.8 tracefs — 内核追踪文件系统

ParameterTypeGo CallNotes说明
uiduidFsconfigSetStringRoot directory UID根目录 UID
gidgidFsconfigSetStringRoot directory GID根目录 GID
modeu32octFsconfigSetStringRoot directory permissions根目录权限

4.9 hugetlbfs — Huge Page Filesystem4.9 hugetlbfs — 大页文件系统

ParameterTypeGo CallNotes说明
pagesizestringFsconfigSetStringPage size, e.g. "2M", "1G"页面大小,如 "2M""1G"
sizestringFsconfigSetStringMaximum size (supports k/m/g/%)最大大小(支持 k/m/g/%)
min_sizestringFsconfigSetStringMinimum preallocated size预分配最小大小
nr_inodesstringFsconfigSetStringMaximum inodes最大 inode 数
modeu32octFsconfigSetStringOctal permissions八进制权限
uiduidFsconfigSetStringRoot directory UID根目录 UID
gidgidFsconfigSetStringRoot directory GID根目录 GID

4.10 overlay — Union Filesystem4.10 overlay — 联合文件系统

fstype namefstype 名"overlay"

Parameters

参数表

ParameterTypeGo CallValues接受值
lowerdirstringFsconfigSetStringLower directory (colon-separated or repeated)下层目录(冒号分隔或多参数追加)
lowerdir+string / fdFsconfigSetString / FsconfigSetFdAppend additional lower directory追加下层目录
upperdirstring / fdFsconfigSetString / FsconfigSetFdUpper directory上层目录
workdirstring / fdFsconfigSetString / FsconfigSetFdWork directory (must be on same fs as upperdir)工作目录(必须与 upperdir 同文件系统)
redirect_direnumFsconfigSetString"off"/"follow"/"nofollow"/"on"
indexenumFsconfigSetString"on" / "off"
uuidenumFsconfigSetString"off"/"null"/"auto"/"on"
nfs_exportenumFsconfigSetString"on" / "off"
userxattrflagFsconfigSetFlagUse user xattr使用 user xattr
xinoenumFsconfigSetString"off"/"auto"/"on"
metacopyenumFsconfigSetString"on" / "off"
verityenumFsconfigSetString"off"/"on"/"require"
volatileflagFsconfigSetFlagVolatile mount (no data flush guarantee)易失性挂载(不保证数据落盘)
override_credsflag_noFsconfigSetFlagEnabled by default; pass "nooverride_creds" to disable默认启用;传递 "nooverride_creds" 禁用
default_permissionsflagFsconfigSetFlagUse kernel permission checks使用内核权限检查
fsyncenumFsconfigSetString"volatile"/"auto"/"strict"
Go: Create overlay container rootfsGo: 创建 overlay 容器 rootfs
func mountOverlay(target, lower, upper, work string) error {
    fsfd, err := unix.Fsopen("overlay", unix.FSOPEN_CLOEXEC)
    if err != nil { return err }
    defer unix.Close(fsfd)

    unix.FsconfigSetString(fsfd, "lowerdir+", lower)
    unix.FsconfigSetString(fsfd, "upperdir", upper)
    unix.FsconfigSetString(fsfd, "workdir", work)
    unix.FsconfigSetString(fsfd, "redirect_dir", "on")
    unix.FsconfigSetString(fsfd, "index", "on")
    unix.FsconfigSetString(fsfd, "xino", "auto")
    unix.FsconfigSetString(fsfd, "metacopy", "on")

    if err := unix.FsconfigCreate(fsfd); err != nil {
        return fmt.Errorf("create overlay: %w", err)
    }

    mntfd, err := unix.Fsmount(fsfd, unix.FSMOUNT_CLOEXEC, unix.MOUNT_ATTR_NOSUID)
    if err != nil { return err }
    defer unix.Close(mntfd)

    return unix.MoveMount(mntfd, "", unix.AT_FDCWD, target,
        unix.MOVE_MOUNT_F_EMPTY_PATH)
}

4.11 bpf — BPF Program Filesystem4.11 bpf — BPF 程序文件系统

ParameterTypeGo CallNotes说明
uidu32FsconfigSetStringRoot directory UID根目录 UID
gidu32FsconfigSetStringRoot directory GID根目录 GID
modeu32octFsconfigSetStringRoot directory permissions根目录权限
delegate_cmdsstringFsconfigSetStringDelegated BPF commands委派的 BPF 命令
delegate_mapsstringFsconfigSetStringDelegated BPF map types委派的 BPF map 类型
delegate_progsstringFsconfigSetStringDelegated BPF program types委派的 BPF prog 类型
delegate_attachsstringFsconfigSetStringDelegated BPF attach types委派的 BPF attach 类型

4.12 ramfs — Non-swappable RAM Filesystem4.12 ramfs — 不可换出的内存文件系统

ParameterTypeGo CallNotes说明
modeu32octFsconfigSetStringRoot permissions (octal, default "0755")根目录权限(八进制,默认 "0755"
Warning: ramfs grows unboundedly with no size limit and is not swapped out. A runaway process can exhaust all memory. Use tmpfs if you need size limits. 警告:ramfs 无限增长,不限制大小,也不会被 swap 换出。失控进程可能耗尽全部内存。需要大小限制请使用 tmpfs。

4.13 pstore — Persistent Storage Filesystem4.13 pstore — 持久存储文件系统

ParameterTypeGo CallNotes说明
kmsg_bytesu32FsconfigSetStringPer-CPU kernel log buffer size (bytes)每个 CPU 的内核日志缓冲区大小(字节)

4.14 efivarfs — EFI Variable Filesystem4.14 efivarfs — EFI 变量文件系统

ParameterTypeGo CallNotes说明
uiduidFsconfigSetStringRoot directory UID根目录 UID
gidgidFsconfigSetStringRoot directory GID根目录 GID

4.15 devtmpfs — Device Node Population4.15 devtmpfs — 设备节点填充

Special: devtmpfs delegates to tmpfs or ramfs' init_fs_context, so it actually accepts all tmpfs parameters (size, mode, uid, etc.). 特殊:devtmpfs 委托给 tmpfs 或 ramfs 的 init_fs_context,因此实际可以使用 tmpfs 的全部参数(sizemodeuid 等)。

4.16 Filesystems Without Parameters4.16 无参数文件系统

The following filesystems accept no parameters in the new mount API. Simply fsopen → FsconfigCreate → fsmount:

以下文件系统在新挂载 API 中不接受任何参数,流程简化为 fsopen → FsconfigCreate → fsmount:

fstypeMount Point挂载点Description说明
"mqueue"/dev/mqueuePOSIX message queuesPOSIX 消息队列
"sysfs"/sysKernel device model内核设备模型
"securityfs"/sys/kernel/securitySecurity module filesystem安全模块文件系统
"configfs"/sys/kernel/configKernel configuration内核配置

5.1 Scenario: Secure /proc Mount5.1 场景:安全挂载 /proc

A complete, production-grade secure /proc mount for container sandboxes:

完整的、生产级别的安全 /proc 挂载,用于容器沙箱:

Go: Secure proc mountGo: 安全 proc 挂载
// MountProcSafe mounts /proc in the most restrictive mode.
// Equivalent to: mount -t proc proc /proc -o hidepid=invisible,gid=1000,subset=pid
func MountProcSafe(target string, exemptGid int) error {
    fsfd, err := unix.Fsopen("proc", unix.FSOPEN_CLOEXEC)
    if err != nil {
        return fmt.Errorf("fsopen(proc): %w", err)
    }
    defer unix.Close(fsfd)

    if err := unix.FsconfigSetString(fsfd, "hidepid", "invisible"); err != nil {
        return err
    }
    if err := unix.FsconfigSetString(fsfd, "gid",
        strconv.Itoa(exemptGid)); err != nil {
        return err
    }
    if err := unix.FsconfigSetString(fsfd, "subset", "pid"); err != nil {
        return err
    }

    if err := unix.FsconfigCreate(fsfd); err != nil {
        return fmt.Errorf("create proc: %w", err)
    }

    mntfd, err := unix.Fsmount(fsfd, unix.FSMOUNT_CLOEXEC,
        unix.MOUNT_ATTR_NOSUID|unix.MOUNT_ATTR_NODEV|unix.MOUNT_ATTR_NOEXEC)
    if err != nil {
        return fmt.Errorf("fsmount: %w", err)
    }
    defer unix.Close(mntfd)

    return unix.MoveMount(mntfd, "", unix.AT_FDCWD, target,
        unix.MOVE_MOUNT_F_EMPTY_PATH)
}

5.2 Scenario: tmpfs with Quotas5.2 场景:带配额的 tmpfs

Go: tmpfs with quotasGo: 带配额的 tmpfs
func MountTmpfsWithQuota(target, size string, uid, gid int) error {
    fsfd, err := unix.Fsopen("tmpfs", unix.FSOPEN_CLOEXEC)
    if err != nil { return err }
    defer unix.Close(fsfd)

    unix.FsconfigSetString(fsfd, "size", size)
    unix.FsconfigSetString(fsfd, "mode", "1777")
    unix.FsconfigSetString(fsfd, "uid", strconv.Itoa(uid))
    unix.FsconfigSetString(fsfd, "gid", strconv.Itoa(gid))
    unix.FsconfigSetString(fsfd, "nr_inodes", "50000")
    unix.FsconfigSetFlag(fsfd, "noswap")

    // Enable quotas (requires CONFIG_TMPFS_QUOTA)
    unix.FsconfigSetFlag(fsfd, "usrquota")
    unix.FsconfigSetFlag(fsfd, "grpquota")

    if err := unix.FsconfigCreate(fsfd); err != nil {
        return fmt.Errorf("create tmpfs: %w", err)
    }

    mntfd, err := unix.Fsmount(fsfd, unix.FSMOUNT_CLOEXEC, unix.MOUNT_ATTR_NOSUID)
    if err != nil { return err }
    defer unix.Close(mntfd)

    return unix.MoveMount(mntfd, "", unix.AT_FDCWD, target,
        unix.MOVE_MOUNT_F_EMPTY_PATH)
}

5.3 Scenario: cgroup2 Container Runtime5.3 场景:cgroup2 容器运行时

Go: cgroup2 mount (containerd style)Go: cgroup2 挂载(containerd 风格)
func MountCgroup2(target string) error {
    fsfd, err := unix.Fsopen("cgroup2", unix.FSOPEN_CLOEXEC)
    if err != nil { return err }
    defer unix.Close(fsfd)

    unix.FsconfigSetFlag(fsfd, "nsdelegate")
    unix.FsconfigSetFlag(fsfd, "memory_recursiveprot")
    unix.FsconfigSetFlag(fsfd, "favordynmods")

    if err := unix.FsconfigCreate(fsfd); err != nil {
        return fmt.Errorf("create cgroup2: %w", err)
    }

    mntfd, err := unix.Fsmount(fsfd, unix.FSMOUNT_CLOEXEC,
        unix.MOUNT_ATTR_NOSUID|unix.MOUNT_ATTR_NODEV|unix.MOUNT_ATTR_NOEXEC)
    if err != nil { return err }
    defer unix.Close(mntfd)

    return unix.MoveMount(mntfd, "", unix.AT_FDCWD, target,
        unix.MOVE_MOUNT_F_EMPTY_PATH)
}

5.4 Scenario: Overlay Container rootfs5.4 场景:overlay 容器 rootfs

Go: overlay rootfs full exampleGo: overlay rootfs 完整示例
func MountOverlayRootFS(target, lower, upper, work string) error {
    for _, dir := range []string{target, upper, work} {
        if err := os.MkdirAll(dir, 0755); err != nil {
            return err
        }
    }

    fsfd, err := unix.Fsopen("overlay", unix.FSOPEN_CLOEXEC)
    if err != nil { return err }
    defer unix.Close(fsfd)

    unix.FsconfigSetString(fsfd, "lowerdir", lower)
    unix.FsconfigSetString(fsfd, "upperdir", upper)
    unix.FsconfigSetString(fsfd, "workdir", work)
    unix.FsconfigSetString(fsfd, "redirect_dir", "on")
    unix.FsconfigSetString(fsfd, "index", "on")
    unix.FsconfigSetString(fsfd, "xino", "auto")
    unix.FsconfigSetString(fsfd, "metacopy", "on")

    if err := unix.FsconfigCreate(fsfd); err != nil {
        return fmt.Errorf("create overlay: %w", err)
    }

    mntfd, err := unix.Fsmount(fsfd, unix.FSMOUNT_CLOEXEC, unix.MOUNT_ATTR_NOSUID)
    if err != nil { return err }
    defer unix.Close(mntfd)

    return unix.MoveMount(mntfd, "", unix.AT_FDCWD, target,
        unix.MOVE_MOUNT_F_EMPTY_PATH)
}

5.5 Scenario: Runtime Reconfiguration5.5 场景:运行时重配置 proc 参数

Go: Online reconfigure procGo: 在线重配置 proc
// ReconfigureProc modifies an existing /proc mount's hidepid setting at runtime.
// Equivalent to: mount -o remount,hidepid=invisible /proc
func ReconfigureProc(hidepid, subset string) error {
    fsfd, err := unix.Fspick(unix.AT_FDCWD, "/proc", unix.FSPICK_CLOEXEC)
    if err != nil {
        return fmt.Errorf("fspick(/proc): %w", err)
    }
    defer unix.Close(fsfd)

    if hidepid != "" {
        if err := unix.FsconfigSetString(fsfd, "hidepid", hidepid); err != nil {
            return err
        }
    }
    if subset != "" {
        if err := unix.FsconfigSetString(fsfd, "subset", subset); err != nil {
            return err
        }
    }

    return unix.FsconfigReconfigure(fsfd)
}

Appx A: fsparam Type Cheat Sheet附录 A:fsparam 类型速查

Kernel Macro内核宏Meaning含义Go Call调用
fsparam_stringString字符串FsconfigSetString
fsparam_flagBoolean flag布尔标志FsconfigSetFlag
fsparam_flag_noEnabled by default; pass "noXXX" to disable默认启用,传 "noXXX" 关闭FsconfigSetFlag("nooverride_creds")
fsparam_u3232-bit unsigned int32 位无符号整数FsconfigSetString(fd, k, "123")
fsparam_s3232-bit signed int32 位有符号整数FsconfigSetString(fd, k, "-1")
fsparam_u32octOctal u32八进制 u32FsconfigSetString(fd, k, "1777")
fsparam_enumEnumerated value枚举值FsconfigSetString(fd, k, "auto")
fsparam_file_or_stringString or fd字符串或 fdFsconfigSetString / FsconfigSetFd
fsparam_uidUser ID用户 IDFsconfigSetString(fd, k, "1000")
fsparam_gidGroup ID组 IDFsconfigSetString(fd, k, "1000")

Appx B: mountAttr Flags附录 B:mountAttr 属性标志

Constant常量Meaning含义
unix.MOUNT_ATTR_RDONLYRead-only只读
unix.MOUNT_ATTR_NOSUIDDisallow setuid/setgid禁止 setuid / setgid
unix.MOUNT_ATTR_NODEVDisallow device files禁止设备文件
unix.MOUNT_ATTR_NOEXECDisallow execution禁止执行
unix.MOUNT_ATTR_NOATIMEDo not update access times不更新访问时间
unix.MOUNT_ATTR_RELATIMERelative atime updates相对访问时间更新
unix.MOUNT_ATTR_NOSYMFOLLOWDisallow symlink following (5.10+)禁止跟随符号链接 (5.10+)
unix.MOUNT_ATTR_NODIRATIMEDo not update directory atime不更新目录访问时间

Appx C: Error Diagnostics附录 C:错误诊断

A key advantage of the new API: read detailed error messages from the context fd.

新 API 的一大优势:可以从上下文 fd 读取详细的错误消息。

func readFsconfigError(fsfd int) string {
    buf := make([]byte, 4096)
    n, err := unix.Read(fsfd, buf)
    if err != nil {
        return "(no diagnostic message)"
    }
    return string(buf[:n])
}

if err := unix.FsconfigCreate(fsfd); err != nil {
    diag := readFsconfigError(fsfd)
    return fmt.Errorf("create failed: %w [diag: %s]", err, diag)
}

Message format:

消息格式:

"e <subsystem>:<message>"  // error
"w <subsystem>:<message>"  // warning
"i <subsystem>:<message>"  // info

Appx D: Dependencies & Imports附录 D:依赖与导入

import (
    "golang.org/x/sys/unix"
)
Note: unix.Fsopen and friends require Linux 5.2+. Check kernel version at runtime with unix.KernelVersion(). Some parameters (e.g. hidepid=ptraceable, subset=pid) require 5.8+. 注意:unix.Fsopen 等函数要求 Linux 5.2+。运行时可通过 unix.KernelVersion() 检查内核版本。部分参数(如 hidepid=ptraceable、subset=pid)需要 5.8+。

Appx E: Real-World Best Practices & References附录 E:落地最佳实践与参考项目

The new mount API is not just theoretical — it has been adopted in production by major container runtimes and security libraries. Below are key real-world references that demonstrate battle-tested usage patterns.

新 mount API 并非纸上谈兵——它已被主流容器运行时和安全库在生产环境中采用。以下是经过实战检验的关键参考项目。

E.1 brauner/man-pages-md — Authoritative API DocumentationE.1 brauner/man-pages-md — 权威 API 文档

github.com/brauner/man-pages-md is the definitive reference for the new mount API man pages, maintained by Christian Brauner (Linux kernel maintainer for the VFS, mount, and namespace subsystems — essentially the person who designed this API). The repository provides:

github.com/brauner/man-pages-md 是新 mount API 手册页的权威参考,由 Christian Brauner(Linux 内核 VFS、mount 和 namespace 子系统的维护者——本质上就是这套 API 的设计者)维护。该仓库提供:

Man Page手册页Description说明
fsopen(2)Open a filesystem configuration context打开文件系统配置上下文
fsconfig(2)Set parameters and issue commands on a context在上下文上设置参数和执行命令
fsmount(2)Create a mount object from a context从上下文创建挂载对象
fspick(2)Pick an existing filesystem for reconfiguration选择已有文件系统进行重配置
move_mount(2)Move a mount to a new location将挂载移动到新位置
open_tree(2)Open a mount tree by path or fd通过路径或 fd 打开挂载树
mount_setattr(2)Change properties of a mount修改挂载属性
mount_attr(2type)Mount attribute structure reference挂载属性结构体参考
Pro tip: When you encounter an error with fsconfig, always read() from the context fd. The diagnostic messages (prefixed with e / w / i ) are documented in fsconfig(2) from this repository and are far more informative than raw errno values. 实用技巧:遇到 fsconfig 错误时,务必从上下文 fd 中 read() 诊断信息。此仓库中的 fsconfig(2) 手册记录了这些诊断消息格式(以 e / w / i 为前缀),比原始 errno 值有用得多。

E.2 runc PR #5378 — libct: Switch to New Mount APIE.2 runc PR #5378 — libct:切换到新 Mount API

opencontainers/runc#5378 is the landmark pull request where runc — the reference OCI container runtime used by Docker, Kubernetes, and containerd — migrated its libct (container library) mount infrastructure from the legacy mount(2) syscall to the new mount API. This PR demonstrates production-grade usage at scale.

opencontainers/runc#5378 是标志性的 PR——runc(Docker、Kubernetes 和 containerd 使用的 OCI 参考容器运行时)将其 libct(容器库)挂载基础设施从传统 mount(2) 系统调用迁移到新 mount API。此 PR 展示了大规模生产环境的用法。

Key Takeaways

核心要点

  1. Graceful fallback: runc probes kernel support at runtime and falls back to legacy mount(2) on older kernels — essential for portability across Linux distributions.
  2. 优雅降级:runc 在运行时探测内核支持,并在旧内核上回退到传统 mount(2) ——这对跨 Linux 发行版的可移植性至关重要。
  3. Detailed error diagnostics: The PR leverages read() on the fs_context fd to extract human-readable error messages, significantly improving debuggability compared to legacy mount(2) which only returns EINVAL.
  4. 详细的错误诊断:该 PR 利用 fs_context fd 上的 read() 提取人类可读的错误消息,相比传统 mount(2) 仅返回 EINVAL,显著提升了可调试性。
  5. Unified mount helper: The PR introduces a common mount wrapper that handles the full fsopen → fsconfig → fsmount → move_mount sequence, ensuring consistent error handling across all filesystem types (proc, tmpfs, devpts, cgroup2, sysfs, etc.).
  6. 统一挂载辅助函数:该 PR 引入了通用挂载包装器,处理完整的 fsopen → fsconfig → fsmount → move_mount 序列,确保所有文件系统类型(proc、tmpfs、devpts、cgroup2、sysfs 等)的错误处理一致。
  7. Idempotent reconfiguration: Uses fspick() + FSCONFIG_CMD_RECONFIGURE for online parameter changes without unmounting — critical for long-running container processes.
  8. 幂等重配置:使用 fspick() + FSCONFIG_CMD_RECONFIGURE 实现在线参数修改而不卸载——这对长时间运行的容器进程至关重要。
Pattern: Graceful kernel probe (runc style)模式:优雅的内核探测(runc 风格)
// Probe whether the new mount API is available on this kernel.
// If not, fall back to unix.Mount (legacy mount(2)).
var useNewMountAPI bool

func init() {
    // Try fsopen on a trivial filesystem
    fsfd, err := unix.Fsopen("tmpfs", unix.FSOPEN_CLOEXEC)
    if err != nil {
        useNewMountAPI = false
        return
    }
    unix.Close(fsfd)
    useNewMountAPI = true
}

func mountSafe(source, target, fstype string, flags uintptr, data string) error {
    if useNewMountAPI {
        return mountNew(source, target, fstype, flags, data)
    }
    return unix.Mount(source, target, fstype, flags, data)
}

E.3 runc PR #4448 — Overlayfs Write-Protect for /proc/self/exeE.3 runc PR #4448 — 用 overlayfs 写保护 /proc/self/exe

opencontainers/runc#4448 by Aleksa Sarai (cyphar) demonstrates an elegant security hardening technique: using the new mount API to create an overlayfs mount that write-protects a container runtime's own /proc/self/exe, preventing attackers from modifying the runtime binary even if they gain write access. This is a beautiful example of the new mount API's ability to create complex, detached mount trees without polluting the global namespace.

opencontainers/runc#4448Aleksa Sarai(cyphar)开发,展示了一种精巧的安全加固技术:使用新 mount API 创建 overlayfs 挂载来写保护容器运行时自身的 /proc/self/exe,防止攻击者即使获得写权限后修改运行时二进制文件。这是新 mount API 在不污染全局命名空间的情况下创建复杂、游离挂载树的绝佳范例。

Key Takeaways

核心要点

  1. Detached mounts for security: Creates an overlay mount object without ever attaching it to the global VFS, then uses it purely through file descriptors — a pattern impossible with legacy mount(2).
  2. 安全游离挂载:创建 overlay 挂载对象而从不附加到全局 VFS,然后纯粹通过文件描述符使用它——这是传统 mount(2) 无法实现的模式。
  3. Opportunistic use: Gracefully falls back to a memfd-based approach when overlayfs isn't available or when the new mount API isn't supported — never breaks existing functionality.
  4. 机会主义使用:当 overlayfs 不可用或新 mount API 不支持时优雅降级到基于 memfd 的方式——从不破坏现有功能。
  5. Minimal privilege surface: Uses overlayfs read-only lowerdir to create a tamper-proof view of the runtime binary, reducing the attack surface even if the attacker has root in the container.
  6. 最小化权限面:使用 overlayfs 只读 lowerdir 创建运行时二进制的防篡改视图,即使攻击者在容器中拥有 root 权限也能减小攻击面。
Pattern: Detached overlay for binary sealing (runc style)模式:游离 overlay 用于二进制密封(runc 风格)
func sealExecutable(exePath string) (*os.File, error) {
    fsfd, err := unix.Fsopen("overlay", unix.FSOPEN_CLOEXEC)
    if err != nil {
        return nil, err // Caller should fall back to memfd
    }
    defer unix.Close(fsfd)

    // lowerdir = the original executable (read-only)
    unix.FsconfigSetString(fsfd, "lowerdir", filepath.Dir(exePath))
    // workdir = ephemeral, unused since we're read-only
    unix.FsconfigSetString(fsfd, "workdir", workDir)

    if err := unix.FsconfigCreate(fsfd); err != nil {
        return nil, err
    }

    // Get a detached mount — never attached to VFS!
    mntfd, err := unix.Fsmount(fsfd, unix.FSMOUNT_CLOEXEC,
        unix.MOUNT_ATTR_RDONLY)
    if err != nil {
        return nil, err
    }

    // Open the sealed binary from the detached mount
    fd, err := unix.Openat(mntfd, filepath.Base(exePath),
        unix.O_RDONLY|unix.O_CLOEXEC, 0)
    unix.Close(mntfd)
    if err != nil {
        return nil, err
    }

    return os.NewFile(uintptr(fd), "sealed-exe"), nil
}

E.4 cyphar/filepath-securejoin — Secure Path Operations via Mount APIE.4 cyphar/filepath-securejoin — 基于 Mount API 的安全路径操作

github.com/cyphar/filepath-securejoin by Aleksa Sarai is the gold standard for how the new mount API should be used in security-critical Go code. Originally a safer alternative to filepath.Join, the library has evolved to deeply integrate with the new mount API (openat2, fsopen, open_tree) to eliminate entire classes of TOCTOU (Time-of-Check-Time-of-Use) vulnerabilities that plague path-based APIs.

github.com/cyphar/filepath-securejoinAleksa Sarai 开发,是新 mount API 在安全关键 Go 代码中使用的标杆。最初作为 filepath.Join 的安全替代品,该库已深度集成了新 mount API(openat2、fsopen、open_tree),以消除困扰基于路径 API 的各类 TOCTOU(检查时间-使用时间)漏洞。

Architecture & Best Practices

架构与最佳实践

Principle原则Implementation实现
Fd over paths 文件描述符优于路径 New API (OpenInRoot, MkdirAll) returns *os.File (O_PATH fd) instead of string paths, eliminating TOCTOU races between path resolution and use. 新 API(OpenInRootMkdirAll)返回 *os.File(O_PATH fd)而非字符串路径,消除了路径解析与使用之间的 TOCTOU 竞态。
Progressive enhancement 渐进增强 Uses openat2(RESOLVE_IN_ROOT) when available (Linux 5.6+), falls back to userspace resolution. Privileged callers additionally use fsopen/open_tree for /proc attack resistance. openat2(RESOLVE_IN_ROOT) 时(Linux 5.6+)使用它,否则回退到用户空间解析。特权调用者还额外使用 fsopen/open_tree 来防御 /proc 攻击。
O_PATH separation O_PATH 分离 Separates O_PATH fd acquisition (OpenInRoot) from actual file opening (Reopen), preventing accidental access to "bad" inodes (fifos, device nodes) that could cause DoS. 将 O_PATH fd 获取(OpenInRoot)与实际文件打开(Reopen)分离,防止意外访问可能导致 DoS 的"坏"inode(fifo、设备节点)。
Magic-link defense Magic-link 防御 Uses fsopen + open_tree to create a private mount of the rootfs, immunizing path resolution against manipulated /proc magic-links (e.g. /proc/self/fd/N). 使用 fsopen + open_tree 创建 rootfs 的私有挂载,使路径解析免疫于被篡改的 /proc magic-link(如 /proc/self/fd/N)。
Licensing hygiene 许可证卫生 Per-file SPDX headers: BSD-3-Clause for Docker-derived code, MPL-2.0 for libpathrs-derived new API. A model for multi-source open-source projects. 每个文件 SPDX 许可证标识头:Docker 派生代码使用 BSD-3-Clause,libpathrs 派生新 API 使用 MPL-2.0。多来源开源项目的典范。
Pattern: Secure open in rootfs (filepath-securejoin style)模式:在 rootfs 中安全打开(filepath-securejoin 风格)
// OpenInRoot safely opens a path within a rootfs.
// This is a simplified illustration of filepath-securejoin's approach.
func OpenInRoot(root, unsafePath string) (*os.File, error) {
    // Phase 1: Open the root directory
    rootFd, err := unix.Open(root, unix.O_PATH|unix.O_CLOEXEC, 0)
    if err != nil {
        return nil, fmt.Errorf("open root %s: %w", root, err)
    }
    defer unix.Close(rootFd)

    // Phase 2: If we have privileges, create a private mount
    // of root to protect against /proc magic-link attacks.
    // This is what filepath-securejoin does opportunistically:
    //   fsfd = fsopen(rootFd)
    //   open_tree to get a private copy
    //   use the private fd for the rest of the resolution

    // Phase 3: Resolve the path using openat2(RESOLVE_IN_ROOT)
    // on Linux 5.6+, or manual component-wise resolution otherwise
    how := &unix.OpenHow{
        Flags:   unix.O_PATH | unix.O_CLOEXEC | unix.O_NOFOLLOW,
        Mode:    0,
        Resolve: unix.RESOLVE_IN_ROOT | unix.RESOLVE_NO_MAGICLINKS,
    }
    fd, err := unix.Openat2(rootFd, unsafePath, how)
    if err != nil {
        return nil, fmt.Errorf("openat2: %w", err)
    }

    return os.NewFile(uintptr(fd), unsafePath), nil
}
Why this matters: Before filepath-securejoin's new API, container runtimes were forced to choose between security (complex fd-based code) and simplicity (path-based code vulnerable to TOCTOU). The new mount API — combined with openat2 — finally makes it possible to have both security and clean, maintainable code. 为什么重要:在 filepath-securejoin 的新 API 之前,容器运行时必须在安全(复杂的基于 fd 的代码)和简单(基于路径的代码,但易受 TOCTOU 攻击)之间做出选择。新 mount API ——与 openat2 结合——终于让安全且简洁、可维护的代码成为可能。

E.5 How These Projects Fit TogetherE.5 这些项目如何协同

These four references form a complete picture of the new mount API ecosystem:

这四个参考形成了新 mount API 生态的完整图景:

Project项目Role角色Author作者
brauner/man-pages-md Reference documentation — canonical man pages for every syscall 参考文档 — 每个系统调用的权威手册 Christian Brauner (kernel maintainer) Christian Brauner(内核维护者)
runc#5378 Production adoption — how a major runtime migrates its mount infrastructure 生产落地 — 主流运行时如何迁移挂载基础设施 lifubang (runc maintainer) lifubang(runc 维护者)
runc#4448 Security hardening — detached overlay mounts without polluting VFS 安全加固 — 不污染 VFS 的游离 overlay 挂载 Aleksa Sarai (cyphar, runc maintainer) Aleksa Sarai(cyphar,runc 维护者)
filepath-securejoin Security library — fd-based path ops eliminating TOCTOU 安全库 — 基于 fd 的路径操作,消除 TOCTOU Aleksa Sarai (cyphar, runc maintainer) Aleksa Sarai(cyphar,runc 维护者)

Recommended reading order: Start with brauner/man-pages-md for authoritative API reference → study runc#5378 for real-world migration patterns → explore runc#4448 for advanced detached-mount techniques → dive into filepath-securejoin for security-first API design principles.

推荐阅读顺序:从 brauner/man-pages-md 入手了解权威 API 参考 → 研究 runc#5378 学习真实迁移模式 → 探索 runc#4448 掌握高级游离挂载技巧 → 深入 filepath-securejoin 理解安全优先的 API 设计原则。


Go New Mount API — Complete Guide  ·  Based on Linux 6.x kernel source  ·  References: brauner/man-pages-md, runc, filepath-securejoin  ·  2026-07 Go 语言 New Mount API 完全指南  ·  基于 Linux 6.x 内核源码  ·  参考资料:brauner/man-pages-md、runc、filepath-securejoin  ·  2026-07