当前位置: 首页 > 工具软件 > verified > 使用案例 >

Android Verified Boot dm-verity 优化和实战2

万承志
2023-12-01

目录

一、AVB背景分析

二、dm的原理         

三、代码跟踪分析


一、AVB背景分析

      在网上查了很多的资料,有很多写的不错,但很系统的比较少。 我只是按自己的思路把

文档理顺一下。按如下的思路:

         问题是什么,原理是什么,具体怎么去解,然后实际的打印log。

         问题在前一篇已经写完,已经找到了内核的入口android-verity.c。

二、dm的原理         

这里还是要补充一下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。

  1. def build_verity_table(block_device, data_blocks, root_hash, salt):

  2. table = "1 %s %s %s %s %s %s sha256 %s %s" 

  3. table %= ( block_device,   block_device,

  4.           BLOCK_SIZE,    BLOCK_SIZE,    data_blocks,

  5.         data_blocks,   root_hash,   salt)

  6.  主要的脚本在: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. 了解dm-verity的相关接口后,就可以在用户空间对他进行初始化了。在Android中fs_mgr_verity负责用户空间对Dm-verity进行控制的,

其中有个load_verity_table这个函数展示了如何从用户空间去使用dm-verity。先贴出代码。

static int load_verity_table(struct dm_ioctl *io, char *name, char *blockdev, int fd, char *table) {

     tgt->length=device_size/512;

    strcpy(tgt->target_type, "verity");

6、 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

 类似资料: