From b0db8fa669f399124204d3689f005f2a45e6238e Mon Sep 17 00:00:00 2001 From: Vojtech Trefny Date: Wed, 22 Jan 2025 14:19:49 +0100 Subject: [PATCH] Fix BitLocker format status and allow closing active BITLK devices Resolves: rhbz#2325038 --- blivet/errors.py | 4 +++ blivet/formats/luks.py | 47 ++++++++++++++++++++++++++-- blivet/populator/helpers/__init__.py | 2 +- blivet/populator/helpers/luks.py | 18 +++++++++++ blivet/tasks/availability.py | 7 +++++ 5 files changed, 75 insertions(+), 3 deletions(-) diff --git a/blivet/errors.py b/blivet/errors.py index d3e87f624..7c144cf8a 100644 --- a/blivet/errors.py +++ b/blivet/errors.py @@ -140,6 +140,10 @@ class IntegrityError(LUKSError): pass +class BitLockerError(DeviceFormatError): + pass + + class MDMemberError(DeviceFormatError): pass diff --git a/blivet/formats/luks.py b/blivet/formats/luks.py index 01ff71355..c8622bc80 100644 --- a/blivet/formats/luks.py +++ b/blivet/formats/luks.py @@ -28,7 +28,7 @@ import os from ..storage_log import log_method_call -from ..errors import LUKSError, IntegrityError +from ..errors import LUKSError, IntegrityError, BitLockerError from ..devicelibs import crypto from . import DeviceFormat, register_device_format from ..flags import flags @@ -635,7 +635,7 @@ def _teardown(self, **kwargs): class BitLocker(DeviceFormat): - """ DM integrity format """ + """ BitLocker format """ _type = "bitlocker" _name = N_("BitLocker") _udev_types = ["BitLocker"] @@ -643,6 +643,49 @@ class BitLocker(DeviceFormat): _formattable = False # can be formatted _linux_native = False # for clearpart _resizable = False # can be resized + _packages = ["cryptsetup"] # required packages + _plugin = availability.BLOCKDEV_CRYPTO_PLUGIN_BITLK + + def __init__(self, **kwargs): + """ + :keyword device: the path to the underlying device + :keyword exists: indicates whether this is an existing format + :type exists: bool + :keyword name: the name of the mapped device + + .. note:: + + The 'device' kwarg is required for existing formats. For non- + existent formats, it is only necessary that the :attr:`device` + attribute be set before the :meth:`create` method runs. Note + that you can specify the device at the last moment by specifying + it via the 'device' kwarg to the :meth:`create` method. + """ + log_method_call(self, **kwargs) + DeviceFormat.__init__(self, **kwargs) + + self.map_name = kwargs.get("name") + + @property + def status(self): + if not self.exists or not self.map_name: + return False + return os.path.exists("/dev/mapper/%s" % self.map_name) + + def _teardown(self, **kwargs): + """ Close, or tear down, the format. """ + log_method_call(self, device=self.device, + type=self.type, status=self.status) + log.debug("unmapping %s", self.map_name) + + # it's safe to use luks_close here, it uses crypt_deactivate which works + # for all devices supported by cryptsetup + try: + blockdev.crypto.luks_close(self.map_name) + except blockdev.CryptoError as e: + raise BitLockerError(e) + + udev.settle() register_device_format(BitLocker) diff --git a/blivet/populator/helpers/__init__.py b/blivet/populator/helpers/__init__.py index e3681b611..b0e778b64 100644 --- a/blivet/populator/helpers/__init__.py +++ b/blivet/populator/helpers/__init__.py @@ -9,7 +9,7 @@ from .disklabel import DiskLabelFormatPopulator from .dm import DMDevicePopulator from .loop import LoopDevicePopulator -from .luks import LUKSDevicePopulator, LUKSFormatPopulator, IntegrityDevicePopulator, IntegrityFormatPopulator, BITLKDevicePopulator +from .luks import LUKSDevicePopulator, LUKSFormatPopulator, IntegrityDevicePopulator, IntegrityFormatPopulator, BITLKDevicePopulator, BitLockerFormatPopulator from .lvm import LVMDevicePopulator, LVMFormatPopulator from .mdraid import MDDevicePopulator, MDFormatPopulator from .multipath import MultipathDevicePopulator, MultipathFormatPopulator diff --git a/blivet/populator/helpers/luks.py b/blivet/populator/helpers/luks.py index 8ece19979..02ba3d890 100644 --- a/blivet/populator/helpers/luks.py +++ b/blivet/populator/helpers/luks.py @@ -207,3 +207,21 @@ def _get_kwargs(self): # is luks- (integrity format has no UUID so we are using name here) kwargs["name"] = "integrity-%s" % udev.device_get_name(self.data) return kwargs + + +class BitLockerFormatPopulator(FormatPopulator): + priority = 100 + _type_specifier = "bitlocker" + + def _get_kwargs(self): + kwargs = super(BitLockerFormatPopulator, self)._get_kwargs() + + holders = udev.device_get_holders(self.data) + if holders: + kwargs["name"] = udev.device_get_name(holders[0]) + else: + # this is just a fallback for closed and non-existing BitLocker devices + # similar to LUKS devices where we assume the name of the active device + # is luks- (BitLocker format has no UUID in udev so we are using name here) + kwargs["name"] = "bitlk-%s" % udev.device_get_name(self.data) + return kwargs diff --git a/blivet/tasks/availability.py b/blivet/tasks/availability.py index 7e689fc71..3be33dc91 100644 --- a/blivet/tasks/availability.py +++ b/blivet/tasks/availability.py @@ -437,6 +437,11 @@ def available_resource(name): blockdev.CryptoTechMode.QUERY)}) BLOCKDEV_CRYPTO_TECH_INTEGRITY = BlockDevMethod(BLOCKDEV_CRYPTO_INTEGRITY) +BLOCKDEV_CRYPTO_BITLK = BlockDevTechInfo(plugin_name="crypto", + check_fn=blockdev.crypto_is_tech_avail, + technologies={blockdev.CryptoTech.BITLK: blockdev.CryptoTechMode.OPEN_CLOSE}) +BLOCKDEV_CRYPTO_TECH_BITLK = BlockDevMethod(BLOCKDEV_CRYPTO_BITLK) + # libblockdev dm plugin required technologies and modes BLOCKDEV_DM_ALL_MODES = (blockdev.DMTechMode.CREATE_ACTIVATE | blockdev.DMTechMode.REMOVE_DEACTIVATE | @@ -578,6 +583,8 @@ class FSOperation(): BLOCKDEV_CRYPTO_PLUGIN = blockdev_plugin("libblockdev crypto plugin", BLOCKDEV_CRYPTO_TECH) BLOCKDEV_CRYPTO_PLUGIN_INTEGRITY = blockdev_plugin("libblockdev crypto plugin (integrity technology)", BLOCKDEV_CRYPTO_TECH_INTEGRITY) +BLOCKDEV_CRYPTO_PLUGIN_BITLK = blockdev_plugin("libblockdev crypto plugin (BitLocker technology)", + BLOCKDEV_CRYPTO_TECH_BITLK) BLOCKDEV_DM_PLUGIN = blockdev_plugin("libblockdev dm plugin", BLOCKDEV_DM_TECH) BLOCKDEV_LOOP_PLUGIN = blockdev_plugin("libblockdev loop plugin", BLOCKDEV_LOOP_TECH) BLOCKDEV_LVM_PLUGIN = blockdev_plugin("libblockdev lvm plugin", BLOCKDEV_LVM_TECH)