Commit 772ae5f5 authored by Milan Broz's avatar Milan Broz Committed by Alasdair G Kergon

dm crypt: optionally support discard requests

Add optional parameter field to dmcrypt table and support
"allow_discards" option.

Discard requests bypass crypt queue processing. Bio is simple remapped
to underlying device.

Note that discard will be never enabled by default because of security
consequences.  It is up to the administrator to enable it for encrypted
devices.

(Note that userspace cryptsetup does not understand new optional
parameters yet.  Support for this will come later.  Until then, you
should use 'dmsetup' to enable and disable this.)
Signed-off-by: default avatarMilan Broz <mbroz@redhat.com>
Signed-off-by: default avatarAlasdair G Kergon <agk@redhat.com>
parent 32737279
...@@ -4,7 +4,8 @@ dm-crypt ...@@ -4,7 +4,8 @@ dm-crypt
Device-Mapper's "crypt" target provides transparent encryption of block devices Device-Mapper's "crypt" target provides transparent encryption of block devices
using the kernel crypto API. using the kernel crypto API.
Parameters: <cipher> <key> <iv_offset> <device path> <offset> Parameters: <cipher> <key> <iv_offset> <device path> \
<offset> [<#opt_params> <opt_params>]
<cipher> <cipher>
Encryption cipher and an optional IV generation mode. Encryption cipher and an optional IV generation mode.
...@@ -37,6 +38,24 @@ Parameters: <cipher> <key> <iv_offset> <device path> <offset> ...@@ -37,6 +38,24 @@ Parameters: <cipher> <key> <iv_offset> <device path> <offset>
<offset> <offset>
Starting sector within the device where the encrypted data begins. Starting sector within the device where the encrypted data begins.
<#opt_params>
Number of optional parameters. If there are no optional parameters,
the optional paramaters section can be skipped or #opt_params can be zero.
Otherwise #opt_params is the number of following arguments.
Example of optional parameters section:
1 allow_discards
allow_discards
Block discard requests (a.k.a. TRIM) are passed through the crypt device.
The default is to ignore discard requests.
WARNING: Assess the specific security risks carefully before enabling this
option. For example, allowing discards on encrypted devices may lead to
the leak of information about the ciphertext device (filesystem type,
used space etc.) if the discarded blocks can be located easily on the
device later.
Example scripts Example scripts
=============== ===============
LUKS (Linux Unified Key Setup) is now the preferred way to set up disk LUKS (Linux Unified Key Setup) is now the preferred way to set up disk
......
...@@ -1574,11 +1574,17 @@ static int crypt_ctr_cipher(struct dm_target *ti, ...@@ -1574,11 +1574,17 @@ static int crypt_ctr_cipher(struct dm_target *ti,
static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv)
{ {
struct crypt_config *cc; struct crypt_config *cc;
unsigned int key_size; unsigned int key_size, opt_params;
unsigned long long tmpll; unsigned long long tmpll;
int ret; int ret;
struct dm_arg_set as;
const char *opt_string;
static struct dm_arg _args[] = {
{0, 1, "Invalid number of feature args"},
};
if (argc != 5) { if (argc < 5) {
ti->error = "Not enough arguments"; ti->error = "Not enough arguments";
return -EINVAL; return -EINVAL;
} }
...@@ -1647,6 +1653,30 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) ...@@ -1647,6 +1653,30 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv)
} }
cc->start = tmpll; cc->start = tmpll;
argv += 5;
argc -= 5;
/* Optional parameters */
if (argc) {
as.argc = argc;
as.argv = argv;
ret = dm_read_arg_group(_args, &as, &opt_params, &ti->error);
if (ret)
goto bad;
opt_string = dm_shift_arg(&as);
if (opt_params == 1 && opt_string &&
!strcasecmp(opt_string, "allow_discards"))
ti->num_discard_requests = 1;
else if (opt_params) {
ret = -EINVAL;
ti->error = "Invalid feature arguments";
goto bad;
}
}
ret = -ENOMEM; ret = -ENOMEM;
cc->io_queue = alloc_workqueue("kcryptd_io", cc->io_queue = alloc_workqueue("kcryptd_io",
WQ_NON_REENTRANT| WQ_NON_REENTRANT|
...@@ -1681,9 +1711,16 @@ static int crypt_map(struct dm_target *ti, struct bio *bio, ...@@ -1681,9 +1711,16 @@ static int crypt_map(struct dm_target *ti, struct bio *bio,
struct dm_crypt_io *io; struct dm_crypt_io *io;
struct crypt_config *cc; struct crypt_config *cc;
if (bio->bi_rw & REQ_FLUSH) { /*
* If bio is REQ_FLUSH or REQ_DISCARD, just bypass crypt queues.
* - for REQ_FLUSH device-mapper core ensures that no IO is in-flight
* - for REQ_DISCARD caller must use flush if IO ordering matters
*/
if (unlikely(bio->bi_rw & (REQ_FLUSH | REQ_DISCARD))) {
cc = ti->private; cc = ti->private;
bio->bi_bdev = cc->dev->bdev; bio->bi_bdev = cc->dev->bdev;
if (bio_sectors(bio))
bio->bi_sector = cc->start + dm_target_offset(ti, bio->bi_sector);
return DM_MAPIO_REMAPPED; return DM_MAPIO_REMAPPED;
} }
...@@ -1726,6 +1763,10 @@ static int crypt_status(struct dm_target *ti, status_type_t type, ...@@ -1726,6 +1763,10 @@ static int crypt_status(struct dm_target *ti, status_type_t type,
DMEMIT(" %llu %s %llu", (unsigned long long)cc->iv_offset, DMEMIT(" %llu %s %llu", (unsigned long long)cc->iv_offset,
cc->dev->name, (unsigned long long)cc->start); cc->dev->name, (unsigned long long)cc->start);
if (ti->num_discard_requests)
DMEMIT(" 1 allow_discards");
break; break;
} }
return 0; return 0;
...@@ -1822,7 +1863,7 @@ static int crypt_iterate_devices(struct dm_target *ti, ...@@ -1822,7 +1863,7 @@ static int crypt_iterate_devices(struct dm_target *ti,
static struct target_type crypt_target = { static struct target_type crypt_target = {
.name = "crypt", .name = "crypt",
.version = {1, 10, 0}, .version = {1, 11, 0},
.module = THIS_MODULE, .module = THIS_MODULE,
.ctr = crypt_ctr, .ctr = crypt_ctr,
.dtr = crypt_dtr, .dtr = crypt_dtr,
......
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