From 2e4aaa1adad2d0838593b13efbf5efe79f58255c Mon Sep 17 00:00:00 2001 From: Ondrej Kozina Date: Mon, 16 Oct 2017 16:41:43 +0200 Subject: [PATCH] crypt_deactivate: fail earlier when holders detected crypt_deactivate fails earlier without noisy dm retries when other device holders detected. The early detection works if: a) other device-mapper device has a hold reference on the device - or - b) mounted fs is detected on the device diff -rupN cryptsetup-1.7.4.old/config.h.in cryptsetup-1.7.4/config.h.in --- cryptsetup-1.7.4.old/config.h.in 2017-03-15 10:43:26.000000000 +0100 +++ cryptsetup-1.7.4/config.h.in 2017-10-19 09:37:17.000000000 +0200 @@ -97,6 +97,14 @@ */ #undef HAVE_DCGETTEXT +/* Define to 1 if you have the declaration of `dm_device_has_holders', and to + 0 if you don't. */ +#undef HAVE_DECL_DM_DEVICE_HAS_HOLDERS + +/* Define to 1 if you have the declaration of `dm_device_has_mounted_fs', and + to 0 if you don't. */ +#undef HAVE_DECL_DM_DEVICE_HAS_MOUNTED_FS + /* Define to 1 if you have the declaration of `dm_task_retry_remove', and to 0 if you don't. */ #undef HAVE_DECL_DM_TASK_RETRY_REMOVE diff -rupN cryptsetup-1.7.4.old/configure cryptsetup-1.7.4/configure --- cryptsetup-1.7.4.old/configure 2017-03-15 10:43:13.000000000 +0100 +++ cryptsetup-1.7.4/configure 2017-10-19 09:37:18.590530138 +0200 @@ -16735,6 +16735,30 @@ cat >>confdefs.h <<_ACEOF #define HAVE_DECL_DM_TASK_RETRY_REMOVE $ac_have_decl _ACEOF +ac_fn_c_check_decl "$LINENO" "dm_device_has_mounted_fs" "ac_cv_have_decl_dm_device_has_mounted_fs" "#include +" +if test "x$ac_cv_have_decl_dm_device_has_mounted_fs" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_DM_DEVICE_HAS_MOUNTED_FS $ac_have_decl +_ACEOF + +ac_fn_c_check_decl "$LINENO" "dm_device_has_holders" "ac_cv_have_decl_dm_device_has_holders" "#include +" +if test "x$ac_cv_have_decl_dm_device_has_holders" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_DM_DEVICE_HAS_HOLDERS $ac_have_decl +_ACEOF + ac_fn_c_check_decl "$LINENO" "DM_UDEV_DISABLE_DISK_RULES_FLAG" "ac_cv_have_decl_DM_UDEV_DISABLE_DISK_RULES_FLAG" "#include " if test "x$ac_cv_have_decl_DM_UDEV_DISABLE_DISK_RULES_FLAG" = xyes; then : diff --git a/lib/libdevmapper.c b/lib/libdevmapper.c index a0d6872..d6017b1 100644 --- a/lib/libdevmapper.c +++ b/lib/libdevmapper.c @@ -1181,6 +1181,13 @@ int dm_query_device(struct crypt_device *cd, const char *name, dmd->uuid = strdup(tmp_uuid + DM_UUID_PREFIX_LEN); } + dmd->holders = 0; +#if (HAVE_DECL_DM_DEVICE_HAS_HOLDERS && HAVE_DECL_DM_DEVICE_HAS_MOUNTED_FS) + if (get_flags & DM_ACTIVE_HOLDERS) + dmd->holders = (dm_device_has_mounted_fs(dmi.major, dmi.minor) || + dm_device_has_holders(dmi.major, dmi.minor)); +#endif + r = (dmi.open_count > 0); out: if (dmt) diff --git a/lib/setup.c b/lib/setup.c index b2e4396..93e8079 100644 --- a/lib/setup.c +++ b/lib/setup.c @@ -2249,6 +2249,7 @@ int crypt_activate_by_volume_key(struct crypt_device *cd, int crypt_deactivate(struct crypt_device *cd, const char *name) { struct crypt_device *fake_cd = NULL; + struct crypt_dm_active_device dmd = {}; int r; if (!name) @@ -2266,6 +2267,13 @@ int crypt_deactivate(struct crypt_device *cd, const char *name) switch (crypt_status(cd, name)) { case CRYPT_ACTIVE: case CRYPT_BUSY: + r = dm_query_device(cd, name, DM_ACTIVE_HOLDERS, &dmd); + if (r >= 0 && dmd.holders) { + log_err(cd, _("Device %s is still in use.\n"), name); + r = -EBUSY; + break; + } + if (isTCRYPT(cd->type)) r = TCRYPT_deactivate(cd, name); else diff --git a/lib/utils_dm.h b/lib/utils_dm.h index c87e9aa..cf22e12 100644 --- a/lib/utils_dm.h +++ b/lib/utils_dm.h @@ -48,14 +48,16 @@ uint32_t dm_flags(void); #define DM_ACTIVE_DEVICE (1 << 0) #define DM_ACTIVE_UUID (1 << 1) +#define DM_ACTIVE_HOLDERS (1 << 2) -#define DM_ACTIVE_CRYPT_CIPHER (1 << 2) -#define DM_ACTIVE_CRYPT_KEYSIZE (1 << 3) -#define DM_ACTIVE_CRYPT_KEY (1 << 4) +#define DM_ACTIVE_CRYPT_CIPHER (1 << 3) +#define DM_ACTIVE_CRYPT_KEYSIZE (1 << 4) +#define DM_ACTIVE_CRYPT_KEY (1 << 5) + +#define DM_ACTIVE_VERITY_ROOT_HASH (1 << 6) +#define DM_ACTIVE_VERITY_HASH_DEVICE (1 << 7) +#define DM_ACTIVE_VERITY_PARAMS (1 << 8) -#define DM_ACTIVE_VERITY_ROOT_HASH (1 << 5) -#define DM_ACTIVE_VERITY_HASH_DEVICE (1 << 6) -#define DM_ACTIVE_VERITY_PARAMS (1 << 7) struct crypt_dm_active_device { enum { DM_CRYPT = 0, DM_VERITY } target; @@ -63,6 +65,7 @@ struct crypt_dm_active_device { uint32_t flags; /* activation flags */ const char *uuid; struct device *data_device; + unsigned holders:1; union { struct { const char *cipher; -- 1.8.3.1