summaryrefslogtreecommitdiffstats
path: root/docs/LUKS2-locking.txt
blob: ccc80d8c55c13851842c03728ed2c1e0aea2a3a2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
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.