| LUKS2 device locking overview |
| ============================= |
| |
| Why |
| ~~~ |
| |
| LUKS2 format keeps two identical copies of metadata stored consecutively |
| at the head of metadata device (file or bdev). The metadata |
| area (both copies) must be updated in a single atomic operation to avoid |
| header corruption during concurrent write. |
| |
| While with LUKS1 users may have clear knowledge of when a LUKS header is |
| being updated (written to) or when it's being read solely the need for |
| locking with legacy format was not so obvious as it is with the LUKSv2 format. |
| |
| With LUKS2 the boundary between read-only and read-write is blurry and what |
| used to be the exclusively read-only operation (i.e., cryptsetup open command) may |
| easily become read-update operation silently without user's knowledge. |
| Major feature of LUKS2 format is resilience against accidental |
| corruption of metadata (i.e., partial header overwrite by parted or cfdisk |
| while creating partition on mistaken block device). |
| Such header corruption is detected early on header read and auto-recovery |
| procedure takes place (the corrupted header with checksum mismatch is being |
| replaced by the secondary one if that one is intact). |
| On current Linux systems header load operation may be triggered without user |
| direct intervention for example by udev rule or from systemd service. |
| Such clash of header read and auto-recovery procedure could have severe |
| consequences with the worst case of having LUKS2 device unaccessible or being |
| broken beyond repair. |
| |
| The whole locking of LUKSv2 device headers split into two categories depending |
| what backend the header is stored on: |
| |
| I) block device |
| ~~~~~~~~~~~~~~~ |
| |
| We perform flock() on file descriptors of files stored in a private |
| directory (by default /run/lock/cryptsetup). The file name is derived |
| from major:minor couple of affected block device. Note we recommend |
| that access to private locking directory is supposed to be limited |
| to superuser only. For this method to work the distribution needs |
| to install the locking directory with appropriate access rights. |
| |
| II) regular files |
| ~~~~~~~~~~~~~~~~~ |
| |
| First notable difference between headers stored in a file |
| vs. headers stored in a block device is that headers in a file may be |
| manipulated by the regular user unlike headers on block devices. Therefore |
| we perform flock() protection on file with the luks2 header directly. |
| |
| Limitations |
| ~~~~~~~~~~~ |
| |
| a) In general, the locking model provides serialization of I/Os targeting |
| the header only. It means the header is always written or read at once |
| while locking is enabled. |
| We do not suppress any other negative effect that two or more concurrent |
| writers of the same header may cause. |
| |
| b) The locking is not cluster aware in any way. |