libblockdev/0015-crypto-Add-a-function-to-set-persistent-flags-for-LU.patch
2025-03-12 08:56:22 +01:00

234 lines
9.3 KiB
Diff

From a0f99ca404218f1da0820e55000531fe0c67f270 Mon Sep 17 00:00:00 2001
From: Vojtech Trefny <vtrefny@redhat.com>
Date: Thu, 6 Mar 2025 14:41:16 +0100
Subject: [PATCH] crypto: Add a function to set persistent flags for LUKS
This will be used to set the allow-discards flag on LUKS devices
during installation by Blivet.
---
configure.ac | 6 +++
src/lib/plugin_apis/crypto.api | 24 +++++++++++
src/plugins/crypto.c | 76 ++++++++++++++++++++++++++++++++++
src/plugins/crypto.h | 11 +++++
tests/crypto_test.py | 29 +++++++++++++
5 files changed, 146 insertions(+)
diff --git a/configure.ac b/configure.ac
index 14d5974c..158b000f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -226,6 +226,12 @@ AS_IF([test "x$with_crypto" != "xno"],
[AC_DEFINE([LIBCRYPTSETUP_23])], [])
AS_IF([$PKG_CONFIG --atleast-version=2.4.0 libcryptsetup],
[AC_DEFINE([LIBCRYPTSETUP_24])], [])
+ AS_IF([$PKG_CONFIG --atleast-version=2.6.0 libcryptsetup],
+ [AC_DEFINE([LIBCRYPTSETUP_26])], [])
+ AS_IF([$PKG_CONFIG --atleast-version=2.7.0 libcryptsetup],
+ [AC_DEFINE([LIBCRYPTSETUP_27])], [])
+ AS_IF([$PKG_CONFIG --atleast-version=2.8.0 libcryptsetup],
+ [AC_DEFINE([LIBCRYPTSETUP_28])], [])
AS_IF([test "x$with_escrow" != "xno"],
[LIBBLOCKDEV_PKG_CHECK_MODULES([NSS], [nss >= 3.18.0])
LIBBLOCKDEV_CHECK_HEADER([volume_key/libvolume_key.h], [$GLIB_CFLAGS $NSS_CFLAGS], [libvolume_key.h not available])],
diff --git a/src/lib/plugin_apis/crypto.api b/src/lib/plugin_apis/crypto.api
index cf87979d..81087ce4 100644
--- a/src/lib/plugin_apis/crypto.api
+++ b/src/lib/plugin_apis/crypto.api
@@ -353,6 +353,16 @@ typedef enum {
#define BD_CRYPTO_TYPE_LUKS_INFO (bd_crypto_luks_info_get_type ())
GType bd_crypto_luks_info_get_type();
+typedef enum {
+ BD_CRYPTO_LUKS_ACTIVATE_ALLOW_DISCARDS = 1 << 0,
+ BD_CRYPTO_LUKS_ACTIVATE_SAME_CPU_CRYPT = 1 << 1,
+ BD_CRYPTO_LUKS_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS = 1 << 2,
+ BD_CRYPTO_LUKS_ACTIVATE_NO_JOURNAL = 1 << 3,
+ BD_CRYPTO_LUKS_ACTIVATE_NO_READ_WORKQUEUE = 1 << 4,
+ BD_CRYPTO_LUKS_ACTIVATE_NO_WRITE_WORKQUEUE = 1 << 5,
+ BD_CRYPTO_LUKS_ACTIVATE_HIGH_PRIORITY = 1 << 6,
+} BDCryptoLUKSPersistentFlags;
+
/**
* BDCryptoLUKSInfo:
* @version: LUKS version
@@ -940,6 +950,20 @@ gboolean bd_crypto_luks_header_backup (const gchar *device, const gchar *backup_
*/
gboolean bd_crypto_luks_header_restore (const gchar *device, const gchar *backup_file, GError **error);
+/**
+ * bd_crypto_luks_set_persistent_flags:
+ * @device: a LUKS device to set the persistent flags on
+ * @flags: flags to set
+ * @error: (out) (optional): place to store error (if any)
+ *
+ * Note: This function is valid only for LUKS2.
+ *
+ * Returns: whether the given @flags were successfully set or not
+ *
+ * Tech category: %BD_CRYPTO_TECH_LUKS-%BD_CRYPTO_TECH_MODE_MODIFY
+ */
+gboolean bd_crypto_luks_set_persistent_flags (const gchar *device, BDCryptoLUKSPersistentFlags flags, GError **error);
+
/**
* bd_crypto_luks_info:
* @luks_device: a device to get information about
diff --git a/src/plugins/crypto.c b/src/plugins/crypto.c
index 2086209e..ed7c0c5a 100644
--- a/src/plugins/crypto.c
+++ b/src/plugins/crypto.c
@@ -1978,6 +1978,82 @@ gboolean bd_crypto_luks_header_restore (const gchar *device, const gchar *backup
return TRUE;
}
+/**
+ * bd_crypto_luks_set_persistent_flags:
+ * @device: a LUKS device to set the persistent flags on
+ * @flags: flags to set
+ * @error: (out) (optional): place to store error (if any)
+ *
+ * Note: This function is valid only for LUKS2.
+ *
+ * Returns: whether the given @flags were successfully set or not
+ *
+ * Tech category: %BD_CRYPTO_TECH_LUKS-%BD_CRYPTO_TECH_MODE_MODIFY
+ */
+gboolean bd_crypto_luks_set_persistent_flags (const gchar *device, BDCryptoLUKSPersistentFlags flags, GError **error) {
+ struct crypt_device *cd = NULL;
+ gint ret = 0;
+ guint32 crypt_flags = 0;
+
+ ret = crypt_init (&cd, device);
+ if (ret != 0) {
+ g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,
+ "Failed to initialize device: %s", strerror_l (-ret, c_locale));
+ return FALSE;
+ }
+
+ ret = crypt_load (cd, CRYPT_LUKS, NULL);
+ if (ret != 0) {
+ g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,
+ "Failed to load device: %s", strerror_l (-ret, c_locale));
+ crypt_free (cd);
+ return FALSE;
+ }
+
+ if (g_strcmp0 (crypt_get_type (cd), CRYPT_LUKS2) != 0) {
+ g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,
+ "Persistent flags can be set only on LUKS v2");
+ crypt_free (cd);
+ return FALSE;
+ }
+
+ if (flags & BD_CRYPTO_LUKS_ACTIVATE_ALLOW_DISCARDS)
+ crypt_flags |= CRYPT_ACTIVATE_ALLOW_DISCARDS;
+ if (flags & BD_CRYPTO_LUKS_ACTIVATE_SAME_CPU_CRYPT)
+ crypt_flags |= CRYPT_ACTIVATE_SAME_CPU_CRYPT;
+ if (flags & BD_CRYPTO_LUKS_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS)
+ crypt_flags |= CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS;
+ if (flags & BD_CRYPTO_LUKS_ACTIVATE_NO_JOURNAL)
+ crypt_flags |= CRYPT_ACTIVATE_NO_JOURNAL;
+ if (flags & BD_CRYPTO_LUKS_ACTIVATE_NO_READ_WORKQUEUE)
+ crypt_flags |= CRYPT_ACTIVATE_NO_READ_WORKQUEUE;
+ if (flags & BD_CRYPTO_LUKS_ACTIVATE_NO_WRITE_WORKQUEUE)
+ crypt_flags |= CRYPT_ACTIVATE_NO_WRITE_WORKQUEUE;
+ if (flags & BD_CRYPTO_LUKS_ACTIVATE_HIGH_PRIORITY) {
+#ifdef LIBCRYPTSETUP_28
+ crypt_flags |= CRYPT_ACTIVATE_HIGH_PRIORITY;
+#else
+ g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_TECH_UNAVAIL,
+ "Libcryptsetup 2.8 or newer is needed for 'high priority' flag support");
+ crypt_free (cd);
+ return FALSE;
+#endif
+ }
+
+
+ ret = crypt_persistent_flags_set (cd, CRYPT_FLAGS_ACTIVATION, crypt_flags);
+ if (ret != 0) {
+ g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,
+ "Failed to set flags: %s", strerror_l (-ret, c_locale));
+ crypt_free (cd);
+ return FALSE;
+ }
+
+ crypt_free (cd);
+
+ return TRUE;
+}
+
/**
* bd_crypto_luks_info:
* @luks_device: a device to get information about
diff --git a/src/plugins/crypto.h b/src/plugins/crypto.h
index 536accf9..15acd4e6 100644
--- a/src/plugins/crypto.h
+++ b/src/plugins/crypto.h
@@ -155,6 +155,16 @@ typedef enum {
BD_CRYPTO_INTEGRITY_OPEN_ALLOW_DISCARDS = 1 << 5,
} BDCryptoIntegrityOpenFlags;
+typedef enum {
+ BD_CRYPTO_LUKS_ACTIVATE_ALLOW_DISCARDS = 1 << 0,
+ BD_CRYPTO_LUKS_ACTIVATE_SAME_CPU_CRYPT = 1 << 1,
+ BD_CRYPTO_LUKS_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS = 1 << 2,
+ BD_CRYPTO_LUKS_ACTIVATE_NO_JOURNAL = 1 << 3,
+ BD_CRYPTO_LUKS_ACTIVATE_NO_READ_WORKQUEUE = 1 << 4,
+ BD_CRYPTO_LUKS_ACTIVATE_NO_WRITE_WORKQUEUE = 1 << 5,
+ BD_CRYPTO_LUKS_ACTIVATE_HIGH_PRIORITY = 1 << 6,
+} BDCryptoLUKSPersistentFlags;
+
/**
* BDCryptoLUKSInfo:
* @version: LUKS version
@@ -244,6 +254,7 @@ gboolean bd_crypto_luks_resume (const gchar *luks_device, const gchar *passphras
gboolean bd_crypto_luks_kill_slot (const gchar *device, gint slot, GError **error);
gboolean bd_crypto_luks_header_backup (const gchar *device, const gchar *backup_file, GError **error);
gboolean bd_crypto_luks_header_restore (const gchar *device, const gchar *backup_file, GError **error);
+gboolean bd_crypto_luks_set_persistent_flags (const gchar *device, BDCryptoLUKSPersistentFlags flags, GError **error);
BDCryptoLUKSInfo* bd_crypto_luks_info (const gchar *luks_device, GError **error);
BDCryptoIntegrityInfo* bd_crypto_integrity_info (const gchar *device, GError **error);
diff --git a/tests/crypto_test.py b/tests/crypto_test.py
index 91ea1f35..b16e719d 100644
--- a/tests/crypto_test.py
+++ b/tests/crypto_test.py
@@ -978,6 +978,35 @@ class CryptoTestInfo(CryptoTestCase):
self.assertTrue(succ)
+class CryptoTestSetPersistentFlags(CryptoTestCase):
+
+ @tag_test(TestTags.SLOW, TestTags.CORE)
+ def test_luks_set_persistent_flags(self):
+ """Verify that we can set flags on a LUKS device"""
+
+ self._luks_format(self.loop_dev, PASSWD, None)
+
+ with self.assertRaisesRegex(GLib.GError, "Persistent flags can be set only on LUKS v2"):
+ BlockDev.crypto_luks_set_persistent_flags(self.loop_dev,
+ BlockDev.CryptoLUKSPersistentFlags.ALLOW_DISCARDS)
+
+ @tag_test(TestTags.SLOW, TestTags.CORE)
+ def test_luks_set_persistent_flags(self):
+ """Verify that we can set flags on a LUKS 2 device"""
+
+ self._luks2_format(self.loop_dev, PASSWD, None)
+
+ succ = BlockDev.crypto_luks_set_persistent_flags(self.loop_dev,
+ BlockDev.CryptoLUKSPersistentFlags.ALLOW_DISCARDS)
+ self.assertTrue(succ)
+
+ _ret, out, err = run_command("cryptsetup luksDump %s" % self.loop_dev)
+ m = re.search(r"Flags:\s*(\S+)\s*", out)
+ if not m or len(m.groups()) != 1:
+ self.fail("Failed to get label information from:\n%s %s" % (out, err))
+ self.assertEqual(m.group(1), "allow-discards")
+
+
class CryptoTestLuksSectorSize(CryptoTestCase):
def setUp(self):
if not check_cryptsetup_version("2.4.0"):
--
2.48.1