Detect old dm-crypt module and disable LUKS suspend/resume.
authorMilan Broz <gmazyland@gmail.com>
Fri, 30 Apr 2010 12:03:41 +0000 (12:03 +0000)
committerMilan Broz <gmazyland@gmail.com>
Fri, 30 Apr 2010 12:03:41 +0000 (12:03 +0000)
Fix apitest to work on older systems.

git-svn-id: https://cryptsetup.googlecode.com/svn/trunk@205 36d66b0a-2a48-0410-832c-cd162a569da5

ChangeLog
lib/libdevmapper.c
lib/setup.c
tests/apitest.c

index f61ee59..5ccd91b 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2010-04-30  Milan Broz  <mbroz@redhat.com>
+       * Try to use pkgconfig for device mapper library.
+       * Detect old dm-crypt module and disable LUKS suspend/resume.
+       * Fix apitest to work on older systems.
+
 2010-04-12  Milan Broz  <mbroz@redhat.com>
        * Fix package config to use proper package version.
        * Avoid class C++ keyword in library header.
index e697f71..6040727 100644 (file)
@@ -18,6 +18,8 @@
 #define DM_CRYPT_TARGET                "crypt"
 #define RETRY_COUNT            5
 
+static int _dm_crypt_wipe_key_supported = 0;
+
 static int _dm_use_count = 0;
 static struct crypt_device *_context = NULL;
 
@@ -61,16 +63,63 @@ static void set_dm_error(int level, const char *file, int line,
 
 static int _dm_simple(int task, const char *name, int udev_wait);
 
+static void _dm_set_crypt_compat(struct crypt_device *context,
+                                int maj, int min, int patch)
+{
+       log_dbg("Detected dm-crypt target of version %i.%i.%i.", maj, min, patch);
+
+       if (maj >= 1 && min >=2)
+               _dm_crypt_wipe_key_supported = 1;
+       else
+               log_dbg("Suspend and resume disabled, no wipe key support.");
+}
+
+static int _dm_check_versions(struct crypt_device *context)
+{
+       int r = 0;
+       struct dm_task *dmt;
+       struct dm_versions *target, *last_target;
+
+       if (!(dmt = dm_task_create(DM_DEVICE_LIST_VERSIONS)))
+               goto fail_versions;
+
+       if (!dm_task_run(dmt)) {
+               dm_task_destroy(dmt);
+               goto fail_versions;
+       }
+
+       target = dm_task_get_versions(dmt);
+       do {
+               last_target = target;
+               if (!strcmp(DM_CRYPT_TARGET, target->name)) {
+                       r = 1;
+                       _dm_set_crypt_compat(context,
+                                            (int)target->version[0],
+                                            (int)target->version[1],
+                                            (int)target->version[2]);
+               }
+               target = (void *) target + target->next;
+       } while (last_target != target);
+
+       if (!r)
+               log_err(context, _("Cannot find compatible device-mapper kernel modules.\n"));
+
+       dm_task_destroy(dmt);
+       return r;
+
+fail_versions:
+       log_err(context, _("Cannot initialize device-mapper. Is dm_mod kernel module loaded?\n"));
+       return 0;
+}
+
 int dm_init(struct crypt_device *context, int check_kernel)
 {
        if (!_dm_use_count++) {
                log_dbg("Initialising device-mapper backend%s, UDEV is %sabled.",
                        check_kernel ? "" : " (NO kernel check requested)",
                        _dm_use_udev() ? "en" : "dis");
-               if (check_kernel && !_dm_simple(DM_DEVICE_LIST_VERSIONS, NULL, 0)) {
-                       log_err(context, _("Cannot initialize device-mapper. Is dm_mod kernel module loaded?\n"));
+               if (check_kernel && !_dm_check_versions(context))
                        return -1;
-               }
                if (getuid() || geteuid())
                        log_dbg(("WARNING: Running as a non-root user. Functionality may be unavailable."));
                dm_log_init(set_dm_error);
@@ -665,6 +714,9 @@ static int _dm_message(const char *name, const char *msg)
 
 int dm_suspend_and_wipe_key(const char *name)
 {
+       if (!_dm_crypt_wipe_key_supported)
+               return -ENOTSUP;
+
        if (!_dm_simple(DM_DEVICE_SUSPEND, name, 0))
                return -EINVAL;
 
@@ -684,6 +736,9 @@ int dm_resume_and_reinstate_key(const char *name,
        char *msg;
        int r = 0;
 
+       if (!_dm_crypt_wipe_key_supported)
+               return -ENOTSUP;
+
        msg = safe_alloc(msg_size);
        if (!msg)
                return -ENOMEM;
index 061636b..fd264f3 100644 (file)
@@ -1304,7 +1304,9 @@ int crypt_suspend(struct crypt_device *cd,
        }
 
        r = dm_suspend_and_wipe_key(name);
-       if (r)
+       if (r == -ENOTSUP)
+               log_err(cd, "Suspend is not supported for device %s.\n", name);
+       else if (r)
                log_err(cd, "Error during suspending device %s.\n", name);
 out:
        if (!cd)
@@ -1348,7 +1350,9 @@ int crypt_resume_by_passphrase(struct crypt_device *cd,
        if (r >= 0) {
                keyslot = r;
                r = dm_resume_and_reinstate_key(name, mk->keyLength, mk->key);
-               if (r)
+               if (r == -ENOTSUP)
+                       log_err(cd, "Resume is not supported for device %s.\n", name);
+               else if (r)
                        log_err(cd, "Error during resuming device %s.\n", name);
        } else
                r = keyslot;
index 9e5e517..14f6aed 100644 (file)
@@ -58,6 +58,8 @@ static int _verbose = 1;
 static char global_log[4096];
 static int global_lines = 0;
 
+static int gcrypt_compatible = 0;
+
 // Helpers
 static int _prepare_keyfile(const char *name, const char *passphrase)
 {
@@ -585,13 +587,19 @@ static void UseLuksDevice(void)
 
 static void SuspendDevice(void)
 {
+       int suspend_status;
        struct crypt_device *cd;
 
        OK_(crypt_init(&cd, DEVICE_1));
        OK_(crypt_load(cd, CRYPT_LUKS1, NULL));
        OK_(crypt_activate_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEY1, strlen(KEY1), 0));
 
-       OK_(crypt_suspend(cd, CDEVICE_1));
+       suspend_status = crypt_suspend(cd, CDEVICE_1);
+       if (suspend_status == -ENOTSUP) {
+               printf("WARNING: Suspend/Resume not supported, skipping test.\n");
+               goto out;
+       }
+       OK_(suspend_status);
        FAIL_(crypt_suspend(cd, CDEVICE_1), "already suspended");
 
        FAIL_(crypt_resume_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEY1, strlen(KEY1)-1), "wrong key");
@@ -604,7 +612,7 @@ static void SuspendDevice(void)
        OK_(crypt_resume_by_keyfile(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEYFILE1, 0));
        FAIL_(crypt_resume_by_keyfile(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEYFILE1, 0), "not suspended");
        _remove_keyfiles();
-
+out:
        OK_(crypt_deactivate(cd, CDEVICE_1));
        crypt_free(cd);
 }
@@ -688,11 +696,34 @@ static void NonFIPSAlg(void)
        char *cipher = "aes";
        char *cipher_mode = "cbc-essiv:sha256";
 
+       if (!gcrypt_compatible) {
+               printf("WARNING: old libgcrypt, skipping test.\n");
+               return;
+       }
        OK_(crypt_init(&cd, DEVICE_2));
        OK_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key, key_size, &params));
        crypt_free(cd);
 }
 
+
+static void _gcrypt_compatible()
+{
+       int maj, min, patch;
+       FILE *f;
+
+       if (!(f = popen("libgcrypt-config --version", "r")))
+               return;
+
+       if (fscanf(f, "%d.%d.%d", &maj, &min, &patch) == 2 &&
+           maj >= 1 && min >= 4)
+               gcrypt_compatible = 1;
+       if (_debug)
+               printf("libgcrypt version %d.%d.%d detected.\n", maj, min, patch);
+
+       (void)fclose(f);
+       return;
+}
+
 int main (int argc, char *argv[])
 {
        int i;
@@ -711,6 +742,7 @@ int main (int argc, char *argv[])
 
        _cleanup();
        _setup();
+       _gcrypt_compatible();
 
        crypt_set_debug_level(_debug ? CRYPT_DEBUG_ALL : CRYPT_DEBUG_NONE);
 
@@ -729,7 +761,6 @@ int main (int argc, char *argv[])
        RUN_(UseLuksDevice, "Use pre-formated LUKS device");
        RUN_(SuspendDevice, "Suspend/Resume test");
 
-
        _cleanup();
        return 0;
 }