Files
sablink-distro/sys-fs/cryptsetup/files/cryptsetup-1.0.6-udevsettle.patch
T

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);