What is dm-verity and how does it protect system integrity?

Last update: 08/01/2026
Author Isaac
  • dm-verity verifies blocks in real time using a cryptographic hash tree, preventing silent changes to critical partitions.
  • Trust is anchored in the root hash and its signature, integrated into a chain of Boot verified along with bootloaders, kernel and Secure Boot.
  • Android, Linux and embedded systems use dm-verity for read-only roots, combining it with FEC, TPM and encryption to harden the system.
  • Updating systems with dm-verity is based on immutable images, A/B schemes, and overlays, avoiding direct changes to the verified root.

What's new in Linux 6.18

If you work with Android, Linux, or embedded systems, you've probably seen messages like "dm-verity corruption" or heard of verified boot, AVB, or Secure Boot. Behind all that is a key part of the kernel: dm-verity, a mechanism designed to ensure that the file system has not been tampered withneither while the device is on nor between restarts.

It might seem like a minor issue, but it actually affects everyday things like your phone not maintaining a malware hidden in the system partition, or that a router or a "closed" server always starts in the same reliable state. dm-verity relies on a SHA-256 hash tree and cryptographic signatures to verify, block by block, that the data on the disk is still what it should be.And if something doesn't add up, the kernel can return read errors, restart the computer, or even panic to avoid continuing to execute questionable code.

What is dm-verity and what problem does it solve?

dm-verity is a target of the Linux kernel's device-mapper subsystem that allows real-time verification of the integrity of a block deviceThis is typically a partition or image containing the root filesystem or a critical partition (e.g., /system on Android). Instead of reading the disk "blindly," each accessed block is cryptographically checked against a pre-computed hash tree.

description of the boot process in UEFI systems
Related article:
Detailed description of the boot process in UEFI systems

On Android since version 4.4 and on many modern Linux distributions, dm-verity is the basis of the verified bootThis ensures that the system partition is exactly the same as when the image was created. This makes it difficult for a rootkit or other type of malware to persist after a reboot by injecting malicious files or binaries into the system.

One of the advantages of this approach is that dm-verity devices appear as normal block devices under /dev/mapperThis allows them to be mounted as if they were just another disk. For the file system above (ext4, EROFS, squashfs, etc.) everything seems standard, but each read operation passes through the verity cryptographic filter.

Why it's necessary: ​​malware with root and trusted boot

all types of malware-6

In systems like Android, applications or binaries that gain privileges root They can hide better than the detection systems themselves.Having more permissions than antivirus or security tools, they can "lie" about files, processes, or configurations, making them harder to detect and delete.

Without a mechanism like dm-verity, An attacker can modify system binaries, libraries, or boot scripts to achieve persistence.and thus prevent tools that allow verify file integrity They detect the alteration; that is, they remain even if you turn the device off and on again. That's the classic nightmare of persistent rootkits.

dm-verity acts as a guardian at the base of the system: The kernel only accepts as valid those blocks that meet the expected hash of the check treeIf someone has manually altered the system partition, the hashes will no longer match, and the kernel will detect this as soon as it tries to read the altered data.

How dm-verity works internally

The basic idea is simple but powerful: A cryptographic hash tree (usually SHA-256) is built over all the blocks of the devicehierarchically. This tree is stored on disk and, during normal use, is used to validate each block read.

Hash tree structure

The verification tree is formed by levels. Layer 0 contains the actual data (e.g., the ext4/EROFS image of the system), divided into 4K blocks.For each of these blocks, a SHA-256 hash is calculated (usually with a random salt to harden pre-computation attacks).

The hashes in layer 0 are concatenated to form layer 1. Layer 1 is regrouped into 4K blocks and a SHA-256 hash is calculated for each resulting blockproducing layer 2. The process is repeated layer by layer until the entire set of hashes fits into a single block; the hash of that final block is the root hash, which represents the entire tree.

When a layer does not fill a complete block, It is filled with zeros until it reaches 4KThis avoids ambiguities and allows the detection of attempts to "cut" the tree by replacing parts with arbitrary data: the expected structure includes that known padding of zeros.

On disc, The tree is stored by concatenating levels from the top layer down (excluding data layer 0)The total size of the tree varies depending on the size of the partition checked, but in practice it is usually quite small, typically less than 30 MB even for large system partitions.

Format versions and hash algorithms

The format in which hash blocks are stored has been evolving. Version 0 of the format, originally used by Chromium OS, added the salt at the end when calculating the hash and stored the digests continuously., filling the rest of the block with zeros.

  My Android keyboard is not working.

Version 1, recommended for new systems, puts the salt before the data when calculating the hash and pads each digest to a power of two. This improves alignment and robustness against certain types of attacks or corruption. The dm-verity table also indicates the algorithm used (sha1, sha256, etc.), although nowadays it is reasonable to use SHA-256.

Step-by-step calculation of the root hash

If you want to build the tree by hand, the general scheme is clear. First, a random salt is chosen in hexadecimal format, the image is divided into 4K blocks, and for each block, its salted SHA-256 is calculated.These hashes form the first “logical” level on top of the data.

Then, The hashes are concatenated until 4K blocks are filledIf there is insufficient space, it is filled with zeros. Each resulting block is also hashed with SHA-256 to form the next level of the tree. This process of "hashing hashes" is repeated until we are left with a single hash: the root hash.

In practical implementations, tools like cryptsetup/veritysetup handle all this calculation and directly generate the tree file (verity.bin) and the root hash value (roothash), ready to be used in the dm-verity table or in the signed metadata.

The dm-verity table: describing what and how to verify

In order for the kernel to use dm-verity, it needs an accurate description of where the data is, where the hash tree is, and what parameters to use. That description is the dm-verity table, a line of parameters that the device-mapper interprets when creating the verified logical device..

In a typical simplified versionThe definition can be seen as:

The most important fields The dm-verity table usually includes:

  • giant: device that contains the data to be verified (for example, a /dev/sdXN partition or a major:minor pair).
  • hash_dev: device that stores the hash tree; it can be the same as dev, as long as hash_start points outside the range of verified data.
  • data_block_size: data block size in bytes, typically 4096.
  • hash_block_size: block size for hashes, it is also usually 4096.
  • num_data_blocks: number of data blocks to be protected.
  • hash_start_block: offset in blocks from the start of the device to where the hash tree begins.
  • algorithm: hash algorithm (sha256 is the de facto standard).
  • digest (root hash): hash of the root block of the tree, expressed in hexadecimal; it is the trusted “anchor”.
  • salt: salt used when calculating hashes, also in hexadecimal.

In addition to these basic fields, There are optional parameters that adjust how the system reacts to corruption or errorsFor example, you can specify that in case of corruption, the system should be restarted, a panic should be triggered, or the issue should be ignored, only logging to the system. logsor that FEC recovery is activated before failure.

Advanced table options: corruption, FEC, and performance

dm-verity includes a set of flags for profiling behavior. ignore_corruption allows reading to continue even if corruption is detected, but leaves a trace in the logs., useful in environments where availability is prioritized over strict integrity.

If you're looking for a firm hand, `restart_on_corruption` or `panic_on_corruption` force a restart or a panic when a block fails verification.Similar variants exist for I/O errors (restart_on_error, panic_on_error). There is also an ignore_zero_blocks option that avoids checking blocks expected to be zero and returns zeros directly.

For systems that integrate forward correction, `use_fec_from_device` along with `fec_roots`, `fec_blocks`, and `fec_start` enable the use of Reed-Solomon codes.With FEC, in the event of a verification failure, it is possible to attempt to reconstruct the block using redundant information before considering it lost.

Other options, such as check_at_most_once, They allow each block to be verified only the first time it is accessed.This reduces overhead at the cost of not detecting live modifications; it's a trade-off between security and performance. Flags like `root_hash_sig_key_desc` allow the kernel to validate a PKCS7 signature of the root hash using keys stored in the keyring.

Signature, metadata, and verity magic number

For everything to make sense, the root hash value must be reliable. In classic Android, a public key is included in the boot partition, and the manufacturer is responsible for verifying it externally.This key is used to validate the signature of the root hash or the dm-verity table, ensuring that the hash tree has not been tampered with.

Verity's metadata encapsulates that information. A 32K block contains a magic number, version, signature, table length and content, plus padding with zeros.This controlled structure allows the metadata to be located and validated without ambiguity.

Typical fields This metadata includes:

  • Magic number: fixed value 0xb001b001, used by components such as fs_mgr to recognize that it is a valid verity block.
  • Version: currently 0, it is used to introduce format changes in the future.
  • Company: dm-verity table signature, usually PKCS1.5 with an RSA-2048 (256 bytes) key.
  • Table length: Size in bytes of the dm-verity table stored below.
  • Panel: the serialized dm-verity table itself.
  • Filling: zeros until the 32.000 bytes of the block are completed.
  Is the change of Ios so slow?

If the magic number is not found when analyzing the end of the system image, It is assumed that the partition is not prepared for verification and the verification process is not activated.This prevents, for example, treating a partition as verified when it is not.

On Android, fs_mgr and the fstab file control which partitions are checkedSimply add the check mark (for example, “verify” in the fs_mgr flags) and place the appropriate public key in /boot/verity_key to bring the end-to-end verification flow into action.

How it links to the verified startup

dm-verity would be of little use if the attacker could sneak in a modified kernel or bootloader that accepts anything. Therefore, in mobile devices and secure platforms, the root hash and the dm-verity table are part of a chain of trust that begins in hardware.

Typically, the manufacturer burns a public key onto the device. That key validates the signature of the first bootloader, which in turn checks the next level, the bootloader of apps and finally, the kernel imageFrom there, the kernel, now verified, takes control and uses dm-verity to extend that trust to the system partition.

On modern Android with AVB (Android Verified Boot 2.0), The bootloader incorporates libavb and reads hashtree descriptors in partitions or in vbmetaWith that information, it constructs the dm-verity parameters and passes them to the kernel on the line of commands, along with instructions such as whether there is a FEC, what to do in case of corruption, etc.

dm-verity on Android: system-as-root, AVB, and corruption messages

Android has been relying on dm-verity for years. Since Android 4.4, it has been used as the basis for verified booting, and from Android 10 onwards, the system-as-root design directly integrates rootfs into system.imgeliminating many classic setups and forcing dm-verity to be handled from a first-stage init.

With system-as-root and modern OTAs, The system partition is usually read-only, protected by a verified hashtree.The kernel sees it through a dm-verity device, transparently to the Android top layer.

Slots A/B, vbmeta and “dm-verity corruption” errors

In devices with an A/B scheme, it's quite easy for something to go out of alignment. If you flash boot or vbmeta without them matching the roothash and the actual system partition tree, the typical result is the dreaded message “dm-verity corruption, your device is not trusted”..

To bypass the verification, there are commands like fastboot flash –disable-verity –disable-verification vbmeta vbmeta.imgor, in some manufacturers, `fastboot oem disable_dm_verity`. But be careful: This disables verified boot and eliminates integrity guarantees.even if you manage to start it up without annoying messages.

The "clean" way to fix it involves Make sure that the system, boot, and vbmeta images are consistent with each other.Regenerate (or restore) the verity tree and update the signatures or descriptors so that the expected root hash matches the actual one. Only in this way can you maintain the chain of trust without Tricks dangerous.

Relationship with TWRP, unlocked bootloader and mods

In the real world, many people encounter dm-verity when installing ROMs, modified kernels, or rooting. To use TWRP, flash firmware, or install mods, you usually need to have an unlocked bootloader.because the verified boot process prevents booting images not signed by the manufacturer.

There are procedures that recommend, for example, First, flash a specific firmware, reboot into bootloader, and execute commands such as “fastboot oem disable_dm_verity” followed by “fastboot oem enable_dm_verity”and then install a newer firmware. These steps aim to "reset" the Verity state so that new images are accepted without corruption messages.

If after crashes or flashing errors you start seeing "dm-verity corruption" warnings on every reboot, It's wise to check that the partition system has no physical damage and that the images you're using are the correct ones for your model.Sometimes a simple mismatch between modem, boot, and system firmware can mess up the verified boot process.

dm-verity on Linux desktops and servers (systemd, veritysetup)

dm-verity is not exclusive to Android. In modern Linux distributions, especially with systemd, it is becoming popular as the basis for high-trust, read-only root systems.very similar to how some routers, appliances or media boxes work.

A typical root mount with dm-verity includes: a root image or partition, a file containing the verity tree (verity.bin), the root hash value, the systemd-veritysetup units, and the appropriate kernel line parametersOptionally, a signed UKI (Unified Kernel Image) and Secure Boot are added to make the whole system well protected.

Partitioning scheme and file system

The usual recommendation is to reserve a specific partition for hashes. A commonly used arrangement consists of: an EFI partition (ESP), an XBOOTLDR partition for the UKIs, a root partition (with or without encryption), a VERITY partition for the tree, and optionally, writable /home and /var partitions..

Instead of classic ext4 for the root, EROFS is a very interesting optionIt is read-only by design, has very good flash performance and SSD and it supports LZ4 compression out of the box. It's no coincidence that it's widely used on Android phones in combination with dm-verity.

Files that need writing and common tricks

If the root directory is mounted as read-only, you need to carefully consider which files need to be modifiable. Many programs expect to write to /etc, /var, or similar paths.Instead of making /etc completely writable, it's more efficient to move only what's necessary to /var/etc and link it symbolically from /etc.

  How can you remove air bubbles from the iPhone screen protector?

For instance, NetworkManager connections can be moved to /var/etc/NetworkManager/system-connections and leave a symlink from /etc/NetworkManager/system-connections. This way the immutable root design is not broken, but configurations that need to be changed can still be changed.

To discover what is actually written during startup and execution, You can use dracut-overlayroot, which mounts a tmpfs overlay on top of the root and leaves any actual writes logged in /run/overlayroot/uAfter using the system for a while, simply inspect that directory to find out what needs to be moved out of the verified root.

It's also common in Arch Linux Relocate the pacman database to /usr/lib/pacman and the cache to /var/lib/pacmanso that the root image always reflects the "sealed" state of the system, while synchronization and update operations are performed in writable areas.

Creating the verity and configuring the boot process with systemd

The typical flow On a Linux system that wants to use dm-verity for root access, it would be:

  • Boot from a live environment and mount the root directory as read-only., once the system has been left exactly as you want it to be “frozen”.
  • Run `veritysetup format root-device verity-device` to generate the hash tree and the root hash.The command usually prints the line with the Root Hash, which is saved in a file (for example, roothash.txt).
  • Test the mapping with veritysetup open, creating a verified /dev/mapper/root and mounting it to check that everything works.

Next, you need to adjust the kernel command line. With systemd, parameters such as systemd.verity=1, roothash=…, systemd.verity_root_data=… and systemd.verity_root_hash=… are used., in addition to options such as systemd.verity_root_options=restart-on-corruption or panic-on-corruption depending on the desired hardness.

If a UKI is used, All these parameters are integrated into the kernel.efi image, which is signed and booted with Secure BootThis prevents someone from changing the roothash on the command line without invalidating the signature, thus maintaining the trust model.

Secure Boot, encryption and TPM: fitting the pieces together

dm-verity only guarantees integrity, not confidentiality. Data can be viewed if it is not encrypted, but it cannot be altered without being detected.That's why it's often combined with encryption (LUKS) and a TPM to protect the keys.

A commonly used strategy is Anchor LUKS decryption keys to certain TPM PCRs using systemd-cryptenroll (PCR 0, 1, 5, 7, for example), so that changing the firmware, partition layout, or Secure Boot status invalidates the keys. This prevents an attacker from disabling Secure Boot to sneak in a kernel that ignores verity without simultaneously breaking the decryption chain.

If systemd-boot is used, The bootloader measures the kernel.efi image in PCR 4If that measure changes, the associated keys are not released and the encrypted partition is not opened. This is another link in the chain to ensure that the kernel, initramfs, and cmdline (including roothash) have not been tampered with.

Usage beyond the root: other partitions, overlays, and updates

Although protecting the root is the most common practice, dm-verity can be applied to other partitions that are mounted at bootOn systems with systemd, these additional partitions are described in /etc/veritytab and are automatically configured by systemd-veritysetup@.service.

However, a verified non-root partition is less secure: It can be read/write recovered relatively easily, and a root user can even disable Verity on it.Even so, it's useful for data you want to monitor or for read-only images mounted at other points.

Regarding updates, a verified read-only root changes the mental model. The administrator is not expected to perform a "pacman -Syu" or similar command on the production root.but rather that new images of the system are generated, with their corresponding verity trees, and deployed in a transactional manner.

There are several strategies for this: Use tools like systemd-sysupdate and systemd-repart to download and flash new images, or propose an A/B scheme with two roots and two verities, where you update the inactive partition and then swap roles.

If you want something more flexible, The verified root can be mounted as a lower directory on an OverlayFS, with an upper layer on tmpfs or disk.Thus, changes are applied to the top layer, but the base remains the verified image. You can even opt for optional or ephemeral persistence (for example, systemd.volatile=overlay) to have "disposable sessions".

In the desktop world, technologies such as Flatpak fits well with this philosophyThey install and update applications in /var and /home without touching the root directory protected by verity. This maintains an immutable base system and allows apps to be managed independently.

This entire ecosystem makes dm-verity much more than just a kernel curiosity: It is the cornerstone of immutable, mobile, and embedded systems that always need to start in a known state, detecting any manipulation of the storageand integrates with verified boot, Secure Boot, encryption and TPM to offer a modern security model without sacrificing too much performance or flexibility.