diff --git a/configure.ac b/configure.ac index a1d9c4b6..d7e54e81 100644 --- a/configure.ac +++ b/configure.ac @@ -319,6 +319,8 @@ LIBS="$LIBS $DEVMAPPER_LIBS" AC_CHECK_DECLS([dm_task_secure_data], [], [], [#include ]) AC_CHECK_DECLS([dm_task_retry_remove], [], [], [#include ]) AC_CHECK_DECLS([dm_task_deferred_remove], [], [], [#include ]) +AC_CHECK_DECLS([dm_device_has_mounted_fs], [], [], [#include ]) +AC_CHECK_DECLS([dm_device_has_holders], [], [], [#include ]) AC_CHECK_DECLS([DM_UDEV_DISABLE_DISK_RULES_FLAG], [have_cookie=yes], [have_cookie=no], [#include ]) if test "x$enable_udev" = xyes; then if test "x$have_cookie" = xno; then diff --git a/lib/libdevmapper.c b/lib/libdevmapper.c index e85cd108..9399f656 100644 --- a/lib/libdevmapper.c +++ b/lib/libdevmapper.c @@ -1978,6 +1978,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 e38b879a..6e0e0d19 100644 --- a/lib/setup.c +++ b/lib/setup.c @@ -3217,6 +3217,7 @@ int crypt_deactivate_by_name(struct crypt_device *cd, const char *name, uint32_t const char *namei = NULL; struct crypt_dm_active_device dmd = {}; int r; + uint32_t get_flags = DM_ACTIVE_DEVICE | DM_ACTIVE_HOLDERS; if (!name) return -EINVAL; @@ -3230,17 +3231,26 @@ int crypt_deactivate_by_name(struct crypt_device *cd, const char *name, uint32_t cd = fake_cd; } + /* skip holders detection and early abort when some flags raised */ + if (flags & (CRYPT_DEACTIVATE_FORCE | CRYPT_DEACTIVATE_DEFERRED)) + get_flags &= ~DM_ACTIVE_HOLDERS; + switch (crypt_status(cd, name)) { case CRYPT_ACTIVE: case CRYPT_BUSY: - key_desc = crypt_get_device_key_description(name); - - if (crypt_get_integrity_tag_size(cd)) { - r = dm_query_device(cd, name, DM_ACTIVE_DEVICE, &dmd); - if (r >= 0) + r = dm_query_device(cd, name, get_flags, &dmd); + if (r >= 0) { + if (dmd.holders) { + log_err(cd, _("Device %s is still in use.\n"), name); + r = -EBUSY; + break; + } + if (crypt_get_integrity_tag_size(cd)) namei = device_dm_name(dmd.data_device); } + key_desc = crypt_get_device_key_description(name); + if (isTCRYPT(cd->type)) r = TCRYPT_deactivate(cd, name, flags); else diff --git a/lib/utils_dm.h b/lib/utils_dm.h index d1329f0b..ee4fd45e 100644 --- a/lib/utils_dm.h +++ b/lib/utils_dm.h @@ -56,14 +56,16 @@ int dm_flags(dm_target_type target, uint32_t *flags); #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 { dm_target_type target; @@ -71,6 +73,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;