摘要

  • draft-ietf-nfsv4-posix-acls-02 提议四个可选属性,让服务器直接公开 POSIX Draft ACL,并说明真正参与访问判定的是哪种 ACL 模型、作用于多大范围。
  • 在逐对象作用域中,一个旧客户端写入 acl 或 dacl 就可能把真形从 POSIX 切到 NFSv4 并删除原有规则;反向写入也会删除 NFSv4 的 ALLOW/DENY,而 AUDIT/ALARM 仍独立存在。
  • 可审计的权限链必须保存能力、真形、按顺序完成的原子写入、一致读回、身份解析、Mask 运算、实际操作判定与文件结果。

一次成功写入,换掉了整套语义

设想一个目录以 POSIX Draft ACL 作为服务器端真形。某个命名组条目带有写权限,但 Mask ACE 把它的有效上限收窄。兼容客户端读取访问 ACL、默认 ACL 和 mode,一切符合预期。

随后,一台不理解新扩展的旧客户端写入标准 dacl。若服务器的 acl_trueform_scope 是单个文件对象,这次成功的 SETATTR 可以把对象切换为 ACL_MODEL_NFS4,同时删除 POSIX 访问 ACL 和默认 ACL。监控只看返回码,会记录“权限更新成功”;POSIX 审计只看数组,会看到空值。两者都漏掉了最重要的事实:掌管访问的模型已经换了。

反向操作同样有破坏性。写入非空 posix_access_acl 或 posix_default_acl,可能把 NFSv4 对象切成 POSIX Draft,并删除原来的 ALLOW/DENY dacl。AUDIT/ALARM ACE 不随它自动消失。“ACL 已更新”这句话没有告诉我们保留了什么、删除了什么,也没有说明下一次访问由哪套规则裁决。

2026 年 9 月 7 日发布的 revision 02 是 NFSv4 工作组的有效 Standards Track Internet-Draft,预计于 2027 年 3 月 11 日到期。它不是 RFC,不是 NFSv4.2 的强制功能,也不是任何产品符合性或部署规模的证明。

草案真正解决的是:让原生 ACL 语义不必经过注定不精确的映射。它没有把数据结构变成一次访问判决。

四个属性把权力边界标出来

acl_trueform 指明真正用于访问判定的模型是 NFSv4、POSIX Draft,还是没有 ACL。acl_trueform_scope 指明该选择只属于一个对象、整个文件系统,还是整台服务器。posix_access_acl 控制当前对象;posix_default_acl 只为目录将来创建的子对象提供继承材料。

支持关系被捆绑起来:服务器若支持任一真形属性,就必须为所有对象支持两者;某文件系统若支持任一 POSIX ACL 属性,就必须同时支持两个 ACL 属性、两个真形属性,以及相关 mode / mode_umask 行为。

这种捆绑防止系统只给一串数组却不说明解释框架。但“支持 NFSv4.2”仍不等于“这个会话、这个 export、这个对象支持此扩展”。逐对象作用域下,相邻文件可以有不同真形。能力回执必须带服务器、会话、export、filehandle、支持位图和观察时间。

真形不是界面标签

草案把 true form 定义为服务器存储并实际用于访问判定的 ACL 模型。这个命名很重要:权威不在管理界面里,而在能拒绝操作的执行点。

服务器级或文件系统级作用域相对稳定,客户端通常每个作用域检查一次。逐对象作用域则允许一次 ACL 写入就改变单个对象。兼容性因此保住了:旧客户端仍能工作;但语义连续性并不自动存在。

“这个共享盘采用 POSIX ACL”可能只是一句过期概括。只要某个旧工具碰过其中一个文件,该文件就可能已经转成 NFSv4 真形。需要回答的不是“平台一般用什么”,而是“这个对象在这次访问的那个 epoch 用什么”。

Mask 决定组权限的上限

最小 POSIX ACL 包括所有者、所属组和其他人。扩展 ACL 再加入命名用户、命名组和一个 Mask。对所属组与命名组而言,权限位必须同时存在于自身条目和 Mask 中才有效。

因此,界面看到某组带 write,并不能断言它真能写;Mask 可能已经把该位去掉。只看 mode 的低九位也不够,因为扩展 ACL 的 group mode 来自 Mask,不一定来自 Group_obj。

真实判定需要:已认证主体、服务器侧名称到身份映射、有效补充组、对象所有者、命中条目、Mask,以及请求的具体操作。即便 XDR 把每个字节都完美传输,缺少主体与组集合,答案仍然未知。

默认 ACL 不控制目录当前访问

访问 ACL 管当前对象。默认 ACL 只能挂在目录上,为未来新建子对象提供继承起点;它不决定谁能访问这个目录本身。

创建子对象时,继承权限要与调用方提供的低九位 mode 取交集。因此扩展依赖 mode_umask:在 OPEN / CREATE 中先提供 mode,完成继承,再应用显式提交的 POSIX ACL。

这意味着默认 ACL 是生产子对象权限的输入,不是永久授权。要审计昨天创建的文件,必须保存当时父目录的默认 ACL、请求 mode 与 umask、应用顺序和子对象的最终原子读回。今天的父目录状态不能可靠重建昨天。

原子性只能固定一个瞬间

同一 SETATTR 同时包含 mode 与 POSIX ACL 时,mode 必须先应用;若一个位图混用 NFSv4 acl / dacl 与 POSIX 属性,服务器必须返回 NFS4ERR_INVAL。读回时,草案建议服务器相对并发写入原子地取得 mode、真形与各 ACL 值。

这能避免一份响应拼接多个时刻,却不是永久锁。读完下一秒,另一个客户端仍可改动;集群另一节点也可能使用不同身份映射。原子读回应被保存为有 epoch 的回执,不应被宣传为持续访问保证。

空数组至少有两种解释

逐对象作用域下,对 POSIX 真形对象写入零长度 posix_access_acl,可以删除 POSIX ACL 并回到 ACL_MODEL_NONE。另一方面,若对象真形本来就是 NFSv4,服务器在 POSIX 属性上也必须返回空数组。

不读取 acl_trueform,两种情况长得一样:前者可能靠 mode 位控制访问,后者可能存在一整套 NFSv4 ACL。把空数组统一翻译成“没有限制”,等于把未知变成授权。

审计状态与访问状态并行

草案把 AUDIT/ALARM ACE 与 ALLOW/DENY 分开。切换真形或删除 dacl 不意味着审计条目被删除。只想改审计的客户端必须用 sacl;使用组合 acl 反而可能触发真形变化。

这是一项有价值的分离,也要求运营记录两条链:谁能访问,与访问如何被记录。迁移可以保留告警而替换权限,也可以保持权限却留下过时审计规则。任何一条都不能从另一条推断。

实验实现只证明可行性

草案列出实验性 FreeBSD 与 Linux 工作。FreeBSD 报告覆盖以 POSIX 为真形的 UFS,没有测试逐对象作用域;Linux 补丁让 getfacl / setfacl 能与支持服务器工作,并报告测试过多条目 ACL。

文本明确说明:这些资料由贡献者提供,未做独立验证,不是 IETF 背书,也不是可用产品目录。“命令看起来正常工作”是珍贵的可行性证据,却不能证明发行版已纳入、默认启用、所有模型转换正确,更不能替某次真实访问作证。

一次访问需要八份回执

完整链条包括:客户端与服务器的精确扩展能力;对象的真形与作用域;按规定顺序被接受的写入;同一 epoch 的原子读回;主体与有效组;ACE、Mask、mode 与继承计算;具体 OPEN/READ/WRITE 判定;以及文件变化、持久性和应用可见结果。

新属性显著加强前四份回执。它们最大的价值,正是让系统承认后四份还没有发生。

来源