From 55f55998c743aa867fca9d7702399c370686686a Mon Sep 17 00:00:00 2001 From: Vojtech Trefny Date: Thu, 18 May 2023 10:35:53 +0200 Subject: [PATCH] Update for 8.9 - Fix setting kickstart data Resolves: rhbz#2175166 - Do not set memory limit for LUKS2 when running in FIPS mode Resolves: rhbz#2183437 - Add support for filesystem online resize Resolves: rhbz#2168680 --- 0013-Fix-setting-kickstart-data.patch | 68 +++++ ...y-limit-for-LUKS2-when-running-in-FI.patch | 133 +++++++++ ...support-for-filesystem-online-resize.patch | 265 ++++++++++++++++++ python-blivet.spec | 13 +- 4 files changed, 478 insertions(+), 1 deletion(-) create mode 100644 0013-Fix-setting-kickstart-data.patch create mode 100644 0014-Do-not-set-memory-limit-for-LUKS2-when-running-in-FI.patch create mode 100644 0015-Add-support-for-filesystem-online-resize.patch diff --git a/0013-Fix-setting-kickstart-data.patch b/0013-Fix-setting-kickstart-data.patch new file mode 100644 index 0000000..1d9a583 --- /dev/null +++ b/0013-Fix-setting-kickstart-data.patch @@ -0,0 +1,68 @@ +From 1af0d3c37a93e431790e641a329a7f34dabf291a Mon Sep 17 00:00:00 2001 +From: Vojtech Trefny +Date: Thu, 2 Mar 2023 12:34:42 +0100 +Subject: [PATCH] Fix setting kickstart data + +When changing our code to PEP8 compliant we also changed some +pykickstart properties like onPart by accident. This PR fixes this. + +Resolves: rhbz#2175166 +--- + blivet/devices/btrfs.py | 4 ++-- + blivet/devices/lvm.py | 2 +- + blivet/devices/partition.py | 6 +++--- + 3 files changed, 6 insertions(+), 6 deletions(-) + +diff --git a/blivet/devices/btrfs.py b/blivet/devices/btrfs.py +index 1ae6a04d..3f56624e 100644 +--- a/blivet/devices/btrfs.py ++++ b/blivet/devices/btrfs.py +@@ -498,8 +498,8 @@ class BTRFSVolumeDevice(BTRFSDevice, ContainerDevice, RaidDevice): + + def populate_ksdata(self, data): + super(BTRFSVolumeDevice, self).populate_ksdata(data) +- data.data_level = self.data_level.name if self.data_level else None +- data.metadata_level = self.metadata_level.name if self.metadata_level else None ++ data.dataLevel = self.data_level.name if self.data_level else None ++ data.metaDataLevel = self.metadata_level.name if self.metadata_level else None + data.devices = ["btrfs.%d" % p.id for p in self.parents] + data.preexist = self.exists + +diff --git a/blivet/devices/lvm.py b/blivet/devices/lvm.py +index 41358e9b..c3132457 100644 +--- a/blivet/devices/lvm.py ++++ b/blivet/devices/lvm.py +@@ -1161,7 +1161,7 @@ class LVMLogicalVolumeBase(DMDevice, RaidDevice): + + if self.req_grow: + # base size could be literal or percentage +- data.max_size_mb = self.req_max_size.convert_to(MiB) ++ data.maxSizeMB = self.req_max_size.convert_to(MiB) + elif data.resize: + data.size = self.target_size.convert_to(MiB) + +diff --git a/blivet/devices/partition.py b/blivet/devices/partition.py +index 89d907c2..0e9250ce 100644 +--- a/blivet/devices/partition.py ++++ b/blivet/devices/partition.py +@@ -982,14 +982,14 @@ class PartitionDevice(StorageDevice): + data.size = self.req_base_size.round_to_nearest(MiB, rounding=ROUND_DOWN).convert_to(spec=MiB) + data.grow = self.req_grow + if self.req_grow: +- data.max_size_mb = self.req_max_size.convert_to(MiB) ++ data.maxSizeMB = self.req_max_size.convert_to(MiB) + + # data.disk = self.disk.name # by-id + if self.req_disks and len(self.req_disks) == 1: + data.disk = self.disk.name +- data.prim_only = self.req_primary ++ data.primOnly = self.req_primary + else: +- data.on_part = self.name # by-id ++ data.onPart = self.name # by-id + + if data.resize: + # on s390x in particular, fractional sizes are reported, which +-- +2.40.1 + diff --git a/0014-Do-not-set-memory-limit-for-LUKS2-when-running-in-FI.patch b/0014-Do-not-set-memory-limit-for-LUKS2-when-running-in-FI.patch new file mode 100644 index 0000000..e6e90c5 --- /dev/null +++ b/0014-Do-not-set-memory-limit-for-LUKS2-when-running-in-FI.patch @@ -0,0 +1,133 @@ +From c2b06150df0b876c7d442097b6c9ca90c9ca2ecc Mon Sep 17 00:00:00 2001 +From: Vojtech Trefny +Date: Thu, 4 May 2023 11:35:44 +0200 +Subject: [PATCH] Do not set memory limit for LUKS2 when running in FIPS mode + +With FIPS enabled LUKS uses pbkdf and not argon so the memory +limit is not a valid parameter. + +Resolves: rhbz#2183437 +--- + blivet/devicelibs/crypto.py | 11 +++++++ + blivet/formats/luks.py | 12 ++++---- + tests/unit_tests/formats_tests/luks_test.py | 30 +++++++++++++++++++ + .../unit_tests/formats_tests/methods_test.py | 3 +- + 4 files changed, 50 insertions(+), 6 deletions(-) + +diff --git a/blivet/devicelibs/crypto.py b/blivet/devicelibs/crypto.py +index f0caf0f7..68e68db1 100644 +--- a/blivet/devicelibs/crypto.py ++++ b/blivet/devicelibs/crypto.py +@@ -21,6 +21,7 @@ + # + + import hashlib ++import os + + import gi + gi.require_version("BlockDev", "2.0") +@@ -100,3 +101,13 @@ def calculate_integrity_metadata_size(device_size, algorithm=DEFAULT_INTEGRITY_A + jsize = (jsize / SECTOR_SIZE + 1) * SECTOR_SIZE # round up to sector + + return msize + jsize ++ ++ ++def is_fips_enabled(): ++ if not os.path.exists("/proc/sys/crypto/fips_enabled"): ++ # if the file doesn't exist, we are definitely not in FIPS mode ++ return False ++ ++ with open("/proc/sys/crypto/fips_enabled", "r") as f: ++ enabled = f.read() ++ return enabled.strip() == "1" +diff --git a/blivet/formats/luks.py b/blivet/formats/luks.py +index 2637e0c5..adf3c711 100644 +--- a/blivet/formats/luks.py ++++ b/blivet/formats/luks.py +@@ -303,11 +303,13 @@ class LUKS(DeviceFormat): + if luks_data.pbkdf_args: + self.pbkdf_args = luks_data.pbkdf_args + else: +- mem_limit = crypto.calculate_luks2_max_memory() +- if mem_limit: +- self.pbkdf_args = LUKS2PBKDFArgs(max_memory_kb=int(mem_limit.convert_to(KiB))) +- luks_data.pbkdf_args = self.pbkdf_args +- log.info("PBKDF arguments for LUKS2 not specified, using defaults with memory limit %s", mem_limit) ++ # argon is not used with FIPS so we don't need to adjust the memory when in FIPS mode ++ if not crypto.is_fips_enabled(): ++ mem_limit = crypto.calculate_luks2_max_memory() ++ if mem_limit: ++ self.pbkdf_args = LUKS2PBKDFArgs(max_memory_kb=int(mem_limit.convert_to(KiB))) ++ luks_data.pbkdf_args = self.pbkdf_args ++ log.info("PBKDF arguments for LUKS2 not specified, using defaults with memory limit %s", mem_limit) + + if self.pbkdf_args: + pbkdf = blockdev.CryptoLUKSPBKDF(type=self.pbkdf_args.type, +diff --git a/tests/unit_tests/formats_tests/luks_test.py b/tests/unit_tests/formats_tests/luks_test.py +index ec7b7592..1127e968 100644 +--- a/tests/unit_tests/formats_tests/luks_test.py ++++ b/tests/unit_tests/formats_tests/luks_test.py +@@ -6,9 +6,14 @@ except ImportError: + import unittest + + from blivet.formats.luks import LUKS ++from blivet.size import Size ++from blivet.static_data import luks_data + + + class LUKSNodevTestCase(unittest.TestCase): ++ def setUp(self): ++ luks_data.pbkdf_args = None ++ + def test_create_discard_option(self): + # flags.discard_new=False --> no discard + fmt = LUKS(exists=False) +@@ -51,6 +56,31 @@ class LUKSNodevTestCase(unittest.TestCase): + fmt = LUKS(cipher="aes-cbc-plain64") + self.assertEqual(fmt.key_size, 0) + ++ def test_luks2_pbkdf_memory_fips(self): ++ fmt = LUKS() ++ with patch("blivet.formats.luks.blockdev.crypto") as bd: ++ # fips enabled, pbkdf memory should not be set ++ with patch("blivet.formats.luks.crypto") as crypto: ++ attrs = {"is_fips_enabled.return_value": True, ++ "get_optimal_luks_sector_size.return_value": 0, ++ "calculate_luks2_max_memory.return_value": Size("256 MiB")} ++ crypto.configure_mock(**attrs) ++ ++ fmt._create() ++ crypto.calculate_luks2_max_memory.assert_not_called() ++ self.assertEqual(bd.luks_format.call_args[1]["extra"].pbkdf.max_memory_kb, 0) ++ ++ # fips disabled, pbkdf memory should be set ++ with patch("blivet.formats.luks.crypto") as crypto: ++ attrs = {"is_fips_enabled.return_value": False, ++ "get_optimal_luks_sector_size.return_value": 0, ++ "calculate_luks2_max_memory.return_value": Size("256 MiB")} ++ crypto.configure_mock(**attrs) ++ ++ fmt._create() ++ crypto.calculate_luks2_max_memory.assert_called() ++ self.assertEqual(bd.luks_format.call_args[1]["extra"].pbkdf.max_memory_kb, 256 * 1024) ++ + def test_sector_size(self): + fmt = LUKS() + self.assertEqual(fmt.luks_sector_size, 512) +diff --git a/tests/unit_tests/formats_tests/methods_test.py b/tests/unit_tests/formats_tests/methods_test.py +index 2743b7db..5d30c260 100644 +--- a/tests/unit_tests/formats_tests/methods_test.py ++++ b/tests/unit_tests/formats_tests/methods_test.py +@@ -366,7 +366,8 @@ class LUKSMethodsTestCase(FormatMethodsTestCase): + + def _test_create_backend(self): + self.format.exists = False +- self.format.create() ++ with patch("blivet.devicelibs.crypto.is_fips_enabled", return_value=False): ++ self.format.create() + self.assertTrue(self.patches["blockdev"].crypto.luks_format.called) # pylint: disable=no-member + + def _test_setup_backend(self): +-- +2.40.1 + diff --git a/0015-Add-support-for-filesystem-online-resize.patch b/0015-Add-support-for-filesystem-online-resize.patch new file mode 100644 index 0000000..39f30e8 --- /dev/null +++ b/0015-Add-support-for-filesystem-online-resize.patch @@ -0,0 +1,265 @@ +From eb16230427fc1081f8515e6ad69ccf99ca521e5d Mon Sep 17 00:00:00 2001 +From: Vojtech Trefny +Date: Tue, 4 Apr 2023 13:31:40 +0200 +Subject: [PATCH 1/2] Add support for filesystem online resize + +Resolves: rhbz#2168680 +--- + blivet/devices/lvm.py | 13 ++++++++----- + blivet/devices/partition.py | 11 ++++++----- + blivet/flags.py | 3 +++ + blivet/formats/fs.py | 32 ++++++++++++++++++++++++++++---- + blivet/formats/fslib.py | 7 +++++++ + 5 files changed, 52 insertions(+), 14 deletions(-) + +diff --git a/blivet/devices/lvm.py b/blivet/devices/lvm.py +index c3132457..ca45c4b5 100644 +--- a/blivet/devices/lvm.py ++++ b/blivet/devices/lvm.py +@@ -42,6 +42,7 @@ from .. import errors + from .. import util + from ..storage_log import log_method_call + from .. import udev ++from ..flags import flags + from ..size import Size, KiB, MiB, ROUND_UP, ROUND_DOWN + from ..static_data.lvm_info import lvs_info + from ..tasks import availability +@@ -2729,12 +2730,14 @@ class LVMLogicalVolumeDevice(LVMLogicalVolumeBase, LVMInternalLogicalVolumeMixin + # Setup VG parents (in case they are dmraid partitions for example) + self.vg.setup_parents(orig=True) + +- if self.original_format.exists: +- self.original_format.teardown() +- if self.format.exists: +- self.format.teardown() ++ if not flags.allow_online_fs_resize: ++ if self.original_format.exists: ++ self.original_format.teardown() ++ if self.format.exists: ++ self.format.teardown() ++ ++ udev.settle() + +- udev.settle() + blockdev.lvm.lvresize(self.vg.name, self._name, self.size) + + @type_specific +diff --git a/blivet/devices/partition.py b/blivet/devices/partition.py +index 0e9250ce..6ae4b8d3 100644 +--- a/blivet/devices/partition.py ++++ b/blivet/devices/partition.py +@@ -745,11 +745,12 @@ class PartitionDevice(StorageDevice): + if not self.exists: + raise errors.DeviceError("device has not been created") + +- # don't teardown when resizing luks +- if self.format.type == "luks" and self.children: +- self.children[0].format.teardown() +- else: +- self.teardown() ++ if not flags.allow_online_fs_resize: ++ # don't teardown when resizing luks ++ if self.format.type == "luks" and self.children: ++ self.children[0].format.teardown() ++ else: ++ self.teardown() + + if not self.sysfs_path: + return +diff --git a/blivet/flags.py b/blivet/flags.py +index 6364164d..ecfa7ad7 100644 +--- a/blivet/flags.py ++++ b/blivet/flags.py +@@ -91,6 +91,9 @@ class Flags(object): + + self.debug_threads = False + ++ # Allow online filesystem resizes ++ self.allow_online_fs_resize = False ++ + def get_boot_cmdline(self): + with open("/proc/cmdline") as f: + buf = f.read().strip() +diff --git a/blivet/formats/fs.py b/blivet/formats/fs.py +index 33922f3a..3f553eb0 100644 +--- a/blivet/formats/fs.py ++++ b/blivet/formats/fs.py +@@ -56,7 +56,7 @@ from ..i18n import N_ + from .. import udev + from ..mounts import mounts_cache + +-from .fslib import kernel_filesystems ++from .fslib import kernel_filesystems, FSResize + + import logging + log = logging.getLogger("blivet") +@@ -88,6 +88,9 @@ class FS(DeviceFormat): + # value is already unpredictable and can change in the future... + _metadata_size_factor = 1.0 + ++ # support for resize: grow/shrink, online/offline ++ _resize_support = 0 ++ + config_actions_map = {"label": "write_label"} + + def __init__(self, **kwargs): +@@ -436,12 +439,27 @@ class FS(DeviceFormat): + self.write_uuid() + + def _pre_resize(self): +- # file systems need a check before being resized +- self.do_check() ++ if self.status: ++ if flags.allow_online_fs_resize: ++ if self.target_size > self.size and not self._resize_support & FSResize.ONLINE_GROW: ++ raise FSError("This filesystem doesn't support online growing") ++ if self.target_size < self.size and not self._resize_support & FSResize.ONLINE_SHRINK: ++ raise FSError("This filesystem doesn't support online shrinking") ++ else: ++ raise FSError("Resizing of mounted filesystems is disabled") ++ ++ if self.status: ++ # fsck tools in general don't allow checks on mounted filesystems ++ log.debug("Filesystem on %s is mounted, not checking", self.device) ++ else: ++ # file systems need a check before being resized ++ self.do_check() ++ + super(FS, self)._pre_resize() + + def _post_resize(self): +- self.do_check() ++ if not self.status: ++ self.do_check() + super(FS, self)._post_resize() + + def do_check(self): +@@ -838,6 +856,7 @@ class Ext2FS(FS): + _formattable = True + _supported = True + _resizable = True ++ _resize_support = FSResize.ONLINE_GROW | FSResize.OFFLINE_GROW | FSResize.OFFLINE_SHRINK + _linux_native = True + _max_size = Size("8 TiB") + _dump = True +@@ -1097,6 +1116,7 @@ class XFS(FS): + _linux_native = True + _supported = True + _resizable = True ++ _resize_support = FSResize.ONLINE_GROW | FSResize.OFFLINE_GROW + _packages = ["xfsprogs"] + _fsck_class = fsck.XFSCK + _info_class = fsinfo.XFSInfo +@@ -1247,6 +1267,7 @@ class NTFS(FS): + _labelfs = fslabeling.NTFSLabeling() + _uuidfs = fsuuid.NTFSUUID() + _resizable = True ++ _resize_support = FSResize.OFFLINE_GROW | FSResize.OFFLINE_SHRINK + _formattable = True + _supported = True + _min_size = Size("1 MiB") +@@ -1490,6 +1511,9 @@ class TmpFS(NoDevFS): + # same, nothing actually needs to be set + pass + ++ def _pre_resize(self): ++ self.do_check() ++ + def do_resize(self): + # Override superclass method to record whether mount options + # should include an explicit size specification. +diff --git a/blivet/formats/fslib.py b/blivet/formats/fslib.py +index ea93b1fd..8722e942 100644 +--- a/blivet/formats/fslib.py ++++ b/blivet/formats/fslib.py +@@ -36,3 +36,10 @@ def update_kernel_filesystems(): + + + update_kernel_filesystems() ++ ++ ++class FSResize(): ++ OFFLINE_SHRINK = 1 << 1 ++ OFFLINE_GROW = 1 << 2 ++ ONLINE_SHRINK = 1 << 3 ++ ONLINE_GROW = 1 << 4 +-- +2.40.1 + + +From 3fce5d0bfd7b09a976ff49feed15077477c6a425 Mon Sep 17 00:00:00 2001 +From: Vojtech Trefny +Date: Thu, 6 Apr 2023 14:02:11 +0200 +Subject: [PATCH 2/2] Add a test case for filesystem online resize + +Related: rhbz#2168680 +--- + tests/storage_tests/formats_test/fs_test.py | 43 ++++++++++++++++++++- + 1 file changed, 42 insertions(+), 1 deletion(-) + +diff --git a/tests/storage_tests/formats_test/fs_test.py b/tests/storage_tests/formats_test/fs_test.py +index 97f4cbbe..1d42dc21 100644 +--- a/tests/storage_tests/formats_test/fs_test.py ++++ b/tests/storage_tests/formats_test/fs_test.py +@@ -6,9 +6,10 @@ import parted + + import blivet.formats.fs as fs + from blivet.size import Size, ROUND_DOWN +-from blivet.errors import DeviceFormatError ++from blivet.errors import DeviceFormatError, FSError + from blivet.formats import get_format + from blivet.devices import PartitionDevice, DiskDevice ++from blivet.flags import flags + + from .loopbackedtestcase import LoopBackedTestCase + +@@ -26,6 +27,46 @@ class Ext3FSTestCase(Ext2FSTestCase): + class Ext4FSTestCase(Ext3FSTestCase): + _fs_class = fs.Ext4FS + ++ def test_online_resize(self): ++ an_fs = self._fs_class() ++ if not an_fs.formattable: ++ self.skipTest("can not create filesystem %s" % an_fs.name) ++ an_fs.device = self.loop_devices[0] ++ self.assertIsNone(an_fs.create()) ++ an_fs.update_size_info() ++ ++ if not self.can_resize(an_fs): ++ self.skipTest("filesystem is not resizable") ++ ++ # shrink offline first (ext doesn't support online shrinking) ++ TARGET_SIZE = Size("64 MiB") ++ an_fs.target_size = TARGET_SIZE ++ self.assertEqual(an_fs.target_size, TARGET_SIZE) ++ self.assertNotEqual(an_fs._size, TARGET_SIZE) ++ self.assertIsNone(an_fs.do_resize()) ++ ++ with tempfile.TemporaryDirectory() as mountpoint: ++ an_fs.mount(mountpoint=mountpoint) ++ ++ # grow back when mounted ++ TARGET_SIZE = Size("100 MiB") ++ an_fs.target_size = TARGET_SIZE ++ self.assertEqual(an_fs.target_size, TARGET_SIZE) ++ self.assertNotEqual(an_fs._size, TARGET_SIZE) ++ ++ # should fail, online resize disabled by default ++ with self.assertRaisesRegex(FSError, "Resizing of mounted filesystems is disabled"): ++ an_fs.do_resize() ++ ++ # enable online resize ++ flags.allow_online_fs_resize = True ++ an_fs.do_resize() ++ flags.allow_online_fs_resize = False ++ self._test_sizes(an_fs) ++ self.assertEqual(an_fs.system_mountpoint, mountpoint) ++ ++ an_fs.unmount() ++ + + class FATFSTestCase(fstesting.FSAsRoot): + _fs_class = fs.FATFS +-- +2.40.1 + diff --git a/python-blivet.spec b/python-blivet.spec index 91c0cf7..aed32ae 100644 --- a/python-blivet.spec +++ b/python-blivet.spec @@ -23,7 +23,7 @@ Version: 3.6.0 #%%global prerelease .b2 # prerelease, if defined, should be something like .a1, .b1, .b2.dev1, or .c2 -Release: 5%{?prerelease}%{?dist} +Release: 6%{?prerelease}%{?dist} Epoch: 1 License: LGPLv2+ %global realname blivet @@ -42,6 +42,9 @@ Patch8: 0009-Revert-Adjust-to-new-XFS-min-size.patch Patch9: 0010-Catch-BlockDevNotImplementedError-for-btrfs-plugin-c.patch Patch10: 0011-Default-to-encryption-sector-size-512-for-LUKS-devic.patch Patch11: 0012-Add-support-for-specifying-stripe-size-for-RAID-LVs.patch +Patch12: 0013-Fix-setting-kickstart-data.patch +Patch13: 0014-Do-not-set-memory-limit-for-LUKS2-when-running-in-FI.patch +Patch14: 0015-Add-support-for-filesystem-online-resize.patch # Versions of required components (done so we make sure the buildrequires # match the requires versions of things). @@ -204,6 +207,14 @@ configuration. %endif %changelog +* Thu May 18 2023 Vojtech Trefny - 3.6.0-6 +- Fix setting kickstart data + Resolves: rhbz#2175166 +- Do not set memory limit for LUKS2 when running in FIPS mode + Resolves: rhbz#2183437 +- Add support for filesystem online resize + Resolves: rhbz#2168680 + * Tue May 02 2023 Vojtech Trefny - 3.6.0-5 - Add support for specifying stripe size for RAID LVs Resolves: rhbz#2142550