summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog5
-rw-r--r--lib/internal.h9
-rw-r--r--lib/libcryptsetup.h2
-rw-r--r--lib/libdevmapper.c28
-rw-r--r--lib/loopaes/loopaes.c2
-rw-r--r--lib/setup.c43
-rw-r--r--lib/utils.c25
-rw-r--r--lib/utils_devpath.c77
-rw-r--r--lib/utils_dm.h3
-rw-r--r--man/cryptsetup.88
-rw-r--r--src/cryptsetup.c29
-rwxr-xr-xtests/compat-test14
12 files changed, 199 insertions, 46 deletions
diff --git a/ChangeLog b/ChangeLog
index 124dbec..1e68e52 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2011-07-01 Milan Broz <mbroz@redhat.com>
+ * Add --shared option for creating non-overlapping crypt segments.
+ * Add shared flag to libcryptsetup api.
+ * Fix plain crypt format parameters to include size option (API change).
+
2011-06-08 Milan Broz <mbroz@redhat.com>
* Fix return code for status command when device doesn't exists.
diff --git a/lib/internal.h b/lib/internal.h
index 07e7db2..1803462 100644
--- a/lib/internal.h
+++ b/lib/internal.h
@@ -47,6 +47,7 @@ void set_error(const char *fmt, ...);
const char *get_error(void);
char *crypt_lookup_dev(const char *dev_id);
+int crypt_sysfs_check_crypt_segment(const char *device, uint64_t offset, uint64_t size);
int sector_size_for_device(const char *device);
int device_read_ahead(const char *dev, uint32_t *read_ahead);
@@ -54,13 +55,11 @@ ssize_t write_blockwise(int fd, void *buf, size_t count);
ssize_t read_blockwise(int fd, void *_buf, size_t count);
ssize_t write_lseek_blockwise(int fd, char *buf, size_t count, off_t offset);
int device_ready(struct crypt_device *cd, const char *device, int mode);
-int get_device_infos(const char *device,
- int open_exclusive,
- int *readonly,
- uint64_t *size);
+
+enum devcheck { DEV_OK = 0, DEV_EXCL = 1, DEV_SHARED = 2 };
int device_check_and_adjust(struct crypt_device *cd,
const char *device,
- int open_exclusive,
+ enum devcheck device_check,
uint64_t *size,
uint64_t *offset,
int *read_only);
diff --git a/lib/libcryptsetup.h b/lib/libcryptsetup.h
index 08c45fe..5d6128a 100644
--- a/lib/libcryptsetup.h
+++ b/lib/libcryptsetup.h
@@ -161,6 +161,7 @@ struct crypt_params_plain {
const char *hash; /* password hash function */
uint64_t offset; /* offset in sectors */
uint64_t skip; /* IV initilisation sector */
+ uint64_t size; /* size of mapped device or 0 for autodetection */
};
struct crypt_params_luks1 {
@@ -375,6 +376,7 @@ int crypt_keyslot_destroy(struct crypt_device *cd, int keyslot);
*/
#define CRYPT_ACTIVATE_READONLY (1 << 0)
#define CRYPT_ACTIVATE_NO_UUID (1 << 1)
+#define CRYPT_ACTIVATE_SHARED (1 << 2)
/**
* Active device runtime attributes
diff --git a/lib/libdevmapper.c b/lib/libdevmapper.c
index 34b1767..aa61c25 100644
--- a/lib/libdevmapper.c
+++ b/lib/libdevmapper.c
@@ -206,7 +206,7 @@ void dm_exit(void)
}
/* Return path to DM device */
-char *dm_device_path(int major, int minor)
+char *dm_device_path(const char *prefix, int major, int minor)
{
struct dm_task *dmt;
const char *name;
@@ -222,7 +222,7 @@ char *dm_device_path(int major, int minor)
return NULL;
}
- if (snprintf(path, sizeof(path), "/dev/mapper/%s", name) < 0)
+ if (snprintf(path, sizeof(path), "%s%s", prefix ?: "", name) < 0)
path[0] = '\0';
dm_task_destroy(dmt);
@@ -764,3 +764,27 @@ int dm_is_dm_kernel_name(const char *name)
{
return strncmp(name, "dm-", 3) ? 0 : 1;
}
+
+int dm_check_segment(const char *name, uint64_t offset, uint64_t size)
+{
+ uint64_t seg_size, seg_offset;
+ int r;
+
+ log_dbg("Checking segments for device %s.", name);
+
+ r = dm_query_device(name, NULL, &seg_size, NULL, &seg_offset,
+ NULL, NULL, NULL, NULL, NULL, NULL);
+ if (r < 0)
+ return r;
+
+ if (offset >= (seg_offset + seg_size) || (offset + size) <= seg_offset)
+ r = 0;
+ else
+ r = -EBUSY;
+
+ log_dbg("seg: %" PRIu64 " - %" PRIu64 ", new %" PRIu64 " - %" PRIu64 "%s",
+ seg_offset, seg_offset + seg_size, offset, offset + size,
+ r ? " (overlapping)" : " (ok)");
+
+ return r;
+}
diff --git a/lib/loopaes/loopaes.c b/lib/loopaes/loopaes.c
index 7fdd56c..e6fe827 100644
--- a/lib/loopaes/loopaes.c
+++ b/lib/loopaes/loopaes.c
@@ -200,7 +200,7 @@ int LOOPAES_activate(struct crypt_device *cd,
device = crypt_get_device_name(cd);
read_only = flags & CRYPT_ACTIVATE_READONLY;
- r = device_check_and_adjust(cd, device, 1, &size, &offset, &read_only);
+ r = device_check_and_adjust(cd, device, DEV_EXCL, &size, &offset, &read_only);
if (r)
return r;
diff --git a/lib/setup.c b/lib/setup.c
index 4da7b81..550928d 100644
--- a/lib/setup.c
+++ b/lib/setup.c
@@ -357,17 +357,26 @@ static int create_device_helper(struct crypt_device *cd,
uint64_t skip,
uint64_t offset,
const char *uuid,
- int read_only,
+ uint32_t activation_flags,
int reload)
{
crypt_status_info ci;
char *dm_cipher = NULL;
char *processed_key = NULL;
- int r;
+ enum devcheck device_check;
+ int r, read_only;
if (!name)
return -EINVAL;
+ read_only = activation_flags & CRYPT_ACTIVATE_READONLY ? 1 : 0;
+ if (reload)
+ device_check = DEV_OK;
+ else if (activation_flags & CRYPT_ACTIVATE_SHARED)
+ device_check = DEV_SHARED;
+ else
+ device_check = DEV_EXCL;
+
ci = crypt_status(cd, name);
if (ci == CRYPT_INVALID)
return -EINVAL;
@@ -385,7 +394,7 @@ static int create_device_helper(struct crypt_device *cd,
return -EINVAL;
}
- r = device_check_and_adjust(cd, cd->device, !reload, &size, &offset, &read_only);
+ r = device_check_and_adjust(cd, cd->device, device_check, &size, &offset, &read_only);
if (r)
return r;
@@ -424,7 +433,7 @@ static int open_from_hdr_and_vk(struct crypt_device *cd,
read_only = flags & CRYPT_ACTIVATE_READONLY;
no_uuid = flags & CRYPT_ACTIVATE_NO_UUID;
- r = device_check_and_adjust(cd, cd->device, 1, &size, &offset, &read_only);
+ r = device_check_and_adjust(cd, cd->device, DEV_EXCL, &size, &offset, &read_only);
if (r)
return r;
@@ -625,8 +634,12 @@ static int crypt_create_and_update_device(struct crypt_options *options, int upd
struct crypt_device *cd = NULL;
char *passphrase = NULL;
size_t passphrase_size = 0;
+ uint32_t activation_flags;
int r;
+ activation_flags = options->flags & CRYPT_FLAG_READONLY ?
+ CRYPT_ACTIVATE_READONLY : 0;
+
r = _crypt_init(&cd, CRYPT_PLAIN, options, 0, 1);
if (r)
return r;
@@ -639,8 +652,7 @@ static int crypt_create_and_update_device(struct crypt_options *options, int upd
options->cipher, NULL, options->key_file,
passphrase, passphrase_size,
options->key_size, options->size, options->skip,
- options->offset, NULL, options->flags & CRYPT_FLAG_READONLY,
- update);
+ options->offset, NULL, activation_flags, update);
crypt_safe_free(passphrase);
crypt_free(cd);
@@ -697,7 +709,7 @@ int crypt_resize_device(struct crypt_options *options)
goto out;
size = options->size;
- r = device_check_and_adjust(cd, device, 0, &size, &offset, &read_only);
+ r = device_check_and_adjust(cd, device, DEV_OK, &size, &offset, &read_only);
if (r)
goto out;
@@ -1226,6 +1238,7 @@ static int _crypt_format_plain(struct crypt_device *cd,
cd->plain_hdr.offset = params ? params->offset : 0;
cd->plain_hdr.skip = params ? params->skip : 0;
+ cd->plain_hdr.size = params ? params->size : 0;
if (!cd->plain_cipher || !cd->plain_cipher_mode)
return -ENOMEM;
@@ -1425,7 +1438,7 @@ int crypt_resize(struct crypt_device *cd, const char *name, uint64_t new_size)
goto out;
}
- r = device_check_and_adjust(cd, device, 0, &new_size, &offset, &read_only);
+ r = device_check_and_adjust(cd, device, DEV_OK, &new_size, &offset, &read_only);
if (r)
goto out;
@@ -1945,10 +1958,9 @@ int crypt_activate_by_passphrase(struct crypt_device *cd,
r = create_device_helper(cd, name, cd->plain_hdr.hash,
cd->plain_cipher, cd->plain_cipher_mode,
NULL, passphrase, passphrase_size,
- cd->volume_key->keylength, 0,
+ cd->volume_key->keylength, cd->plain_hdr.size,
cd->plain_hdr.skip, cd->plain_hdr.offset,
- cd->plain_uuid,
- flags & CRYPT_ACTIVATE_READONLY, 0);
+ cd->plain_uuid, flags, 0);
keyslot = 0;
} else if (isLUKS(cd->type)) {
/* provided passphrase, do not retry */
@@ -2011,10 +2023,9 @@ int crypt_activate_by_keyfile(struct crypt_device *cd,
r = create_device_helper(cd, name, cd->plain_hdr.hash,
cd->plain_cipher, cd->plain_cipher_mode,
NULL, passphrase_read, passphrase_size_read,
- cd->volume_key->keylength, 0,
+ cd->volume_key->keylength, cd->plain_hdr.size,
cd->plain_hdr.skip, cd->plain_hdr.offset,
- cd->plain_uuid,
- flags & CRYPT_ACTIVATE_READONLY, 0);
+ cd->plain_uuid, flags, 0);
} else if (isLUKS(cd->type)) {
r = key_from_file(cd, _("Enter passphrase: "), &passphrase_read,
&passphrase_size_read, keyfile, keyfile_size);
@@ -2079,8 +2090,8 @@ int crypt_activate_by_volume_key(struct crypt_device *cd,
return create_device_helper(cd, name, NULL,
cd->plain_cipher, cd->plain_cipher_mode, NULL, volume_key, volume_key_size,
- cd->volume_key->keylength, 0, cd->plain_hdr.skip,
- cd->plain_hdr.offset, cd->plain_uuid, flags & CRYPT_ACTIVATE_READONLY, 0);
+ cd->volume_key->keylength, cd->plain_hdr.size, cd->plain_hdr.skip,
+ cd->plain_hdr.offset, cd->plain_uuid, flags, 0);
}
if (!isLUKS(cd->type)) {
diff --git a/lib/utils.c b/lib/utils.c
index 9c555d1..19fff5d 100644
--- a/lib/utils.c
+++ b/lib/utils.c
@@ -336,10 +336,8 @@ int device_ready(struct crypt_device *cd, const char *device, int mode)
return r;
}
-int get_device_infos(const char *device,
- int open_exclusive,
- int *readonly,
- uint64_t *size)
+static int get_device_infos(const char *device, enum devcheck device_check,
+ int *readonly, uint64_t *size)
{
struct stat st;
unsigned long size_small;
@@ -353,7 +351,7 @@ int get_device_infos(const char *device,
return -EINVAL;
/* never wipe header on mounted device */
- if (open_exclusive && S_ISBLK(st.st_mode))
+ if (device_check == DEV_EXCL && S_ISBLK(st.st_mode))
flags |= O_EXCL;
/* Try to open read-write to check whether it is a read-only device */
@@ -363,7 +361,7 @@ int get_device_infos(const char *device,
fd = open(device, O_RDONLY | flags);
}
- if (fd == -1 && open_exclusive && errno == EBUSY)
+ if (fd == -1 && device_check == DEV_EXCL && errno == EBUSY)
return -EBUSY;
if (fd == -1)
@@ -396,7 +394,7 @@ out:
int device_check_and_adjust(struct crypt_device *cd,
const char *device,
- int open_exclusive,
+ enum devcheck device_check,
uint64_t *size,
uint64_t *offset,
int *read_only)
@@ -407,7 +405,7 @@ int device_check_and_adjust(struct crypt_device *cd,
if (!device)
return -ENOTBLK;
- r = get_device_infos(device, open_exclusive, &real_readonly, &real_size);
+ r = get_device_infos(device, device_check, &real_readonly, &real_size);
if (r < 0) {
if (r == -EBUSY)
log_err(cd, _("Cannot use device %s which is in use "
@@ -432,6 +430,17 @@ int device_check_and_adjust(struct crypt_device *cd,
*size -= *offset;
}
+ if (device_check == DEV_SHARED) {
+ log_dbg("Checking crypt segments for device %s.", device);
+ r = crypt_sysfs_check_crypt_segment(device, *offset, *size);
+ if (r < 0) {
+ log_err(cd, "Cannot use device %s (crypt segments "
+ "overlaps or in use by another device).\n",
+ device);
+ return r;
+ }
+ }
+
if (real_readonly)
*read_only = 1;
diff --git a/lib/utils_devpath.c b/lib/utils_devpath.c
index f78a36e..2844f35 100644
--- a/lib/utils_devpath.c
+++ b/lib/utils_devpath.c
@@ -24,11 +24,14 @@
#include <stdlib.h>
#include <unistd.h>
#include <dirent.h>
+#include <fcntl.h>
+#include <errno.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "utils_dm.h"
char *crypt_lookup_dev(const char *dev_id);
+int crypt_sysfs_check_crypt_segment(const char *device, uint64_t offset, uint64_t size);
static char *__lookup_dev(char *path, dev_t dev, int dir_level, const int max_level)
{
@@ -146,7 +149,7 @@ char *crypt_lookup_dev(const char *dev_id)
devname++;
if (dm_is_dm_kernel_name(devname))
- devpath = dm_device_path(major, minor);
+ devpath = dm_device_path("/dev/mapper/", major, minor);
else if (snprintf(path, sizeof(path), "/dev/%s", devname) > 0)
devpath = strdup(path);
@@ -163,3 +166,75 @@ char *crypt_lookup_dev(const char *dev_id)
return devpath;
}
+
+static int crypt_sysfs_get_major_minor(const char *kname, int *major, int *minor)
+{
+ char path[PATH_MAX], tmp[64];
+ int fd, r = 0;
+
+ if (snprintf(path, sizeof(path), "/sys/block/%s/dev", kname) < 0)
+ return 0;
+
+ if ((fd = open(path, O_RDONLY)) < 0)
+ return 0;
+ r = read(fd, tmp, sizeof(tmp));
+ close(fd);
+
+ if (r <= 0 || sscanf(tmp, "%d:%d", major, minor) != 2)
+ return 0;
+
+ return 1;
+}
+
+static int crypt_sysfs_get_holders_dir(const char *device, char *path, int size)
+{
+ struct stat st;
+
+ if (stat(device, &st) < 0 || !S_ISBLK(st.st_mode))
+ return 0;
+
+ if (snprintf(path, size, "/sys/dev/block/%d:%d/holders",
+ major(st.st_rdev), minor(st.st_rdev)) < 0)
+ return 0;
+
+ return 1;
+}
+
+int crypt_sysfs_check_crypt_segment(const char *device, uint64_t offset, uint64_t size)
+{
+ DIR *dir;
+ struct dirent *d;
+ char path[PATH_MAX], *dmname;
+ int major, minor, r = 0;
+
+ if (!crypt_sysfs_get_holders_dir(device, path, sizeof(path)))
+ return -EINVAL;
+
+ if (!(dir = opendir(path)))
+ return -EINVAL;
+
+ while (!r && (d = readdir(dir))) {
+ if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
+ continue;
+
+ if (!dm_is_dm_kernel_name(d->d_name)) {
+ r = -EBUSY;
+ break;
+ }
+
+ if (!crypt_sysfs_get_major_minor(d->d_name, &major, &minor)) {
+ r = -EINVAL;
+ break;
+ }
+
+ if (!(dmname = dm_device_path(NULL, major, minor))) {
+ r = -EINVAL;
+ break;
+ }
+ r = dm_check_segment(dmname, offset, size);
+ free(dmname);
+ }
+ closedir(dir);
+
+ return r;
+}
diff --git a/lib/utils_dm.h b/lib/utils_dm.h
index 585df44..59b29a8 100644
--- a/lib/utils_dm.h
+++ b/lib/utils_dm.h
@@ -38,8 +38,9 @@ int dm_suspend_and_wipe_key(const char *name);
int dm_resume_and_reinstate_key(const char *name,
size_t key_size,
const char *key);
-char *dm_device_path(int major, int minor);
+char *dm_device_path(const char *prefix, int major, int minor);
int dm_is_dm_device(int major, int minor);
int dm_is_dm_kernel_name(const char *name);
+int dm_check_segment(const char *name, uint64_t offset, uint64_t size);
#endif /* _UTILS_DM_H */
diff --git a/man/cryptsetup.8 b/man/cryptsetup.8
index 18ca603..fd8c329 100644
--- a/man/cryptsetup.8
+++ b/man/cryptsetup.8
@@ -14,7 +14,7 @@ For basic (plain) dm-crypt mappings, there are four operations.
creates a mapping with <name> backed by device <device>.
\fB<options>\fR can be [\-\-hash, \-\-cipher, \-\-verify-passphrase,
-\-\-key-file, \-\-key-size, \-\-offset, \-\-skip, \-\-size, \-\-readonly]
+\-\-key-file, \-\-key-size, \-\-offset, \-\-skip, \-\-size, \-\-readonly, \-\-shared]
.PP
\fIremove\fR <name>
.IP
@@ -319,6 +319,12 @@ This option is only relevant for \fIcreate\fR and \fIloopaesOpen\fR action.
.B "\-\-readonly"
set up a read-only mapping.
.TP
+.B "\-\-shared"
+create another non-overlapping mapping to one common ciphertext device,
+e.g. to create hidden device inside another encrypted device.
+This option is only relevant for \fIcreate\fR action.
+Use \-\-offset, \-\-size and \-\-skip to specify mapped area.
+.TP
.B "\-\-iter-time, \-i"
The number of milliseconds to spend with PBKDF2 password processing.
This option is only relevant to the LUKS operations as
diff --git a/src/cryptsetup.c b/src/cryptsetup.c
index 21182f0..f9e719d 100644
--- a/src/cryptsetup.c
+++ b/src/cryptsetup.c
@@ -61,6 +61,7 @@ static int opt_align_payload = 0;
static int opt_random = 0;
static int opt_urandom = 0;
static int opt_dump_master_key = 0;
+static int opt_shared = 0;
static const char **action_argv;
static int action_argc;
@@ -224,10 +225,12 @@ static int action_create(int arg __attribute__((unused)))
.hash = opt_hash ?: DEFAULT_PLAIN_HASH,
.skip = opt_skip,
.offset = opt_offset,
+ .size = opt_size,
};
char *password = NULL;
size_t passwordLen;
size_t key_size = (opt_key_size ?: DEFAULT_PLAIN_KEYBITS) / 8;
+ uint32_t activate_flags = 0;
int r;
if (params.hash && !strcmp(params.hash, "plain"))
@@ -262,11 +265,17 @@ static int action_create(int arg __attribute__((unused)))
if (r < 0)
goto out;
+ if (opt_readonly)
+ activate_flags |= CRYPT_ACTIVATE_READONLY;
+
+ if (opt_shared)
+ activate_flags |= CRYPT_ACTIVATE_SHARED;
+
if (opt_key_file)
/* With hashing, read the whole keyfile */
r = crypt_activate_by_keyfile(cd, action_argv[0],
CRYPT_ANY_SLOT, opt_key_file, params.hash ? 0 : key_size,
- opt_readonly ? CRYPT_ACTIVATE_READONLY : 0);
+ activate_flags);
else {
r = crypt_get_key(_("Enter passphrase: "),
&password, &passwordLen, opt_keyfile_size,
@@ -277,17 +286,8 @@ static int action_create(int arg __attribute__((unused)))
goto out;
r = crypt_activate_by_passphrase(cd, action_argv[0],
- CRYPT_ANY_SLOT, password, passwordLen,
- opt_readonly ? CRYPT_ACTIVATE_READONLY : 0);
+ CRYPT_ANY_SLOT, password, passwordLen, activate_flags);
}
-
- /* FIXME: workaround, new api missing format parameter for size.
- * Properly fix it after bumping library version,
- * add start_offset and size into "PLAIN" format specifiers.
- */
- if (r >= 0 && opt_size)
- r = crypt_resize(cd, action_argv[0], opt_size);
-
out:
crypt_free(cd);
crypt_safe_free(password);
@@ -1137,6 +1137,7 @@ int main(int argc, const char **argv)
{ "header-backup-file",'\0', POPT_ARG_STRING, &opt_header_backup_file, 0, N_("File with LUKS header and keyslots backup."), NULL },
{ "use-random", '\0', POPT_ARG_NONE, &opt_random, 0, N_("Use /dev/random for generating volume key."), NULL },
{ "use-urandom", '\0', POPT_ARG_NONE, &opt_urandom, 0, N_("Use /dev/urandom for generating volume key."), NULL },
+ { "shared", '\0', POPT_ARG_NONE, &opt_shared, 0, N_("Share device with another non-overlapping crypt segment."), NULL },
{ "uuid", '\0', POPT_ARG_STRING, &opt_uuid, 0, N_("UUID for device to use."), NULL },
POPT_TABLEEND
};
@@ -1218,6 +1219,12 @@ int main(int argc, const char **argv)
/* FIXME: rewrite this from scratch */
+ if (opt_shared && strcmp(aname, "create")) {
+ usage(popt_context, EXIT_FAILURE,
+ _("Option --shared is allowed only for create operation.\n"),
+ poptGetInvocationName(popt_context));
+ }
+
if (opt_key_size &&
strcmp(aname, "luksFormat") &&
strcmp(aname, "create") &&
diff --git a/tests/compat-test b/tests/compat-test
index fdd8e49..291c1bf 100755
--- a/tests/compat-test
+++ b/tests/compat-test
@@ -4,6 +4,7 @@ CRYPTSETUP=../src/cryptsetup
DEV_NAME=dummy
DEV_NAME2=dummy2
+DEV_NAME3=dummy3
ORIG_IMG=luks-test-orig
IMG=luks-test
KEY1=key1
@@ -24,6 +25,7 @@ LOOPDEV=$(losetup -f 2>/dev/null)
function remove_mapping()
{
+ [ -b /dev/mapper/$DEV_NAME3 ] && dmsetup remove $DEV_NAME3
[ -b /dev/mapper/$DEV_NAME2 ] && dmsetup remove $DEV_NAME2
[ -b /dev/mapper/$DEV_NAME ] && dmsetup remove $DEV_NAME
losetup -d $LOOPDEV >/dev/null 2>&1
@@ -355,5 +357,17 @@ echo "key0" | $CRYPTSETUP luksRemoveKey $LOOPDEV -l 2 2>/dev/null && fail
echo "key01" | $CRYPTSETUP luksRemoveKey $LOOPDEV -d 4 2>/dev/null && fail
echo -e "key0\n" | $CRYPTSETUP luksRemoveKey $LOOPDEV -d- -l 4 || fail
+prepare "[25] Create non-overlapping segments" wipe
+echo "key0" | $CRYPTSETUP create $DEV_NAME $LOOPDEV --offset 0 --size 256 || fail
+echo "key0" | $CRYPTSETUP create $DEV_NAME2 $LOOPDEV --offset 512 --size 256 2>/dev/null && fail
+echo "key0" | $CRYPTSETUP create $DEV_NAME2 $LOOPDEV --offset 512 --size 256 --shared || fail
+echo "key0" | $CRYPTSETUP create $DEV_NAME3 $LOOPDEV --offset 255 --size 256 --shared 2>/dev/null && fail
+echo "key0" | $CRYPTSETUP create $DEV_NAME3 $LOOPDEV --offset 256 --size 257 --shared 2>/dev/null && fail
+echo "key0" | $CRYPTSETUP create $DEV_NAME3 $LOOPDEV --offset 256 --size 1024 --shared 2>/dev/null && fail
+echo "key0" | $CRYPTSETUP create $DEV_NAME3 $LOOPDEV --offset 256 --size 256 --shared || fail
+$CRYPTSETUP -q remove $DEV_NAME3 || fail
+$CRYPTSETUP -q remove $DEV_NAME2 || fail
+$CRYPTSETUP -q remove $DEV_NAME || fail
+
remove_mapping
exit 0