在网上查了很多的资料,有很多写的不错,但很系统的比较少。 我只是按自己的思路把
文档理顺一下。按如下的思路:
问题是什么,原理是什么,具体怎么去解,然后实际的打印log。
问题在前一篇已经写完,已经找到了内核的入口android-verity.c。
这里还是要补充一下dm的原理,否则的话,不管是别人写的文档还是下面写的东西,
你会很难理解,主要是代码的运行机制,怎样做到dm里说的分块去验证。可参看网上的介绍
“Device mapper ”,都写的很详细,可能大部分都是抄成一样的,而且有些缺陷是跟Android下的
linux有点对不上,但不妨碍我们对概念和原理的理解,如下提几个重要单词。
1、 mapped_device -- 映射表是由 dm_table.c 文件中定义的 dm_table
dm_target1……
dm_table dm_target结构数组 = mapped_device 到它某个 target device 的映射关系
dm_table 结构中将这些 dm_target 按照 B 树的方式组织起来方便 IO 请求映射时的查找操作
Dm_target 结构具体记录该结构对应 target device 所映射的 mapped device 逻辑区域的开始地址和范围,
同时还包含指向具体 target device 相关操作的 target_type 结构的指针。
target_type 才是内核代码真正操作的函数集。
2、网上介绍的一般都是从用户态触发校验,但system却不是,这个信息很关键,很重要,否则你无法
理解在Android下找不到对应的dm_ioctl。
内核部分代码
kernel-4.4/init/do_mounts_dm.c
static void __init dm_setup_drives(void)
dm_table_add_target(table, target->type, target->begin, target->length, target->params)
kernel-4.4/drivers/md/dm-table.c
int dm_table_add_target(struct dm_table *t, const char *type, sector_t start, sector_t len, char *params)
tgt->type = dm_get_target_type(type);
r = tgt->type->ctr(tgt, argc, argv);
kernel-4.4/drivers/md/dm-target.c
static int android_verity_ctr(struct dm_target *ti, unsigned argc, char **argv)
static int verify_verity_signature(char *key_id, struct android_metadata *metadata)
static struct target_type android_verity_target = {
.name = "android-verity",
.version = {1, 0, 0},
.module = THIS_MODULE,
kernel-4.4/drivers/md/dm-verity-target.c
static struct target_type verity_target = {
.name = "verity",
.version = {1, 4, 0},
.module = THIS_MODULE,
.ctr = verity_ctr,
.dtr = verity_dtr,
.map = verity_map,
.status = verity_status,
.prepare_ioctl = verity_prepare_ioctl,
.iterate_devices = verity_iterate_devices,
.io_hints = verity_io_hints,
};
3、好了,在这我从其他人的文档或官网抄些资料。
主流程,Android 官方文档如下:
– Generate an ext4 system image.
– Generate a hash tree for that image.
– Build a dm-verity table for that hash tree.
– Sign that dm-verity table to produce a table signature.
– Bundle the table signature and dm-verity table into verity metadata.
– Concatenate the system image, the verity metadata, and the hash tree.-----------
a、 注意---注意- 注意---只签了这个- dm-verity table,而就是说在挂system的时候,刚开始只是简单对
这个总表做一个验证,这样节省验证时间,同时也把对应的验证链表建完 (根据传入
的参数建一张表,等下对比使用)
b、 dm-verity table的概念非常重要,这涉及到kernel里如何通过这个描述,去恢复建立一张表
看一下如何建立verity-table。实际上,verity-table就是为了去描述之前生成的hash tree。
def build_verity_table(block_device, data_blocks, root_hash, salt):
table = "1 %s %s %s %s %s %s sha256 %s %s"
table %= ( block_device, block_device,
BLOCK_SIZE, BLOCK_SIZE, data_blocks,
data_blocks, root_hash, salt)
c、主要的脚本在:build/tools/releasetools/build_image.py BuildImage 函数 中
4、重要的实际上是在第3点,内核中启动验证。
static struct target_type verity_target = {
.name = "verity",
.version = {1, 4, 0},
.module = THIS_MODULE,
.ctr = verity_ctr,
.dtr = verity_dtr,
.map = verity_map,
int verity_ctr(struct dm_target *ti, unsigned argc, char **argv)
/* WQ_UNBOUND greatly improves performance when running on ramdisk */
v->verify_wq = alloc_workqueue("kverityd", WQ_CPU_INTENSIVE | WQ_MEM_RECLAIM | WQ_UNBOUND, num_online_cpus());
(Target_type 结构主要包含了 target device 对应的 target driver 插件的名字、定义的构建和删除该类型target device的方 法、 该类target device对应的IO请求重映射和结束IO的方法等)。
Device mapper本质功能就是根据映射关系和target driver描述的IO处理规则,将IO请求从逻辑设备mapped device
转发相应的target device上。generic_make_request和submit_bio接口 中定向到mapped device的所有块读写IO请求。
IO请求在device mapper的设备树中通过请求转发从上到下地进行处理。当一个bio请求在设备树中的mapped deivce向下层转 发时,一个或者多个bio的克隆被创建并发送给下层target device。
注意: 一个image对应一个verity table,这个信息很重要,在内核只会建立一次,其他的节点都是动态
添加进去的不断变大Tree,通过work队列等机制。
5、 log
[ 2.930724] <4>.(4)[1:swapper/0]device-mapper: init: adding target '0 1 android-verity PARTUUID=a4da8f1b-fe07-433b-95cb-84a5f23e477b '
[ 2.932247] <4>.(4)[1:swapper/0]device-mapper: android-verity: key:id:7e4333f9bba00adfe0ede979e28ed1920492b40f dev:PARTUUID=a4da8f1b-fe07-433b-95cb-84a5f23e477b
[ 2.936164] <1>.(1)[1:swapper/0]device-mapper: android-verity: bio magic_number:2952900609 protocol_version:0 table_length:254
[ 2.937600] <1>.(1)[1:swapper/0]device-mapper: android-verity: verity_table: 1 /dev/block/platform/bootdevice/by-name/system /dev/block/platform/bootdevice/by-name/system 4096 4096 903183 903183 sha256 a2608f0b20824a417440f72bf3177468fbbd8f4124fd78b724ac54a4268da478 aee087a5be3b982978c923f566a94613496b417f2af592639bc80d141e34dfe7
[ 2.941296] <6>.(6)[1:swapper/0] verify_verity_signature debug begin
[ 2.960841] <4>.(4)[1:swapper/0]device-mapper: android-verity: android-verity mounted as verity target
[ 2.962172] <6>.(6)[1:swapper/0] func verity_iterate_devices enter
[ 2.963066] <6>.(6)[1:swapper/0] func verity_iterate_devices enter
[ 2.963947] <6>.(6)[1:swapper/0] func verity_io_hints enter
[ 2.964749] <6>.(6)[1:swapper/0] func verity_iterate_devices enter
[ 2.969174] <6>.(6)[1:swapper/0] func verity_map enter
[ 2.971341] <0>.(0)[273:exe_cq] func verity_end_io enter
[ 2.972144] <4>.(4)[186:kworker/u16:4] func verity_work enter
[ 2.972972] <4>.(4)[186:kworker/u16:4] func verity_verify_io enter
[ 2.974899] <4>.(4)[186:kworker/u16:4] func verity_finish_io enter
[ 2.977011] <6>.(6)[1:swapper/0] func verity_map enter
[ 2.978025] <0>.(0)[273:exe_cq] func verity_end_io enter
[ 2.978869] <4>.(4)[186:kworker/u16:4] func verity_work enter
[ 2.979698] <4>.(4)[186:kworker/u16:4] func verity_verify_io enter
[ 2.980581] <4>.(4)[186:kworker/u16:4] func verity_finish_io enter
[ 11.335907] <1>.(2)[441:kworker/u16:9] func verity_work enter
[ 11.335910] <1>.(2)[441:kworker/u16:9] func verity_verify_io enter
[ 6.652958] <5>.(0)[425:boot_logo_updat] func verity_map enter
[ 6.653727] <5>.(2)[405:android.hardwar] func verity_map enter
[ 6.653840] <5>.(2)[418:vendor.mediatek] func verity_map enter
[ 6.654051] <5>.(3)[431:surfaceflinger] func verity_map enter
[ 6.654400] <5>.(6)[424:audioserver] func verity_map enter
[ 9.031733] <2>.(6)[772:patchoat] func verity_map enter
[ 9.032981] <2>.(6)[615:camerahalserver] func verity_map enter
[ 9.032999] <2>.(6)[615:camerahalserver] func verity_map enter
[ 9.035876] <2>.(6)[519:HwBinder:397_1] func verity_map enter
[ 15.430523] <6>.(6)[1601:droid.bluetooth] func verity_map enter
[ 15.430523] <6>.(0)[1610:droid.deskclock] func verity_map enter