329 lines
8.0 KiB
Diff
329 lines
8.0 KiB
Diff
Index: lib/setup.c
|
|
===================================================================
|
|
--- lib/setup.c (revision 29)
|
|
+++ lib/setup.c (revision 32)
|
|
@@ -396,7 +396,7 @@ static int __crypt_remove_device(int arg
|
|
return -EBUSY;
|
|
}
|
|
|
|
- return backend->remove(options);
|
|
+ return backend->remove(0, options);
|
|
}
|
|
|
|
static int __crypt_luks_format(int arg, struct setup_backend *backend, struct crypt_options *options)
|
|
@@ -705,7 +705,10 @@ static int crypt_job(int (*job)(int arg,
|
|
|
|
backend = get_setup_backend(default_backend);
|
|
|
|
- setup_enter(backend,options->icb->log);
|
|
+ if (setup_enter(backend,options->icb->log) < 0) {
|
|
+ r = -ENOSYS;
|
|
+ goto out;
|
|
+ }
|
|
|
|
if (!backend) {
|
|
set_error("No setup backend available");
|
|
Index: lib/internal.h
|
|
===================================================================
|
|
--- lib/internal.h (revision 29)
|
|
+++ lib/internal.h (revision 32)
|
|
@@ -40,7 +40,7 @@ struct setup_backend {
|
|
const char *key);
|
|
int (*status)(int details, struct crypt_options *options,
|
|
char **key);
|
|
- int (*remove)(struct crypt_options *options);
|
|
+ int (*remove)(int force, struct crypt_options *options);
|
|
|
|
const char * (*dir)(void);
|
|
};
|
|
Index: lib/libdevmapper.c
|
|
===================================================================
|
|
--- lib/libdevmapper.c (revision 29)
|
|
+++ lib/libdevmapper.c (revision 32)
|
|
@@ -17,13 +17,7 @@
|
|
#define DEVICE_DIR "/dev"
|
|
|
|
#define CRYPT_TARGET "crypt"
|
|
-
|
|
-#define UDEVSETTLE "/sbin/udevsettle"
|
|
-
|
|
-static void run_udevsettle(void)
|
|
-{
|
|
- system(UDEVSETTLE);
|
|
-}
|
|
+#define RETRY_COUNT 5
|
|
|
|
static void set_dm_error(int level, const char *file, int line,
|
|
const char *f, ...)
|
|
@@ -38,9 +32,16 @@ static void set_dm_error(int level, cons
|
|
va_end(va);
|
|
}
|
|
|
|
+static int _dm_simple(int task, const char *name);
|
|
+
|
|
static int dm_init(void)
|
|
{
|
|
dm_log_init(set_dm_error);
|
|
+ if (!_dm_simple(DM_DEVICE_LIST_VERSIONS, "test")) {
|
|
+ set_error("Cannot communicate with device-mapper. Is the dm_mod module loaded?");
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
return 1; /* unsafe memory */
|
|
}
|
|
|
|
@@ -50,16 +51,6 @@ static void dm_exit(void)
|
|
dm_lib_release();
|
|
}
|
|
|
|
-static void flush_dm_workqueue(void)
|
|
-{
|
|
- /*
|
|
- * Unfortunately this is the only way to trigger libdevmapper's
|
|
- * update_nodes function
|
|
- */
|
|
- dm_exit();
|
|
- dm_init();
|
|
-}
|
|
-
|
|
static char *__lookup_dev(char *path, dev_t dev)
|
|
{
|
|
struct dirent *entry;
|
|
@@ -152,6 +143,89 @@ out:
|
|
return params;
|
|
}
|
|
|
|
+/* DM helpers */
|
|
+static int _dm_simple(int task, const char *name)
|
|
+{
|
|
+ int r = 0;
|
|
+ struct dm_task *dmt;
|
|
+
|
|
+ if (!(dmt = dm_task_create(task)))
|
|
+ return 0;
|
|
+
|
|
+ if (!dm_task_set_name(dmt, name))
|
|
+ goto out;
|
|
+
|
|
+ r = dm_task_run(dmt);
|
|
+
|
|
+ out:
|
|
+ dm_task_destroy(dmt);
|
|
+ return r;
|
|
+}
|
|
+
|
|
+static int _error_device(struct crypt_options *options)
|
|
+{
|
|
+ struct dm_task *dmt;
|
|
+ int r = 0;
|
|
+
|
|
+ if (!(dmt = dm_task_create(DM_DEVICE_RELOAD)))
|
|
+ return 0;
|
|
+
|
|
+ if (!dm_task_set_name(dmt, options->name))
|
|
+ goto error;
|
|
+
|
|
+ if (!dm_task_add_target(dmt, UINT64_C(0), options->size, "error", ""))
|
|
+ goto error;
|
|
+
|
|
+ if (!dm_task_set_ro(dmt))
|
|
+ goto error;
|
|
+
|
|
+ if (!dm_task_no_open_count(dmt))
|
|
+ goto error;
|
|
+
|
|
+ if (!dm_task_run(dmt))
|
|
+ goto error;
|
|
+
|
|
+ if (!_dm_simple(DM_DEVICE_RESUME, options->name)) {
|
|
+ _dm_simple(DM_DEVICE_CLEAR, options->name);
|
|
+ goto error;
|
|
+ }
|
|
+
|
|
+ r = 1;
|
|
+
|
|
+error:
|
|
+ dm_task_destroy(dmt);
|
|
+ return r;
|
|
+}
|
|
+
|
|
+static int _dm_remove(struct crypt_options *options, int force)
|
|
+{
|
|
+ int r = -EINVAL;
|
|
+ int retries = force ? RETRY_COUNT : 1;
|
|
+
|
|
+ /* If force flag is set, replace device with error, read-only target.
|
|
+ * it should stop processes from reading it and also removed underlying
|
|
+ * device from mapping, so it is usable again.
|
|
+ * Force flag should be used only for temporary devices, which are
|
|
+ * intended to work inside cryptsetup only!
|
|
+ * Anyway, if some process try to read temporary cryptsetup device,
|
|
+ * it is bug - no other process should try touch it (e.g. udev).
|
|
+ */
|
|
+ if (force) {
|
|
+ _error_device(options);
|
|
+ retries = RETRY_COUNT;
|
|
+ }
|
|
+
|
|
+ do {
|
|
+ r = _dm_simple(DM_DEVICE_REMOVE, options->name) ? 0 : -EINVAL;
|
|
+ if (--retries)
|
|
+ sleep(1);
|
|
+ } while (r == -EINVAL && retries);
|
|
+
|
|
+ dm_task_update_nodes();
|
|
+
|
|
+ return r;
|
|
+}
|
|
+
|
|
static int dm_create_device(int reload, struct crypt_options *options,
|
|
const char *key)
|
|
{
|
|
@@ -191,24 +265,14 @@ static int dm_create_device(int reload,
|
|
if (dmi.read_only)
|
|
options->flags |= CRYPT_FLAG_READONLY;
|
|
|
|
- /* run udevsettle to avoid a race in libdevmapper causing busy dm devices */
|
|
- run_udevsettle();
|
|
-
|
|
r = 0;
|
|
-
|
|
out:
|
|
if (r < 0 && !reload) {
|
|
char *error = (char *)get_error();
|
|
if (error)
|
|
error = strdup(error);
|
|
- if (dmt)
|
|
- dm_task_destroy(dmt);
|
|
|
|
- if (!(dmt = dm_task_create(DM_DEVICE_REMOVE)))
|
|
- goto out_restore_error;
|
|
- if (!dm_task_set_name(dmt, options->name))
|
|
- goto out_restore_error;
|
|
- if (!dm_task_run(dmt))
|
|
+ if (!_dm_remove(options, 0))
|
|
goto out_restore_error;
|
|
|
|
out_restore_error:
|
|
@@ -224,7 +288,7 @@ out_no_removal:
|
|
dm_task_destroy(dmt);
|
|
if(dmt_query)
|
|
dm_task_destroy(dmt_query);
|
|
- flush_dm_workqueue();
|
|
+ dm_task_update_nodes();
|
|
return r;
|
|
}
|
|
|
|
@@ -352,25 +416,12 @@ out:
|
|
return r;
|
|
}
|
|
|
|
-static int dm_remove_device(struct crypt_options *options)
|
|
+static int dm_remove_device(int force, struct crypt_options *options)
|
|
{
|
|
- struct dm_task *dmt;
|
|
- int r = -EINVAL;
|
|
-
|
|
- if (!(dmt = dm_task_create(DM_DEVICE_REMOVE)))
|
|
- goto out;
|
|
- if (!dm_task_set_name(dmt, options->name))
|
|
- goto out;
|
|
- if (!dm_task_run(dmt))
|
|
- goto out;
|
|
-
|
|
- r = 0;
|
|
+ if (!options || !options->name)
|
|
+ return -EINVAL;
|
|
|
|
-out:
|
|
- if (dmt)
|
|
- dm_task_destroy(dmt);
|
|
- flush_dm_workqueue();
|
|
- return r;
|
|
+ return _dm_remove(options, force);;
|
|
}
|
|
|
|
|
|
Index: luks/keyencryption.c
|
|
===================================================================
|
|
--- luks/keyencryption.c (revision 29)
|
|
+++ luks/keyencryption.c (revision 32)
|
|
@@ -45,6 +45,11 @@ static inline int round_up_modulo(int x,
|
|
return div_round_up(x, m) * m;
|
|
}
|
|
|
|
+static struct setup_backend *cleaner_backend=NULL;
|
|
+static const char *cleaner_name=NULL;
|
|
+static uint64_t cleaner_size = 0;
|
|
+static int devfd=-1;
|
|
+
|
|
static int setup_mapping(const char *cipher, const char *name,
|
|
const char *device, unsigned int payloadOffset,
|
|
const char *key, size_t keyLength,
|
|
@@ -52,7 +57,7 @@ static int setup_mapping(const char *cip
|
|
struct setup_backend *backend,
|
|
int mode)
|
|
{
|
|
- struct crypt_options k;
|
|
+ struct crypt_options k = {0};
|
|
struct crypt_options *options = &k;
|
|
int device_sector_size = sector_size_for_device(device);
|
|
int r;
|
|
@@ -66,6 +71,7 @@ static int setup_mapping(const char *cip
|
|
return -EINVAL;
|
|
}
|
|
options->size = round_up_modulo(srcLength,device_sector_size)/SECTOR_SIZE;
|
|
+ cleaner_size = options->size;
|
|
|
|
options->offset = sector;
|
|
options->cipher = cipher;
|
|
@@ -87,24 +93,21 @@ static int setup_mapping(const char *cip
|
|
return r;
|
|
}
|
|
|
|
-static int clear_mapping(const char *name, struct setup_backend *backend)
|
|
+static int clear_mapping(const char *name, uint64_t size, struct setup_backend *backend)
|
|
{
|
|
- struct crypt_options options;
|
|
+ struct crypt_options options = {0};
|
|
options.name=name;
|
|
- return backend->remove(&options);
|
|
+ options.size = size;
|
|
+ return backend->remove(1, &options);
|
|
}
|
|
|
|
-/* I miss closures in C! */
|
|
-static struct setup_backend *cleaner_backend=NULL;
|
|
-static const char *cleaner_name=NULL;
|
|
-static int devfd=0;
|
|
-
|
|
static void sigint_handler(int sig)
|
|
{
|
|
- if(devfd)
|
|
+ if(devfd >= 0)
|
|
close(devfd);
|
|
+ devfd = -1;
|
|
if(cleaner_backend && cleaner_name)
|
|
- clear_mapping(cleaner_name, cleaner_backend);
|
|
+ clear_mapping(cleaner_name, cleaner_size, cleaner_backend);
|
|
signal(SIGINT, SIG_DFL);
|
|
kill(getpid(), SIGINT);
|
|
}
|
|
@@ -160,13 +163,14 @@ static int LUKS_endec_template(char *src
|
|
r = 0;
|
|
out3:
|
|
close(devfd);
|
|
- devfd = 0;
|
|
+ devfd = -1;
|
|
out2:
|
|
- clear_mapping(name,backend);
|
|
+ clear_mapping(cleaner_name, cleaner_size, cleaner_backend);
|
|
out1:
|
|
signal(SIGINT, SIG_DFL);
|
|
cleaner_name = NULL;
|
|
cleaner_backend = NULL;
|
|
+ cleaner_size = 0;
|
|
free(dmCipherSpec);
|
|
free(fullpath);
|
|
free(name);
|