Commit 961e6542 authored by Ondrej Kozina's avatar Ondrej Kozina

crypt_deactivate: fail earlier when holders detected

crypt_deactivate_* fail 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

Any deactivation flag CRYPT_DEACTIVATE_FORCE or
CRYPT_DEACTIVATE_DEFERRED will disable this detection
parent f901cb7b
......@@ -319,6 +319,8 @@ LIBS="$LIBS $DEVMAPPER_LIBS"
AC_CHECK_DECLS([dm_task_secure_data], [], [], [#include <libdevmapper.h>])
AC_CHECK_DECLS([dm_task_retry_remove], [], [], [#include <libdevmapper.h>])
AC_CHECK_DECLS([dm_task_deferred_remove], [], [], [#include <libdevmapper.h>])
AC_CHECK_DECLS([dm_device_has_mounted_fs], [], [], [#include <libdevmapper.h>])
AC_CHECK_DECLS([dm_device_has_holders], [], [], [#include <libdevmapper.h>])
AC_CHECK_DECLS([DM_UDEV_DISABLE_DISK_RULES_FLAG], [have_cookie=yes], [have_cookie=no], [#include <libdevmapper.h>])
if test "x$enable_udev" = xyes; then
if test "x$have_cookie" = xno; then
......
......@@ -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)
......
......@@ -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
......
......@@ -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;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment