aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2016-10-26 10:02:01 -0400
committerJames Morris <james.l.morris@oracle.com>2016-10-27 01:03:27 -0400
commit7df3e59c3d1df4f87fe874c7956ef7a3d2f4d5fb (patch)
tree5a232a7bc6c456e08b59c0b5d58c8f109f553cc2
parent03dab869b7b239c4e013ec82aea22e181e441cfc (diff)
KEYS: Sort out big_key initialisation
big_key has two separate initialisation functions, one that registers the key type and one that registers the crypto. If the key type fails to register, there's no problem if the crypto registers successfully because there's no way to reach the crypto except through the key type. However, if the key type registers successfully but the crypto does not, big_key_rng and big_key_blkcipher may end up set to NULL - but the code neither checks for this nor unregisters the big key key type. Furthermore, since the key type is registered before the crypto, it is theoretically possible for the kernel to try adding a big_key before the crypto is set up, leading to the same effect. Fix this by merging big_key_crypto_init() and big_key_init() and calling the resulting function late. If they're going to be encrypted, we shouldn't be creating big_keys before we have the facilities to do the encryption available. The key type registration is also moved after the crypto initialisation. The fix also includes message printing on failure. If the big_key type isn't correctly set up, simply doing: dd if=/dev/zero bs=4096 count=1 | keyctl padd big_key a @s ought to cause an oops. Fixes: 13100a72f40f5748a04017e0ab3df4cf27c809ef ('Security: Keys: Big keys stored encrypted') Signed-off-by: David Howells <dhowells@redhat.com> cc: Peter Hlavaty <zer0mem@yahoo.com> cc: Kirill Marinushkin <k.marinushkin@gmail.com> cc: Artem Savkov <asavkov@redhat.com> cc: stable@vger.kernel.org Signed-off-by: James Morris <james.l.morris@oracle.com>
-rw-r--r--security/keys/big_key.c59
1 files changed, 32 insertions, 27 deletions
diff --git a/security/keys/big_key.c b/security/keys/big_key.c
index c0b3030b5634..835c1ab30d01 100644
--- a/security/keys/big_key.c
+++ b/security/keys/big_key.c
@@ -9,6 +9,7 @@
9 * 2 of the Licence, or (at your option) any later version. 9 * 2 of the Licence, or (at your option) any later version.
10 */ 10 */
11 11
12#define pr_fmt(fmt) "big_key: "fmt
12#include <linux/init.h> 13#include <linux/init.h>
13#include <linux/seq_file.h> 14#include <linux/seq_file.h>
14#include <linux/file.h> 15#include <linux/file.h>
@@ -341,44 +342,48 @@ error:
341 */ 342 */
342static int __init big_key_init(void) 343static int __init big_key_init(void)
343{ 344{
344 return register_key_type(&key_type_big_key); 345 struct crypto_skcipher *cipher;
345} 346 struct crypto_rng *rng;
346 347 int ret;
347/*
348 * Initialize big_key crypto and RNG algorithms
349 */
350static int __init big_key_crypto_init(void)
351{
352 int ret = -EINVAL;
353 348
354 /* init RNG */ 349 rng = crypto_alloc_rng(big_key_rng_name, 0, 0);
355 big_key_rng = crypto_alloc_rng(big_key_rng_name, 0, 0); 350 if (IS_ERR(rng)) {
356 if (IS_ERR(big_key_rng)) { 351 pr_err("Can't alloc rng: %ld\n", PTR_ERR(rng));
357 big_key_rng = NULL; 352 return PTR_ERR(rng);
358 return -EFAULT;
359 } 353 }
360 354
355 big_key_rng = rng;
356
361 /* seed RNG */ 357 /* seed RNG */
362 ret = crypto_rng_reset(big_key_rng, NULL, crypto_rng_seedsize(big_key_rng)); 358 ret = crypto_rng_reset(rng, NULL, crypto_rng_seedsize(rng));
363 if (ret) 359 if (ret) {
364 goto error; 360 pr_err("Can't reset rng: %d\n", ret);
361 goto error_rng;
362 }
365 363
366 /* init block cipher */ 364 /* init block cipher */
367 big_key_skcipher = crypto_alloc_skcipher(big_key_alg_name, 365 cipher = crypto_alloc_skcipher(big_key_alg_name, 0, CRYPTO_ALG_ASYNC);
368 0, CRYPTO_ALG_ASYNC); 366 if (IS_ERR(cipher)) {
369 if (IS_ERR(big_key_skcipher)) { 367 ret = PTR_ERR(cipher);
370 big_key_skcipher = NULL; 368 pr_err("Can't alloc crypto: %d\n", ret);
371 ret = -EFAULT; 369 goto error_rng;
372 goto error; 370 }
371
372 big_key_skcipher = cipher;
373
374 ret = register_key_type(&key_type_big_key);
375 if (ret < 0) {
376 pr_err("Can't register type: %d\n", ret);
377 goto error_cipher;
373 } 378 }
374 379
375 return 0; 380 return 0;
376 381
377error: 382error_cipher:
383 crypto_free_skcipher(big_key_skcipher);
384error_rng:
378 crypto_free_rng(big_key_rng); 385 crypto_free_rng(big_key_rng);
379 big_key_rng = NULL;
380 return ret; 386 return ret;
381} 387}
382 388
383device_initcall(big_key_init); 389late_initcall(big_key_init);
384late_initcall(big_key_crypto_init);