SFS分区并非标准文件系统,而是由AVB和内核dm-verity/dm-sfs实现的只读签名验证封装层;其内容由init在early boot阶段通过libavb解析加载,用户态无法直接访问设备节点或绕过libavb解析。

Android SFS 分区不是标准文件系统,libfs 和 libandroidfs 不公开也不可直接链接
Android 12+ 的 SFS(Secure File System)分区并非 ext4、f2fs 或 erofs 这类常规可挂载文件系统,而是由 Android Verified Boot(AVB)和 libavb 配合内核 dm-verity + dm-bow(或 dm-sfs)驱动实现的只读、签名验证、加密感知的元数据封装层。它不暴露 block device 接口给用户态,更不会出现在 /proc/partitions 或 lsblk 中。试图用 fopen("/dev/block/by-name/sfs", "rb") 或 open() 直接读取会失败(ENOENT 或 EACCES),因为该设备节点根本不存在或被 SELinux 策略屏蔽。
关键点:
- SFS 分区内容由
init在 early boot 阶段通过libavb解析并加载进内存,后续仅通过/system/etc/avb/下的预校验 manifest(如vbmeta_system.img)间接引用 - 用户态 C++ 程序无法绕过内核驱动直接解析 SFS —— 它没有公开的 on-disk 格式文档,也没有 ABI 稳定的解析库
- Google 明确将 SFS 实现为“firmware-adjacent”,源码散落在
system/security/avb/、bootable/bootloader/edk2/Platform/Android/及内核drivers/md/dm-sfs.c(仅限特定 OEM 内核分支)中,不纳入 AOSP 主干
想提取 SFS 中的 manifest 或签名信息?必须走 AVB 工具链,而非自写 C++ 解析器
真正能“读取 SFS”的唯一合法路径,是复用 AOSP 提供的 avbtool(Python)及其底层 C 库 libavb。C++ 项目若需集成,应调用 libavb 的稳定 API,而非逆向二进制结构。
实操建议:
- 从 AOSP 源码同步
system/security/avb/,编译出静态库libavb.a(注意:需启用AVB_ENABLE_DEBUG才开放部分内部结构体) - 核心入口函数是
avb_vbmeta_image_verify()和avb_descriptor_foreach(),用于校验 vbmeta 并遍历其中嵌套的AvbDescriptor(含 hash、hashtree、chain partition 等) - SFS 关键数据实际存于
AvbHashDescriptor的partition_name字段(如"system")与digest字段(32 字节 SHA256),而非独立“SFS 文件”中 - 不要尝试用
fread()读取/dev/block/by-name/vbmeta_system后手动解析 —— AVB header 偏移、descriptor 对齐、RSA 签名验证流程都必须由libavb完成,否则校验必失败
avb_slot_verify() 是唯一可信赖的 C++ 可调用接口,但仅适用于已挂载设备或镜像文件
如果你手头有完整的 vbmeta_system.img(例如从线刷包解包得到),C++ 可安全调用 avb_slot_verify() 获取解析结果;但若目标是运行中的设备上的 SFS 分区,则此路不通——avb_slot_verify() 要求输入是完整 vbmeta 映像字节流,而运行时 SFS 的元数据已由内核解密并映射为逻辑块,不再以原始格式存在。
典型代码片段(需链接 -lavb):
AvbSlotVerifyData* verify_data = nullptr;
AvbSlotVerifyResult result = avb_slot_verify(
avb_ops, // 自定义 AvbOps 实现,用于读取分区(如从文件 or /dev/block/...)
"system", // slot 名称
AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR,
&verify_data);
if (result == AVB_SLOT_VERIFY_RESULT_OK && verify_data) {
// verify_data->vbmeta_images[0] 即 vbmeta_system.img 解析后结构
// verify_data->loaded_partitions 包含 system、vendor 等经校验的分区信息
}
注意陷阱:
-
AvbOps必须正确实现read_from_partition()—— 若从文件读取,要处理 padding 和 alignment;若从设备读,需 root 权限 + 绕过 SELinux(avc: denied { read } for ... scontext=u:r:shell:s0) -
avb_slot_verify()不解析 SFS 本身,它只消费 vbmeta 中对 SFS 所保护分区(如system)的描述,SFS 是机制,不是数据容器 - 返回的
verify_data中不含原始 SFS 二进制,只有校验通过后的逻辑视图(如分区哈希、公钥指纹、rollback index)
真要“解析 SFS 结构”?你大概率混淆了概念:SFS 无传统目录树,只有 AVB 描述链
很多人搜索“SFS 分区结构”是想看到类似 ls -R /sfs 的结果,但 SFS 没有 inode、dentry 或 superblock。它的“结构”就是一组 AVB descriptor 链:vbmeta → hash descriptor → hashtree descriptor →(可选)chain descriptor → 下一级 vbmeta。整个链条最终锚定到一个真实分区(如 /dev/block/by-name/system)的哈希值上。
所以,所谓“解析 SFS”,实质是:
- 用
avbtool info vbmeta_system.img查看 descriptor 层级关系 - 用
avbtool verify_image --image system.img校验其是否匹配 vbmeta 中声明的哈希 - 在 C++ 中调用
avb_descriptor_foreach()遍历 descriptor,根据descriptor->tag类型(AVB_DESCRIPTOR_TAG_HASH/AVB_DESCRIPTOR_TAG_HASHTREE)提取对应字段 - 放弃寻找“SFS 根目录”或“SFS 文件列表”——它不存在
最易被忽略的一点:SFS 的“安全性”来自内核驱动的实时验证,不是靠用户态解析出来的某个结构体。任何脱离 libavb 或内核 dm-sfs 的“解析”,得到的只是未验证的、可能被篡改的元数据快照。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











