Commit 1cf55613 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'for-4.15/dm-fixes-2' of...

Merge tag 'for-4.15/dm-fixes-2' of git://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm

Pull device mapper fixes from Mike Snitzer:
 "All fixes marked for stable:

   - Fix DM thinp btree corruption seen when inserting a new key/value
     pair into a full root node.

   - Fix DM thinp btree removal deadlock due to artificially low number
     of allowed concurrent locks allowed.

   - Fix possible DM crypt corruption if kernel keyring service is used.
     Only affects ciphers using following IVs: essiv, lmk and tcw.

   - Two DM crypt device initialization error checking fixes.

   - Fix DM integrity to allow use of async ciphers that require DMA"

* tag 'for-4.15/dm-fixes-2' of git://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm:
  dm crypt: fix error return code in crypt_ctr()
  dm crypt: wipe kernel key copy after IV initialization
  dm integrity: don't store cipher request on the stack
  dm crypt: fix crash by adding missing check for auth key size
  dm btree: fix serious bug in btree_split_beneath()
  dm thin metadata: THIN_MAX_CONCURRENT_LOCKS should be 6
parents ec835f81 3cc2e57c
...@@ -1954,10 +1954,15 @@ static int crypt_setkey(struct crypt_config *cc) ...@@ -1954,10 +1954,15 @@ static int crypt_setkey(struct crypt_config *cc)
/* Ignore extra keys (which are used for IV etc) */ /* Ignore extra keys (which are used for IV etc) */
subkey_size = crypt_subkey_size(cc); subkey_size = crypt_subkey_size(cc);
if (crypt_integrity_hmac(cc)) if (crypt_integrity_hmac(cc)) {
if (subkey_size < cc->key_mac_size)
return -EINVAL;
crypt_copy_authenckey(cc->authenc_key, cc->key, crypt_copy_authenckey(cc->authenc_key, cc->key,
subkey_size - cc->key_mac_size, subkey_size - cc->key_mac_size,
cc->key_mac_size); cc->key_mac_size);
}
for (i = 0; i < cc->tfms_count; i++) { for (i = 0; i < cc->tfms_count; i++) {
if (crypt_integrity_hmac(cc)) if (crypt_integrity_hmac(cc))
r = crypto_aead_setkey(cc->cipher_tfm.tfms_aead[i], r = crypto_aead_setkey(cc->cipher_tfm.tfms_aead[i],
...@@ -2053,9 +2058,6 @@ static int crypt_set_keyring_key(struct crypt_config *cc, const char *key_string ...@@ -2053,9 +2058,6 @@ static int crypt_set_keyring_key(struct crypt_config *cc, const char *key_string
ret = crypt_setkey(cc); ret = crypt_setkey(cc);
/* wipe the kernel key payload copy in each case */
memset(cc->key, 0, cc->key_size * sizeof(u8));
if (!ret) { if (!ret) {
set_bit(DM_CRYPT_KEY_VALID, &cc->flags); set_bit(DM_CRYPT_KEY_VALID, &cc->flags);
kzfree(cc->key_string); kzfree(cc->key_string);
...@@ -2523,6 +2525,10 @@ static int crypt_ctr_cipher(struct dm_target *ti, char *cipher_in, char *key) ...@@ -2523,6 +2525,10 @@ static int crypt_ctr_cipher(struct dm_target *ti, char *cipher_in, char *key)
} }
} }
/* wipe the kernel key payload copy */
if (cc->key_string)
memset(cc->key, 0, cc->key_size * sizeof(u8));
return ret; return ret;
} }
...@@ -2740,6 +2746,7 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) ...@@ -2740,6 +2746,7 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv)
cc->tag_pool_max_sectors * cc->on_disk_tag_size); cc->tag_pool_max_sectors * cc->on_disk_tag_size);
if (!cc->tag_pool) { if (!cc->tag_pool) {
ti->error = "Cannot allocate integrity tags mempool"; ti->error = "Cannot allocate integrity tags mempool";
ret = -ENOMEM;
goto bad; goto bad;
} }
...@@ -2961,6 +2968,9 @@ static int crypt_message(struct dm_target *ti, unsigned argc, char **argv) ...@@ -2961,6 +2968,9 @@ static int crypt_message(struct dm_target *ti, unsigned argc, char **argv)
return ret; return ret;
if (cc->iv_gen_ops && cc->iv_gen_ops->init) if (cc->iv_gen_ops && cc->iv_gen_ops->init)
ret = cc->iv_gen_ops->init(cc); ret = cc->iv_gen_ops->init(cc);
/* wipe the kernel key payload copy */
if (cc->key_string)
memset(cc->key, 0, cc->key_size * sizeof(u8));
return ret; return ret;
} }
if (argc == 2 && !strcasecmp(argv[1], "wipe")) { if (argc == 2 && !strcasecmp(argv[1], "wipe")) {
...@@ -3007,7 +3017,7 @@ static void crypt_io_hints(struct dm_target *ti, struct queue_limits *limits) ...@@ -3007,7 +3017,7 @@ static void crypt_io_hints(struct dm_target *ti, struct queue_limits *limits)
static struct target_type crypt_target = { static struct target_type crypt_target = {
.name = "crypt", .name = "crypt",
.version = {1, 18, 0}, .version = {1, 18, 1},
.module = THIS_MODULE, .module = THIS_MODULE,
.ctr = crypt_ctr, .ctr = crypt_ctr,
.dtr = crypt_dtr, .dtr = crypt_dtr,
......
...@@ -2559,7 +2559,8 @@ static int create_journal(struct dm_integrity_c *ic, char **error) ...@@ -2559,7 +2559,8 @@ static int create_journal(struct dm_integrity_c *ic, char **error)
int r = 0; int r = 0;
unsigned i; unsigned i;
__u64 journal_pages, journal_desc_size, journal_tree_size; __u64 journal_pages, journal_desc_size, journal_tree_size;
unsigned char *crypt_data = NULL; unsigned char *crypt_data = NULL, *crypt_iv = NULL;
struct skcipher_request *req = NULL;
ic->commit_ids[0] = cpu_to_le64(0x1111111111111111ULL); ic->commit_ids[0] = cpu_to_le64(0x1111111111111111ULL);
ic->commit_ids[1] = cpu_to_le64(0x2222222222222222ULL); ic->commit_ids[1] = cpu_to_le64(0x2222222222222222ULL);
...@@ -2617,9 +2618,20 @@ static int create_journal(struct dm_integrity_c *ic, char **error) ...@@ -2617,9 +2618,20 @@ static int create_journal(struct dm_integrity_c *ic, char **error)
if (blocksize == 1) { if (blocksize == 1) {
struct scatterlist *sg; struct scatterlist *sg;
SKCIPHER_REQUEST_ON_STACK(req, ic->journal_crypt);
unsigned char iv[ivsize]; req = skcipher_request_alloc(ic->journal_crypt, GFP_KERNEL);
skcipher_request_set_tfm(req, ic->journal_crypt); if (!req) {
*error = "Could not allocate crypt request";
r = -ENOMEM;
goto bad;
}
crypt_iv = kmalloc(ivsize, GFP_KERNEL);
if (!crypt_iv) {
*error = "Could not allocate iv";
r = -ENOMEM;
goto bad;
}
ic->journal_xor = dm_integrity_alloc_page_list(ic); ic->journal_xor = dm_integrity_alloc_page_list(ic);
if (!ic->journal_xor) { if (!ic->journal_xor) {
...@@ -2641,9 +2653,9 @@ static int create_journal(struct dm_integrity_c *ic, char **error) ...@@ -2641,9 +2653,9 @@ static int create_journal(struct dm_integrity_c *ic, char **error)
sg_set_buf(&sg[i], va, PAGE_SIZE); sg_set_buf(&sg[i], va, PAGE_SIZE);
} }
sg_set_buf(&sg[i], &ic->commit_ids, sizeof ic->commit_ids); sg_set_buf(&sg[i], &ic->commit_ids, sizeof ic->commit_ids);
memset(iv, 0x00, ivsize); memset(crypt_iv, 0x00, ivsize);
skcipher_request_set_crypt(req, sg, sg, PAGE_SIZE * ic->journal_pages + sizeof ic->commit_ids, iv); skcipher_request_set_crypt(req, sg, sg, PAGE_SIZE * ic->journal_pages + sizeof ic->commit_ids, crypt_iv);
init_completion(&comp.comp); init_completion(&comp.comp);
comp.in_flight = (atomic_t)ATOMIC_INIT(1); comp.in_flight = (atomic_t)ATOMIC_INIT(1);
if (do_crypt(true, req, &comp)) if (do_crypt(true, req, &comp))
...@@ -2659,10 +2671,22 @@ static int create_journal(struct dm_integrity_c *ic, char **error) ...@@ -2659,10 +2671,22 @@ static int create_journal(struct dm_integrity_c *ic, char **error)
crypto_free_skcipher(ic->journal_crypt); crypto_free_skcipher(ic->journal_crypt);
ic->journal_crypt = NULL; ic->journal_crypt = NULL;
} else { } else {
SKCIPHER_REQUEST_ON_STACK(req, ic->journal_crypt);
unsigned char iv[ivsize];
unsigned crypt_len = roundup(ivsize, blocksize); unsigned crypt_len = roundup(ivsize, blocksize);
req = skcipher_request_alloc(ic->journal_crypt, GFP_KERNEL);
if (!req) {
*error = "Could not allocate crypt request";
r = -ENOMEM;
goto bad;
}
crypt_iv = kmalloc(ivsize, GFP_KERNEL);
if (!crypt_iv) {
*error = "Could not allocate iv";
r = -ENOMEM;
goto bad;
}
crypt_data = kmalloc(crypt_len, GFP_KERNEL); crypt_data = kmalloc(crypt_len, GFP_KERNEL);
if (!crypt_data) { if (!crypt_data) {
*error = "Unable to allocate crypt data"; *error = "Unable to allocate crypt data";
...@@ -2670,8 +2694,6 @@ static int create_journal(struct dm_integrity_c *ic, char **error) ...@@ -2670,8 +2694,6 @@ static int create_journal(struct dm_integrity_c *ic, char **error)
goto bad; goto bad;
} }
skcipher_request_set_tfm(req, ic->journal_crypt);
ic->journal_scatterlist = dm_integrity_alloc_journal_scatterlist(ic, ic->journal); ic->journal_scatterlist = dm_integrity_alloc_journal_scatterlist(ic, ic->journal);
if (!ic->journal_scatterlist) { if (!ic->journal_scatterlist) {
*error = "Unable to allocate sg list"; *error = "Unable to allocate sg list";
...@@ -2695,12 +2717,12 @@ static int create_journal(struct dm_integrity_c *ic, char **error) ...@@ -2695,12 +2717,12 @@ static int create_journal(struct dm_integrity_c *ic, char **error)
struct skcipher_request *section_req; struct skcipher_request *section_req;
__u32 section_le = cpu_to_le32(i); __u32 section_le = cpu_to_le32(i);
memset(iv, 0x00, ivsize); memset(crypt_iv, 0x00, ivsize);
memset(crypt_data, 0x00, crypt_len); memset(crypt_data, 0x00, crypt_len);
memcpy(crypt_data, &section_le, min((size_t)crypt_len, sizeof(section_le))); memcpy(crypt_data, &section_le, min((size_t)crypt_len, sizeof(section_le)));
sg_init_one(&sg, crypt_data, crypt_len); sg_init_one(&sg, crypt_data, crypt_len);
skcipher_request_set_crypt(req, &sg, &sg, crypt_len, iv); skcipher_request_set_crypt(req, &sg, &sg, crypt_len, crypt_iv);
init_completion(&comp.comp); init_completion(&comp.comp);
comp.in_flight = (atomic_t)ATOMIC_INIT(1); comp.in_flight = (atomic_t)ATOMIC_INIT(1);
if (do_crypt(true, req, &comp)) if (do_crypt(true, req, &comp))
...@@ -2758,6 +2780,9 @@ static int create_journal(struct dm_integrity_c *ic, char **error) ...@@ -2758,6 +2780,9 @@ static int create_journal(struct dm_integrity_c *ic, char **error)
} }
bad: bad:
kfree(crypt_data); kfree(crypt_data);
kfree(crypt_iv);
skcipher_request_free(req);
return r; return r;
} }
......
...@@ -80,10 +80,14 @@ ...@@ -80,10 +80,14 @@
#define SECTOR_TO_BLOCK_SHIFT 3 #define SECTOR_TO_BLOCK_SHIFT 3
/* /*
* For btree insert:
* 3 for btree insert + * 3 for btree insert +
* 2 for btree lookup used within space map * 2 for btree lookup used within space map
* For btree remove:
* 2 for shadow spine +
* 4 for rebalance 3 child node
*/ */
#define THIN_MAX_CONCURRENT_LOCKS 5 #define THIN_MAX_CONCURRENT_LOCKS 6
/* This should be plenty */ /* This should be plenty */
#define SPACE_MAP_ROOT_SIZE 128 #define SPACE_MAP_ROOT_SIZE 128
......
...@@ -683,23 +683,8 @@ static int btree_split_beneath(struct shadow_spine *s, uint64_t key) ...@@ -683,23 +683,8 @@ static int btree_split_beneath(struct shadow_spine *s, uint64_t key)
pn->keys[1] = rn->keys[0]; pn->keys[1] = rn->keys[0];
memcpy_disk(value_ptr(pn, 1), &val, sizeof(__le64)); memcpy_disk(value_ptr(pn, 1), &val, sizeof(__le64));
/* unlock_block(s->info, left);
* rejig the spine. This is ugly, since it knows too unlock_block(s->info, right);
* much about the spine
*/
if (s->nodes[0] != new_parent) {
unlock_block(s->info, s->nodes[0]);
s->nodes[0] = new_parent;
}
if (key < le64_to_cpu(rn->keys[0])) {
unlock_block(s->info, right);
s->nodes[1] = left;
} else {
unlock_block(s->info, left);
s->nodes[1] = right;
}
s->count = 2;
return 0; return 0;
} }
......
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