当前位置:首页 > 文章列表 > 文章 > linux > Linux mount_setattr 怎样批量调整挂载属性

Linux mount_setattr 怎样批量调整挂载属性

来源:17golang原创 2026-11-03 13:25:01 0浏览 收藏

Linux 的 mount_setattr() 不是修改目录中每个文件的工具,而是修改一个挂载对象,或者由它派生出的整棵挂载树。需要把目录变成只读、禁止执行、禁止设备访问,或调整挂载传播类型时,可以把目标路径、属性集合和递归范围一次交给内核处理。

官方文档地址:https://www.man7.org/linux/man-pages/man2/mount_setattr.2.html

批量调整的关键是先决定“改哪一个挂载对象”,再分别填写 attr_clr、attr_set 和 propagation。AT_RECURSIVE 负责把同一组变化扩展到挂载树;它不会把普通目录递归变成挂载点,也不会替代权限检查。
  • 单个挂载点:用 dirfd + path 定位,flags 通常为 0。
  • 整棵挂载树:在定位参数上加入 AT_RECURSIVE。
  • 设置和清除:把要移除的位放进 attr_clr,把要打开的位放进 attr_set。
  • 兼容性:结构体必须零填充,并把 size 传成调用方实际使用的结构体版本大小。

先区分挂载对象属性与文件系统参数

Linux 的挂载选项不只有一层。挂载对象属性附着在某个 mount object 上,同一个文件系统实例可以派生出多个具有不同属性的挂载对象;文件系统参数则更接近 superblock,影响从同一文件系统实例派生出的对象。mount_setattr() 主要处理前者,fsconfig() 等新 Mount API 负责另一层。

因此,下面这些任务适合用 mount_setattr() 组织:

目标对应字段说明
变成只读attr_set 中的 MOUNT_ATTR_RDONLY作用在挂载对象,不等价于修改文件系统实例参数。
禁止执行或设备访问MOUNT_ATTR_NOEXEC、MOUNT_ATTR_NODEV适合按挂载边界表达运行时限制。
修改传播类型propagation从 MS_PRIVATE、MS_SHARED、MS_SLAVE、MS_UNBINDABLE 中选择一个。
配置文件系统自身参数不要只依赖 mount_setattr()这属于另一层语义,应使用相应 Mount API 或文件系统工具。
mount_setattr 修改挂载对象属性并与文件系统参数分层的静态结构图
图1:挂载对象属性与文件系统参数的静态边界说明图,不是终端截图或运行证据。

按 dirfd、path 和 flags 定位目标

系统调用原型是 mount_setattr(int dirfd, const char *path, unsigned int flags, struct mount_attr *attr, size_t size)。其中 dirfd 与 path 共同确定目标,flags 改变路径解析和递归范围。

  • dirfd=AT_FDCWD 时,相对路径从当前工作目录解析;也可以传入一个目录文件描述符,让路径解析相对于该目录。
  • path 指向挂载点或挂载树的入口,不是任意普通目录。
  • AT_EMPTY_PATH 配合空路径时,目标由 dirfd 指向的挂载对象决定。
  • AT_RECURSIVE 把变化扩展到整个挂载树;没有它时只处理目标挂载对象。
  • AT_SYMLINK_NOFOLLOW 和 AT_NO_AUTOMOUNT 用于收紧路径解析行为,是否需要它们要结合调用场景。
#include 
#include 
#include 
#include 

static int make_tree_readonly(const char *mount_path) {
    struct mount_attr attr = {0};

    // 只设置挂载对象的只读属性,不修改目录中的单个文件权限。
    attr.attr_set = MOUNT_ATTR_RDONLY;

    // AT_RECURSIVE 让同一组属性作用于目标挂载树。
    return (int)syscall(SYS_mount_setattr,
                        AT_FDCWD, mount_path, AT_RECURSIVE,
                        &attr, sizeof(attr));
}

这个例子表达的是系统调用参数关系。实际编译时要确认 libc、内核头文件和目标架构提供了 SYS_mount_setattr、struct mount_attr 及对应属性常量;如果调用返回 -1,应立即保存 errno,不要把失败误判为部分成功。

用 attr_set 与 attr_clr 组织属性变更

attr_clr 与 attr_set 是两个不同方向的位集合。内核会先清除 attr_clr 指定的属性,再设置 attr_set 指定的属性,因此同一个位不应同时放入两边。

#include 

static void prepare_sandbox_attributes(struct mount_attr *attr) {
    *attr = (struct mount_attr){0};

    // 先清掉可能残留的执行和设备访问能力,再设置只读属性。
    attr->attr_clr = MOUNT_ATTR_NOEXEC | MOUNT_ATTR_NODEV;
    attr->attr_set = MOUNT_ATTR_RDONLY | MOUNT_ATTR_NOEXEC | MOUNT_ATTR_NODEV;

    // propagation 为 0 表示不改变传播类型,避免把属性修改和传播策略混在一起。
    attr->propagation = 0;
}

上面的写法展示了“清除旧状态、设置目标状态”的意图。若只要求最终状态为只读且禁止执行,可以只在 attr_set 写入对应位;若需要把可能存在的旧 atime 设置一并替换,则必须按文档要求让 attr_clr 覆盖 MOUNT_ATTR__ATIME,不能只清除其中一小段枚举位。

同一组清除和设置请求重复执行后,属性状态应保持不变。这使得管理程序可以把变更设计成幂等操作,但幂等不代表可以忽略权限、挂载树中某个节点的锁定状态或正在进行的写入。

按单点、递归和传播需求选择调用方式

“批量”并不只有一种含义。最简单的是给一棵挂载树统一设置只读;更复杂的场景还会同时处理递归范围和传播策略。建议把三类选择拆开审阅:

场景flagsattr 内容适用判断
只改入口挂载点0attr_set 或 attr_clr子挂载点必须保持独立策略时使用。
整棵树只读AT_RECURSIVE设置 MOUNT_ATTR_RDONLY容器或沙箱的挂载树需要统一收紧时使用。
整棵树禁止执行和设备访问AT_RECURSIVE设置 MOUNT_ATTR_NOEXEC | MOUNT_ATTR_NODEV把运行时访问边界放在挂载层表达。
改变传播按路径解析需要选择设置一个 propagation 值传播类型互斥,不要同时填写多个。
mount_setattr 通过入口挂载点和 AT_RECURSIVE 扩展到挂载树的静态关系图
图2:单个挂载对象、递归挂载树和传播类型的静态关系图,不是实际系统截图。

按内核约束和权限边界落地

调用能否成功,除了字段是否填对,还取决于目标挂载对象、挂载命名空间、底层文件系统和当前权限。把错误码按原因分类,排查速度会比只打印“operation failed”更快。

错误常见原因处理方向
EINVAL目标不是挂载点、flags 或属性位不受支持、传播类型组合无效。先缩小到单个挂载点,再逐项加入 flags 和属性位。
EBUSY尝试设置只读或 ID 映射时,挂载仍有不允许的写入状态。检查打开的写句柄和挂载对象状态,不把它当成普通路径错误。
EPERM属性被锁定,或调用者在对应用户命名空间中缺少能力。确认挂载命名空间、用户命名空间和 CAP_SYS_ADMIN 边界。
E2BIG传入的扩展结构体大小超过内核支持范围,且未知字段非零。零填充结构体,并按支持的结构体版本传入 size。
#include 
#include 
#include 

static int report_mount_setattr_error(int rc) {
    if (rc == 0) {
        return 0;
    }

    // syscall 失败时 errno 才是判断权限、忙状态和参数错误的依据。
    int saved_errno = errno;
    fprintf(stderr, "mount_setattr failed: %s\n", strerror(saved_errno));

    // 保留原始 errno,方便上层按 EINVAL、EBUSY 或 EPERM 分支处理。
    errno = saved_errno;
    return -1;
}

另外,mount_attr 是可扩展结构体,初始化时应整体清零;新字段追加在结构体尾部,未知字段保持零值时内核才能安全忽略。若要使用 ID-mapped mount,还要满足用户命名空间、底层文件系统支持、分离挂载和无写入者等额外前提。

常见问题与选择结论

mount_setattr 会递归修改目录里的文件权限吗?

不会。它修改的是挂载对象属性;AT_RECURSIVE 的递归对象是挂载树,不是普通文件目录树。要修改文件权限,应使用文件权限或 ACL 相关接口。

attr_set 和 attr_clr 可以同时写同一个属性吗?

不应这样设计。内核语义是先清除再设置,但调用方应让两组位表达清晰的目标状态,避免把同一属性放入两边导致代码审阅困难。

为什么设置只读时返回 EBUSY?

目标挂载仍可能有打开的写入文件,内核会拒绝把这种状态直接切换为只读。先确认写入者和挂载树结构,再决定是等待、迁移工作负载,还是只改更窄的挂载对象。

mount_setattr 和 mount 命令的 -o ro 一样吗?

它们都可能让挂载表现为只读,但一个更明确地表达挂载对象属性,另一个可能同时涉及文件系统参数。需要按挂载对象和 superblock 的边界选择接口。

实际落地时,可以遵循“先定位、再清除、后设置、最后递归”的顺序:先用 dirfd 和 path 明确目标,再零填充 mount_attr,把目标位放进 attr_set,按需使用 attr_clr 和 AT_RECURSIVE,最后针对 errno、命名空间和写入者做失败处理。这样可以把挂载树的批量收紧控制在清晰、可回滚和可审阅的边界内。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
Linux proc_pid_fdinfo 怎样查看 epoll 监听项Linux proc_pid_fdinfo 怎样查看 epoll 监听项
上一篇
Linux proc_pid_fdinfo 怎样查看 epoll 监听项
Linux systemd.resource-control 怎样限制 CPU 配额
下一篇
Linux systemd.resource-control 怎样限制 CPU 配额
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • PubMedQA数据集详解:生物医学问答基准、功能与应用指南
    PubMedQA
    深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
    857次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    862次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    938次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    919次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    747次使用