Skip to content

Commit

Permalink
Use correct LUKS metadata size for LUKS 2
Browse files Browse the repository at this point in the history
When creating or resizing LUKS 2 devices we need to take the
bigger metadata into account (16 MiB for LUKS2 but just 2 MiB for
LUKS1).
  • Loading branch information
vojtechtrefny committed Jul 24, 2024
1 parent 167cb76 commit c1218f4
Show file tree
Hide file tree
Showing 8 changed files with 36 additions and 14 deletions.
7 changes: 3 additions & 4 deletions blivet/blivet.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@
from .deviceaction import ActionDestroyFormat, ActionResizeDevice, ActionResizeFormat
from .devicelibs.edd import get_edd_dict
from .devicelibs.btrfs import MAIN_VOLUME_ID
from .devicelibs.crypto import LUKS_METADATA_SIZE
from .errors import StorageError, DependencyError
from .size import Size
from .devicetree import DeviceTree
Expand Down Expand Up @@ -988,16 +987,16 @@ def resize_device(self, device, new_size):
if device.format.resizable:
if device.format.type == "luks" and device.children:
# resize the luks format
actions.append(ActionResizeFormat(device, new_size - LUKS_METADATA_SIZE))
actions.append(ActionResizeFormat(device, new_size - device.format._header_size))

luks_dev = device.children[0]
if luks_dev.resizable:
# resize the luks device
actions.append(ActionResizeDevice(luks_dev, new_size - LUKS_METADATA_SIZE))
actions.append(ActionResizeDevice(luks_dev, new_size - device.format._header_size))

if luks_dev.format.resizable:
# resize the format on the luks device
actions.append(ActionResizeFormat(luks_dev, new_size - LUKS_METADATA_SIZE))
actions.append(ActionResizeFormat(luks_dev, new_size - device.format._header_size))
else:
actions.append(ActionResizeFormat(device, new_size))

Expand Down
4 changes: 2 additions & 2 deletions blivet/devicefactory.py
Original file line number Diff line number Diff line change
Expand Up @@ -425,9 +425,9 @@ def encrypted(self):
def encrypted(self, value):
if not self.encrypted and value and self.size:
# encrypted, bump size up with LUKS metadata size
self.size += get_format("luks").min_size
self.size += get_format("luks", luks_version=self.luks_version).min_size
elif self.encrypted and not value and self.size:
self.size -= get_format("luks").min_size
self.size -= get_format("luks", luks_version=self.luks_version).min_size

self._encrypted = value

Expand Down
4 changes: 3 additions & 1 deletion blivet/devicelibs/crypto.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@
import logging
log = logging.getLogger("blivet")

LUKS_METADATA_SIZE = Size("2 MiB")
LUKS1_METADATA_SIZE = Size("2 MiB")
LUKS2_METADATA_SIZE = Size("16 MiB")
LUKS_METADATA_SIZE = LUKS2_METADATA_SIZE # luks2 is default
MIN_CREATE_ENTROPY = 256 # bits
SECTOR_SIZE = Size("512 B")

Expand Down
10 changes: 5 additions & 5 deletions blivet/devices/luks.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ def device_id(self):

def _get_size(self):
if not self.exists:
size = self.raw_device.size - crypto.LUKS_METADATA_SIZE
size = self.raw_device.size - self.raw_device.format._header_size
elif self.resizable and self.target_size != Size(0):
size = self.target_size
else:
Expand All @@ -86,10 +86,10 @@ def _get_size(self):

def _set_size(self, newsize):
if not self.exists and not self.raw_device.exists:
self.raw_device.size = newsize + crypto.LUKS_METADATA_SIZE
self.raw_device.size = newsize + self.raw_device.format._header_size

# just run the StorageDevice._set_size to make sure we are in the format limits
super(LUKSDevice, self)._set_size(newsize - crypto.LUKS_METADATA_SIZE)
super(LUKSDevice, self)._set_size(newsize - self.raw_device.format._header_size)
else:
raise DeviceError("Cannot set size for an existing LUKS device")

Expand All @@ -113,7 +113,7 @@ def _set_target_size(self, newsize):
raise ValueError("size is smaller than the minimum for this device")

# don't allow larger luks than size (or target size) of backing device
if newsize > (self.raw_device.size - crypto.LUKS_METADATA_SIZE):
if newsize > (self.raw_device.size - self.raw_device.format._header_size):
log.error("requested size %s is larger than size of the backing device %s",
newsize, self.raw_device.size)
raise ValueError("size is larger than the size of the backing device")
Expand All @@ -128,7 +128,7 @@ def _get_target_size(self):
def max_size(self):
""" The maximum size this luks device can be. Maximum is based on the
maximum size of the backing device. """
max_luks = self.raw_device.max_size - crypto.LUKS_METADATA_SIZE
max_luks = self.raw_device.max_size - self.raw_device.format._header_size
max_format = self.format.max_size
return min(max_luks, max_format) if max_format else max_luks

Expand Down
3 changes: 1 addition & 2 deletions blivet/devices/storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@
from .device import Device
from .network import NetworkStorageDevice
from .lib import LINUX_SECTOR_SIZE
from ..devicelibs.crypto import LUKS_METADATA_SIZE


class StorageDevice(Device):
Expand Down Expand Up @@ -699,7 +698,7 @@ def min_size(self):
""" The minimum size this device can be. """
if self.format.type == "luks" and self.children:
if self.resizable:
min_size = self.children[0].min_size + LUKS_METADATA_SIZE
min_size = self.children[0].min_size + self.format._header_size
else:
min_size = self.current_size
else:
Expand Down
6 changes: 6 additions & 0 deletions blivet/formats/luks.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,12 @@ def __init__(self, **kwargs):
self.map_name = kwargs.get("name")
self.luks_version = kwargs.get("luks_version") or crypto.DEFAULT_LUKS_VERSION

if self.luks_version == "luks2":
self._header_size = crypto.LUKS2_METADATA_SIZE
else:
self._header_size = crypto.LUKS1_METADATA_SIZE
self._min_size = self._header_size

if not self.exists and self.luks_version not in crypto.LUKS_VERSIONS.keys():
raise ValueError("Unknown or unsupported LUKS version '%s'" % self.luks_version)

Expand Down
2 changes: 2 additions & 0 deletions tests/unit_tests/devices_test/device_size_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from blivet.devices import StorageDevice, LUKSDevice
from blivet import errors
from blivet.formats import get_format
from blivet.formats.luks import LUKS
from blivet.size import Size


Expand Down Expand Up @@ -108,6 +109,7 @@ class LUKSDeviceSizeTest(StorageDeviceSizeTest):
def _get_device(self, *args, **kwargs):
exists = kwargs.get("exists", False)
parent = StorageDevice(*args, size=kwargs["size"] + crypto.LUKS_METADATA_SIZE, exists=exists)
parent.format = LUKS()
return LUKSDevice(*args, **kwargs, parents=[parent])

def test_size_getter(self):
Expand Down
14 changes: 14 additions & 0 deletions tests/unit_tests/formats_tests/luks_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,3 +114,17 @@ def test_sector_size_luks2(self):
fmt._create()
crypto.luks_format.assert_called()
self.assertIsNone(crypto.luks_format.call_args[1]["extra"])

def test_header_size(self):
fmt = LUKS(luks_version="luks2")
self.assertEqual(fmt._header_size, Size("16 MiB"))
self.assertEqual(fmt._min_size, Size("16 MiB"))

fmt = LUKS(luks_version="luks1")
self.assertEqual(fmt._header_size, Size("2 MiB"))
self.assertEqual(fmt._min_size, Size("2 MiB"))

# default is luks2
fmt = LUKS()
self.assertEqual(fmt._header_size, Size("16 MiB"))
self.assertEqual(fmt._min_size, Size("16 MiB"))

0 comments on commit c1218f4

Please sign in to comment.