RK3588 kernel-6.1 fs/ext4/acl.c POSIX ACL 支持分析

RK3588 kernel-6.1 fs/ext4/acl.c POSIX ACL 支持分析

1. 分析范围

  • rk3588/kernel-6.1/fs/ext4/acl.c
  • rk3588/kernel-6.1/fs/ext4/acl.h
  • xattr.c 中扩展属性接口、VFS posix_acl 通用层的衔接

编译依赖:CONFIG_EXT4_FS_POSIX_ACL(在 fs/ext4/Makefile 中把 acl.o 链入 ext4 模块)。


2. 代码作用(一句话)

acl.c 在 ext4 里把 POSIX ACL 落到磁盘:以“固定二进制布局”存放在扩展属性(xattr)中,并在读/写时与内核内存结构 struct posix_acl 互转;设置 ACL 时走 JBD2 事务 + ext4_xattr_set,新建文件时从父目录继承 default ACL。


3. 解决了什么问题

3.1 UNIX 经典权限的局限

传统 rwx 只对 owner / group / other 三组生效。需要下面能力时不够用:

  • 多个用户多个组 单独授权;
  • 目录上设 默认 ACL,使新建文件/子目录 自动继承 权限语义;
  • mask 一起限制 ACL 条目的有效权限(POSIX.1e 模型)。

POSIX ACL 在 Linux 上通过 setfacl/getfacl 等接口暴露;文件系统必须能 持久化 ACL 并在 permission 检查时参与决策。ext4 选择把它存在 xattr 里(与 ext3 时期思路一致),acl.c 负责 格式转换与 I/O 路径,实际权限检查由 VFS 通用 posix_acl_* + inode i_acl / i_default_acl 缓存完成。

3.2 ext4 侧具体承担的工作

问题 acl.c 的做法
盘上长什么样 ext4_acl_header + ext4_acl_entry / ext4_acl_entry_short,版本号 EXT4_ACL_VERSION
与用户态/通用 ACL 如何对应 ext4_acl_from_disk / ext4_acl_to_disk
从哪里读写 通过 ext4_xattr_get / ext4_xattr_set_handle,索引 EXT4_XATTR_INDEX_POSIX_ACL_ACCESS..._DEFAULT
一致性 ext4_set_aclext4_journal_start/stop,与元数据日志一致
access ACL 与 mode 位一致性 posix_acl_update_mode:访问 ACL 可能要求同步更新 i_mode 中 owner 类权限
新 inode ext4_init_acl:从父目录 posix_acl_create 得到 default + access,再写入子 inode

4. 磁盘格式(acl.h

  • ext4_acl_header:仅 a_version(当前 0x0001),小端。
  • ext4_acl_entrye_tage_perm、可选 e_id(用于 ACL_USER / ACL_GROUP 条目)。
  • ext4_acl_entry_short:无 e_id,用于 ACL_USER_OBJACL_GROUP_OBJACL_MASKACL_OTHER

条目数量与总长用 ext4_acl_count() / ext4_acl_size() 推算(前 4 条按 short 布局,多出的为带 id 的 full entry),与 acl.c 中遍历逻辑一致,防止畸形 xattr 越界解析。


5. 核心函数说明

5.1 ext4_acl_from_disk / ext4_acl_to_disk

  • 从盘读出:校验长度、a_versionext4_acl_count,逐条解析 e_tag/e_perm,对 ACL_USER/ACL_GROUPmake_kuid/make_kgidinit_user_ns)填入内存 ACL。
  • 写回盘:分配连续 buffer,e_tag/e_perm/e_id 转小端;from_kuid/from_kgid 写 id(同样在 init_user_ns 下序列化,与磁盘历史格式一致)。

解析结束指针必须 严格等于 end,否则 EINVAL,避免尾部垃圾或截断。

5.2 ext4_get_acl

VFS get_posix_acl 的 ext4 实现入口(由 ext4.h 里 inode 操作表挂接)。

  • 类型ACL_TYPE_ACCESS → access xattr;ACL_TYPE_DEFAULT → default xattr(仅目录语义在设置层限制)。
  • rcu == true:直接返回 ERR_PTR(-ECHILD),不支持在 RCU 下读 ACL(需一致快照则走非 RCU 路径)。
  • 通过 ext4_xattr_get 取 blob,再 ext4_acl_from_disk-ENODATA/-ENOSYS 视为 无 ACL(NULL)

5.3 __ext4_set_acl

内部函数:在已有 handle_text4_xattr_set_handle 写入或删除 xattr;成功后 set_cached_acl 更新 inode 上 ACL 缓存。

  • default ACL:若 inode 不是目录 且要设置非空 default ACL,返回 -EACCES(符合 POSIX:default ACL 只属于目录)。
  • acl == NULL:删除对应 xattr(size == 0)。

5.4 ext4_set_acl

对外设置入口:配额初始化 → 计算 xattr 所需 journal creditsext4_journal_start

  • ACL_TYPE_ACCESSacl 非空:调用 posix_acl_update_mode,必要时更新 inode->i_modei_ctime,并 ext4_mark_inode_dirty
  • -ENOSPC 时按 ext4 惯例 ext4_should_retry_alloc 重试。

5.5 ext4_init_acl

ext4_new_inode 路径调用(父目录 dir 已持锁;新 inode 仍独占)。

  • posix_acl_create(dir, &inode->i_mode, &default_acl, &acl):由通用层根据父目录 default ACL 和 umask 算出子节点的 default + access。
  • 分别 __ext4_set_acl(..., XATTR_CREATE) 写入;释放临时 ACL 引用;错误时仍要 release,避免泄漏。

6. 配置关闭时(acl.h

若未定义 CONFIG_EXT4_FS_POSIX_ACL

  • ext4_get_acl / ext4_set_acl 被定义为 NULL(不需 POSIX ACL 钩子)。
  • ext4_init_acl 内联为仅 inode->i_mode &= ~current_umask(),并注释说明:否则不会因未调用 posix_acl_create 而漏掉 umask。

7. 与其它模块的关系

1
2
3
4
5
6
7
8
9
10
11
12
13
VFS / generic_acl / permission()
|
v
ext4_get_acl / ext4_set_acl(acl.c)
|
v
ext4_xattr_get / ext4_xattr_set_handle(xattr.c)
|
v
磁盘 inode 扩展属性块(或 inline xattr)
|
v
ext4_jbd2(事务提交)

8. RK3588 / 嵌入式注意点

  • 开启 CONFIG_EXT4_FS_POSIX_ACL 会增加代码体积与少量元数据路径开销;Android/服务器镜像若使用 ACL,需要打开;纯嵌入式只读 rootfs 可酌情关闭。
  • ACL 存 xattr:小文件 + 多 ACL 可能增加元数据与 fsck 负担;权限模型简单时继续用传统 chmod 即可。
  • user namespace 与挂载 idmap 场景下,盘上 uid/gid 与 init_user_ns 序列化方式需与上层策略一致;本文件 ACL 序列化固定走 init_user_ns,与多数 xattr ACL 实现一致。

9. 小结

维度 结论
作用 ext4 的 POSIX ACL:盘上 xattr 比特流 ↔ struct posix_acl,带日志的 set,新建 inode 继承
解决问题 在 ext4 上实现超出 user/group/other 的细粒度权限与目录默认 ACL,并与 VFS ACL 框架对接
关键依赖 xattr、JBD2、posix_acl_* 通用层、CONFIG_EXT4_FS_POSIX_ACL

文档对应路径:rk3588/kernel-6.1/fs/ext4/acl.c。保存位置:linuxDoc/fs/ext4/

文章互动

阅读 --

留言

0 条留言

正在加载留言…