dm-integrity: device-mapper target that emulates per-sector (integrity) tags.
Device-mapper is infrastructure in the Linux kernel
that provides a generic way to create virtual layers of block devices.
Device-mapper integrity target emulates a block device that has additional per-sector tags
that can be used for storing integrity information.
The integrity target is used with the dm-crypt target to provide authenticated disk encryption
or it can be used standalone.
Basic documentation of dm-integrity mapping table comes with kernel source and the latest version is available
in git repository.
To enable dm-integrity support, enable CONFIG_DM_INTEGRITY in Device Drivers/Multi-device support
(RAID and LVM) configuration option.
It will automatically enable CONFIG_BLK_DEV_INTEGRITY kernel option to support integrity tags in IO requests.
To configure you need userspace components: device mapper library
(part of LVM2 package) and integritysetup (part of cryptsetup package).
The dm-integrity target is available since kernel version 4.12.
Device mapper integrity table mapping line specification
Mapping table in device mapper is defined like
<start_sector> <size> <target name> <target mapping table>
start_sector is 0 (for tables using only one mapped segment, iow table contains only one line)
size is size of device in sectors
target name is name of mapping target, here "integrity" for dm-integrity
Sectors are always counted in 512B sectors (even if device has bigger hw sector like 4k).
Table fields are separated by space.
The dm-integrity target version
Every device-mapper target has internal version which is increased when some new feature is added.
To check which version you have installed, load the dm target module
(dm-integrity.ko for dm-integrity) and use dmsetup targets to check version.
Mapping table for integrity target
The basic syntax is common for all 1.x.y dm-integrity target versions.
If some extension was added later, it is mentioned in the description.
data_dev: This is the device that is going to be used as backend and contains the data and metadata.
It may be specified as a path, like /dev/sdaX, or a device number, major:minor.
offset: Starting sector within the device where the encrypted data begins.
tag_size: The size of the integrity tag (per-sector) in bytes.
mode: Operating mode: D - direct writes (without journal) - journaling is not used and data sectors and integrity tags
are written separately. In case of crash, it is possible that the data and integrity tag doesn't match. J - journaled writes - data and integrity tags are written to the journal and atomicity is guaranteed.
In case of crash, either both data and tag or none of them are written. The journaled mode degrades write
throughput twice because the data have to be written twice. R - recovery mode - in this mode, journal is not replayed, checksums are not checked and writes
to the device are not allowed. This mode is useful for data recovery if the device cannot be activated in any
of the other standard modes.
#opt_params: Number of optional parameters.
If there are no optional parameters, the optional parameters section can be skipped or it can be zero.
Otherwise it is the number of following arguments. Available since: 1.0.0 (kernel 4.12)
journal_sectors: The size of journal, this argument is used only if formatting the
device. If the device is already formatted, the value from the superblock is used.. Available since: 1.0.0 (kernel 4.12)
interleave_sectors: The number of interleaved sectors. This values is rounded down to
a power of two. If the device is already formatted, the value from the superblock is used.. Available since: 1.0.0 (kernel 4.12)
buffer_sectors: The number of sectors in one buffer. The value is rounded down to
a power of two. The tag area is accessed using buffers, the buffer size is configurable.
The large buffer size means that the I/O size will be larger, but there could be less I/Os issued.. Available since: 1.0.0 (kernel 4.12)
block_size: The size of a data block in bytes. The larger the block size the
less overhead there is for per-block integrity metadata.
Supported values are 512, 1024, 2048 and 4096 bytes. If not specified the default block size is 512 bytes. Available since: 1.0.0 (kernel 4.12)
journal_watermark: The journal watermark in percents. When the size of the journal
exceeds this watermark, the journal flush will be started.. Available since: 1.0.0 (kernel 4.12)
commit_time: Commit time in milliseconds. When this time passes, the journal is
written. The journal is also written immediately if the FLUSH request is received. Available since: 1.0.0 (kernel 4.12)
Use standalone and calculate hash or crc internally.
When this argument is used, the dm-integrity target won't accept integrity tags from
the upper target, but it will automatically generate and verify the integrity tags.
You can use a crc algorithm (such as crc32), then integrity target will protect the data
against accidental corruption.
You can also use a hmac algorithm (for example "hmac(sha256):0123456789abcdef"), in this
mode it will provide cryptographic authentication of the data without encryption.
When this argument is not used, the integrity tags are accepted from an upper layer target,
such as dm-crypt. Available since: 1.0.0 (kernel 4.12)
Optional Journal encryption parameters
The encryption of journal should be used only in combination with data encryption.
The journal contains history of last writes to the block device, an attacker reading
the journal could see the last sector numbers that were written.
From the sector numbers, the attacker can infer the size of files that were written.
Journal encryption prevents this information to leak from the journal.
Journal MAC protects sector numbers in the journal from accidental or malicious modification.
Encrypt the journal using given algorithm.
You can use a block cipher here (such as "cbc(aes)") or a stream cipher
(for example "chacha20" or "ctr(aes)"). Available since: 1.0.0 (kernel 4.12)
To protect against accidental modification, use a CRC algorithm, to protect against
malicious modification, use a HMAC algorithm with a key. Available since: 1.0.0 (kernel 4.12)
When loading the target for the first time, the kernel driver will format the device.
But it will only format the device if the superblock contains zeroes.
If the superblock is neither valid nor zeroed, the dm-integrity target can't be loaded.
Note that presented device is smaller and after the initial format the calculated data
size is written to superblock. You can use integritysetup tool to dump superblock.
Note that if you are using internal_hash, device reads will fails because the integrity
checksums were not initialized. You have to use direct-io write to initially format the device,
or use integritysetup format command.
Configuration with dmsetup tool
Dmsetup is used to create and remove devices, get information about
devices or reload tables (that means changing the mapping while the device is in use).
Usually this tool is only used for low-level access to dm device,
example here is mentioned just to show how the low level parameters works.
Always prefer using integritysetup if possible.
To create device and specify mapping table, use dmsetup create <name> --table " ..." command.
The example above is then created using (after hash device was populated with hashes)
SIZE=411288 # it would be calculated on initial formatdmsetup create name --table "0 $SIZE integrity /dev/sdb 0 4 J 1 internal_hash:crc32"
You can check the full mapping table using dmsetup table.
Note that for all device-mapper operations is required root privilege (CAP_SYSADMIN).
The newly created device then appears as /dev/mapper/name.
Configuration using integritysetup
Note: the integritysetup tool is not yet released, it is part of master branch of
Preparing the device (formatting) with default parameters (CRC32) integritysetup format /dev/sdb
Activation of integrity data device integritysetup open /dev/sdb name
Note that internal hash algorithm is not written into superblock
(there is only required tag size), you have to specify it during activation, for example
integritysetup format /dev/sdb --tag-size 32
integritysetup open /dev/sdb name --integrity sha256
Integrity failures count
For the standalone mode, device-mapper status line provides count of detected integrity
mismatches (failures). You can check this count with dmsetup status:
dmsetup status name
Integrity superblock format
The current on-disk dm-integrity specification (size of superblock is always 512 bytes):