97 lines
3.9 KiB
Text
97 lines
3.9 KiB
Text
LUKS2 device locking overview
|
|
=============================
|
|
|
|
Why
|
|
~~~
|
|
|
|
LUKS2 format keeps two identical copies of metadata stored consecutively
|
|
at the head of the 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 the user's knowledge.
|
|
A major feature of the LUKS2 format is resilience against accidental
|
|
corruption of metadata (i.e., partial header overwrite by parted or cfdisk
|
|
while creating a partition on a mistaken block device).
|
|
Such header corruption is detected early on the header read and the 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 the user
|
|
direct intervention for example by an udev rule or from a systemd service.
|
|
Such a clash of header read and auto-recovery procedure could have severe
|
|
consequences with the worst case of having a LUKS2 device inaccessible 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 the affected block device. Note we recommend
|
|
that access to the private locking directory is supposed to be limited
|
|
to the superuser only. For this method to work the distribution needs
|
|
to install the locking directory with appropriate access rights.
|
|
|
|
II) regular files
|
|
~~~~~~~~~~~~~~~~~
|
|
|
|
A 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.
|
|
|
|
Additional LUKS2 locks
|
|
======================
|
|
|
|
LUKS2 reencryption device lock
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
Device in LUKS2 reencryption is protected by an exclusive lock placed in the default
|
|
locking directory. The lock's purpose is to exclude multiple processes from
|
|
performing reencryption on the same device (identified by LUKS uuid). The lock
|
|
is taken no matter the LUKS2 reencryption mode (online or offline).
|
|
|
|
LUKS2 memory hard global lock
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
An optional global lock that makes libcryptsetup serialize memory hard
|
|
pbkdf function when deriving a key encryption key from passphrase on unlocking
|
|
LUKS2 keyslot. The lock has to be enabled via the CRYPT_ACTIVATE_SERIALIZE_MEMORY_HARD_PBKDF
|
|
flag. The lock is placed in the default locking directory.
|
|
|
|
LUKS2 OPAL lock
|
|
~~~~~~~~~~~~~~~
|
|
|
|
Exclusive per device lock taken when manipulating LUKS2 device configured for use with
|
|
SED OPAL2 locking range.
|
|
|
|
Lock ordering
|
|
=============
|
|
|
|
To avoid a deadlock following rules must apply:
|
|
|
|
- LUKS2 reencrytpion lock must be taken before LUKS2 OPAL lock.
|
|
|
|
- LUKS2 OPAL lock must be taken before LUKS2 metadata lock.
|
|
|
|
- LUKS2 memory hard global lock can not be used with other locks.
|