dm crypt: wipe kernel key copy after IV initialization

Loading key via kernel keyring service erases the internal
key copy immediately after we pass it in crypto layer. This is
wrong because IV is initialized later and we use wrong key
for the initialization (instead of real key there's just zeroed
block).

The bug may cause data corruption if key is loaded via kernel keyring
service first and later same crypt device is reactivated using exactly
same key in hexbyte representation, or vice versa. The bug (and fix)
affects only ciphers using following IVs: essiv, lmk and tcw.

Fixes: c538f6ec9f56 ("dm crypt: add ability to use keys from the kernel key retention service")
Cc: stable@vger.kernel.org # 4.10+
Signed-off-by: Ondrej Kozina <okozina@redhat.com>
Reviewed-by: Milan Broz <gmazyland@gmail.com>
Signed-off-by: Mike Snitzer <snitzer@redhat.com>

authored by Ondrej Kozina and committed by Mike Snitzer dc94902b 717f4b1c

+8 -4
+8 -4
drivers/md/dm-crypt.c
··· 2058 2058 2059 2059 ret = crypt_setkey(cc); 2060 2060 2061 - /* wipe the kernel key payload copy in each case */ 2062 - memset(cc->key, 0, cc->key_size * sizeof(u8)); 2063 - 2064 2061 if (!ret) { 2065 2062 set_bit(DM_CRYPT_KEY_VALID, &cc->flags); 2066 2063 kzfree(cc->key_string); ··· 2525 2528 } 2526 2529 } 2527 2530 2531 + /* wipe the kernel key payload copy */ 2532 + if (cc->key_string) 2533 + memset(cc->key, 0, cc->key_size * sizeof(u8)); 2534 + 2528 2535 return ret; 2529 2536 } 2530 2537 ··· 2967 2966 return ret; 2968 2967 if (cc->iv_gen_ops && cc->iv_gen_ops->init) 2969 2968 ret = cc->iv_gen_ops->init(cc); 2969 + /* wipe the kernel key payload copy */ 2970 + if (cc->key_string) 2971 + memset(cc->key, 0, cc->key_size * sizeof(u8)); 2970 2972 return ret; 2971 2973 } 2972 2974 if (argc == 2 && !strcasecmp(argv[1], "wipe")) { ··· 3016 3012 3017 3013 static struct target_type crypt_target = { 3018 3014 .name = "crypt", 3019 - .version = {1, 18, 0}, 3015 + .version = {1, 18, 1}, 3020 3016 .module = THIS_MODULE, 3021 3017 .ctr = crypt_ctr, 3022 3018 .dtr = crypt_dtr,