Understanding dm-verity: Design Principles, Application Layer, and Kernel Implementation
dm‑verity is a Linux device‑mapper target that protects a data partition’s integrity by using a compile‑time hash‑tree stored on a separate hash device, with Android employing it for verified boot; user‑space creates the dm device, loads the verity table, activates it, while the kernel’s dev_create, table_load, and suspend handlers set up mapped_device structures and enforce per‑block hash verification during I/O.
dm-verity is a target device type in the device‑mapper framework that guarantees the integrity of a device or its partitions.
It relies on two underlying devices: a data device that stores the actual data and a hash device that stores hash values used to verify the data device.
The mapper device and the target device have a one‑to‑one relationship. Read operations on the mapper are forwarded to the target device, where dm‑verity maps them to reads on the data device and adds an extra hash verification step by comparing the computed hash with the value stored on the hash device.
Design principle (Android focus)
On Android, dm‑verity is used during image boot to verify system partitions (e.g., system , vendor ) and ensure they have not been tampered with. The verification is based on a hash‑tree (hashtree) built at compile time.
During compilation, each 4 KB block of the image is hashed, forming layer 0. The hashes of layer 0 are themselves hashed to form layer 1, and this process continues until a single 4 KB block containing the root hash is produced.
The root hash is signed and stored to protect the hash tree itself from tampering. At runtime, each accessed 4 KB block is hashed and compared with the corresponding hash in the tree; a mismatch indicates corruption or malicious modification.
For a 1 GB image, the process yields 262 144 data blocks, 2 048 blocks for layer 0 hashes, 16 blocks for layer 1, and finally one block for the root hash.
Using a hash tree dramatically reduces the number of hash calculations needed for verification: only one hash per tree level (e.g., three hashes for a three‑level tree) instead of a hash per data block.
Application‑layer workflow (three steps)
1. Create dm device
• Open the device‑mapper node: open /dev/device-mapper
• Pass the partition name and a generated UUID to the DM_DEV_CREATE ioctl.
2. Load verity table
The verity table contains fields such as:
Verity target version
Data block device
Hash block device
Data block size
Hash block size
Number of data blocks
Hash start block
Hash algorithm
Root digest (root hash)
Salt
The table is passed to the kernel via the DM_TABLE_LOAD ioctl.
3. Activate dm device
The DM_DEV_SUSPEND ioctl (without the DM_SUSPEND_FLAG ) activates the device, effectively resuming normal operation.
Overall, the application performs create → load verity table → activate dm device to set up real‑time block verification.
Kernel‑layer implementation (three steps)
1. dev_create – handles the DM_DEV_CREATE ioctl.
• Validates the partition name.
• Allocates and initializes a mapped‑device structure, assigns a minor number (e.g., dm‑1 ), registers a request queue with blk_queue_make_request , and registers the device with the kernel.
• Inserts the mapped device into a global hash table.
2. dm_ctl_ioctl(DM_TABLE_LOAD_CMD) – processes the DM_TABLE_LOAD ioctl.
• Parses the verity table, creates dm_table and dm_target structures, and invokes the target‑type constructor to build the target device.
3. dm_ctl_ioctl(DM_DEV_SUSPEND_CMD) – handles the DM_DEV_SUSPEND ioctl.
• Links the mapped device with its dm_table , completing the creation of a usable logical block device.
The key kernel structures involved are mapped_device , dm_table , dm_target , target_type , and the specific target device (dm‑verity).
Core data flow
After the application creates, loads, and activates the dm device, the logical block device is mounted. I/O requests from the filesystem are forwarded to the target device, where the hashtree is consulted to verify each block’s hash before the data is returned.
Conclusion
The article presents the design rationale of dm‑verity, demonstrates how the Android platform leverages it for verified boot, details the user‑space ioctl sequence, and explains the corresponding kernel implementation, culminating in a clear picture of the end‑to‑end integrity‑verification data flow.
OPPO Kernel Craftsman
Sharing Linux kernel-related cutting-edge technology, technical articles, technical news, and curated tutorials
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.