linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] KEYS: Sort out big_key initialisation
@ 2016-07-30 20:03 Kirill Marinushkin
  2016-07-30 20:12 ` Joe Perches
  0 siblings, 1 reply; 5+ messages in thread
From: Kirill Marinushkin @ 2016-07-30 20:03 UTC (permalink / raw)
  To: dhowells
  Cc: zer0mem, gregkh, serge, james.l.morris, keyrings,
	linux-security-module, linux-kernel, stable, k.marinushkin

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.

Signed-off-by: David Howells <dhowells@redhat.com>
cc: Peter Hlavaty <zer0mem@yahoo.com>
cc: stable@vger.kernel.org
Signed-off-by: Kirill Marinushkin <k.marinushkin@gmail.com>
---
 security/keys/Kconfig   |  2 +-
 security/keys/big_key.c | 62 +++++++++++++++++++++++++++----------------------
 2 files changed, 35 insertions(+), 29 deletions(-)

diff --git a/security/keys/Kconfig b/security/keys/Kconfig
index f826e87..8213221 100644
--- a/security/keys/Kconfig
+++ b/security/keys/Kconfig
@@ -44,7 +44,7 @@ config BIG_KEYS
 	select CRYPTO
 	select CRYPTO_AES
 	select CRYPTO_ECB
-	select CRYPTO_RNG
+	select CRYPTO_ANSI_CPRNG
 	help
 	  This option provides support for holding large keys within the kernel
 	  (for example Kerberos ticket caches).  The data may be stored out to
diff --git a/security/keys/big_key.c b/security/keys/big_key.c
index c0b3030..fce1df9 100644
--- a/security/keys/big_key.c
+++ b/security/keys/big_key.c
@@ -9,6 +9,7 @@
  * 2 of the Licence, or (at your option) any later version.
  */
 
+#define pr_fmt(fmt) "big_key: "fmt
 #include <linux/init.h>
 #include <linux/seq_file.h>
 #include <linux/file.h>
@@ -341,44 +342,49 @@ error:
  */
 static int __init big_key_init(void)
 {
-	return register_key_type(&key_type_big_key);
-}
-
-/*
- * Initialize big_key crypto and RNG algorithms
- */
-static int __init big_key_crypto_init(void)
-{
-	int ret = -EINVAL;
+	struct crypto_skcipher *cipher;
+	struct crypto_rng *rng;
+	int ret;
 
-	/* init RNG */
-	big_key_rng = crypto_alloc_rng(big_key_rng_name, 0, 0);
-	if (IS_ERR(big_key_rng)) {
-		big_key_rng = NULL;
-		return -EFAULT;
+	rng = crypto_alloc_rng(big_key_rng_name, 0, 0);
+	if (IS_ERR(rng)) {
+		pr_err("Can't alloc rng: %ld\n", PTR_ERR(rng));
+		return PTR_ERR(rng);
 	}
 
+	big_key_rng = rng;
+
 	/* seed RNG */
-	ret = crypto_rng_reset(big_key_rng, NULL, crypto_rng_seedsize(big_key_rng));
-	if (ret)
-		goto error;
+	ret = crypto_rng_reset(rng, NULL, crypto_rng_seedsize(rng));
+	if (ret) {
+		pr_err("Can't reset rng: %d\n", ret);
+		goto error_rng;
+	}
 
-	/* init block cipher */
-	big_key_skcipher = crypto_alloc_skcipher(big_key_alg_name,
-						 0, CRYPTO_ALG_ASYNC);
-	if (IS_ERR(big_key_skcipher)) {
-		big_key_skcipher = NULL;
-		ret = -EFAULT;
-		goto error;
+	cipher = crypto_alloc_skcipher(big_key_alg_name,
+				       0, CRYPTO_ALG_ASYNC);
+	if (IS_ERR(cipher)) {
+		ret = PTR_ERR(cipher);
+		pr_err("Can't alloc crypto: %d\n", ret);
+		goto error_rng;
+	}
+
+	big_key_skcipher = cipher;
+
+	ret = register_key_type(&key_type_big_key);
+	if (ret < 0) {
+		pr_err("Can't register key type: %d\n", ret);
+		goto error_cipher;
 	}
 
 	return 0;
 
-error:
+error_cipher:
+	crypto_free_skcipher(big_key_skcipher);
+error_rng:
 	crypto_free_rng(big_key_rng);
-	big_key_rng = NULL;
+
 	return ret;
 }
 
-device_initcall(big_key_init);
-late_initcall(big_key_crypto_init);
+late_initcall(big_key_init);
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH] KEYS: Sort out big_key initialisation
  2016-07-30 20:03 [PATCH] KEYS: Sort out big_key initialisation Kirill Marinushkin
@ 2016-07-30 20:12 ` Joe Perches
  2016-08-11 19:17   ` Kirill Marinushkin
  0 siblings, 1 reply; 5+ messages in thread
From: Joe Perches @ 2016-07-30 20:12 UTC (permalink / raw)
  To: Kirill Marinushkin, dhowells
  Cc: zer0mem, gregkh, serge, james.l.morris, keyrings,
	linux-security-module, linux-kernel, stable

On Sat, 2016-07-30 at 22:03 +0200, Kirill Marinushkin wrote:
> 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.

trivia:

> diff --git a/security/keys/big_key.c b/security/keys/big_key.c
[]
> @@ -9,6 +9,7 @@
>   * 2 of the Licence, or (at your option) any later version.
>   */
>  
> +#define pr_fmt(fmt) "big_key: "fmt

It's much more common to use

#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

^ permalink raw reply	[flat|nested] 5+ messages in thread

* RE: [PATCH] KEYS: Sort out big_key initialisation
  2016-07-30 20:12 ` Joe Perches
@ 2016-08-11 19:17   ` Kirill Marinushkin
  0 siblings, 0 replies; 5+ messages in thread
From: Kirill Marinushkin @ 2016-08-11 19:17 UTC (permalink / raw)
  To: joe
  Cc: dhowells, k.marinushkin, zer0mem, gregkh, serge, james.l.morris,
	keyrings, linux-security-module, linux-kernel, stable,
	Kirill Marinushkin

> It's much more common to use
> 
> #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

This happened to be a wrong email thread and a wrong kernel tag;
I resent a proper patch in-reply-to a proper thread.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] KEYS: Sort out big_key initialisation
  2016-07-30 16:21 Kirill Marinushkin
@ 2016-07-30 17:07 ` Greg KH
  0 siblings, 0 replies; 5+ messages in thread
From: Greg KH @ 2016-07-30 17:07 UTC (permalink / raw)
  To: Kirill Marinushkin
  Cc: dhowells, zer0mem, serge, james.l.morris, keyrings,
	linux-security-module, linux-kernel, stable

On Sat, Jul 30, 2016 at 06:21:41PM +0200, Kirill Marinushkin wrote:
> 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.
> 
> Signed-off-by: David Howells <dhowells@redhat.com>
> Signed-off-by: Kirill Marinushkin <k.marinushkin@gmail.com>
> ---
>  security/keys/Kconfig   |  2 +-
>  security/keys/big_key.c | 62 +++++++++++++++++++++++++++----------------------
>  2 files changed, 35 insertions(+), 29 deletions(-)


<formletter>

This is not the correct way to submit patches for inclusion in the
stable kernel tree.  Please read Documentation/stable_kernel_rules.txt
for how to do this properly.

</formletter>

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH] KEYS: Sort out big_key initialisation
@ 2016-07-30 16:21 Kirill Marinushkin
  2016-07-30 17:07 ` Greg KH
  0 siblings, 1 reply; 5+ messages in thread
From: Kirill Marinushkin @ 2016-07-30 16:21 UTC (permalink / raw)
  To: dhowells
  Cc: zer0mem, gregkh, serge, james.l.morris, keyrings,
	linux-security-module, linux-kernel, stable, k.marinushkin

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.

Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: Kirill Marinushkin <k.marinushkin@gmail.com>
---
 security/keys/Kconfig   |  2 +-
 security/keys/big_key.c | 62 +++++++++++++++++++++++++++----------------------
 2 files changed, 35 insertions(+), 29 deletions(-)

diff --git a/security/keys/Kconfig b/security/keys/Kconfig
index f826e87..8213221 100644
--- a/security/keys/Kconfig
+++ b/security/keys/Kconfig
@@ -44,7 +44,7 @@ config BIG_KEYS
 	select CRYPTO
 	select CRYPTO_AES
 	select CRYPTO_ECB
-	select CRYPTO_RNG
+	select CRYPTO_ANSI_CPRNG
 	help
 	  This option provides support for holding large keys within the kernel
 	  (for example Kerberos ticket caches).  The data may be stored out to
diff --git a/security/keys/big_key.c b/security/keys/big_key.c
index c0b3030..fce1df9 100644
--- a/security/keys/big_key.c
+++ b/security/keys/big_key.c
@@ -9,6 +9,7 @@
  * 2 of the Licence, or (at your option) any later version.
  */
 
+#define pr_fmt(fmt) "big_key: "fmt
 #include <linux/init.h>
 #include <linux/seq_file.h>
 #include <linux/file.h>
@@ -341,44 +342,49 @@ error:
  */
 static int __init big_key_init(void)
 {
-	return register_key_type(&key_type_big_key);
-}
-
-/*
- * Initialize big_key crypto and RNG algorithms
- */
-static int __init big_key_crypto_init(void)
-{
-	int ret = -EINVAL;
+	struct crypto_skcipher *cipher;
+	struct crypto_rng *rng;
+	int ret;
 
-	/* init RNG */
-	big_key_rng = crypto_alloc_rng(big_key_rng_name, 0, 0);
-	if (IS_ERR(big_key_rng)) {
-		big_key_rng = NULL;
-		return -EFAULT;
+	rng = crypto_alloc_rng(big_key_rng_name, 0, 0);
+	if (IS_ERR(rng)) {
+		pr_err("Can't alloc rng: %ld\n", PTR_ERR(rng));
+		return PTR_ERR(rng);
 	}
 
+	big_key_rng = rng;
+
 	/* seed RNG */
-	ret = crypto_rng_reset(big_key_rng, NULL, crypto_rng_seedsize(big_key_rng));
-	if (ret)
-		goto error;
+	ret = crypto_rng_reset(rng, NULL, crypto_rng_seedsize(rng));
+	if (ret) {
+		pr_err("Can't reset rng: %d\n", ret);
+		goto error_rng;
+	}
 
-	/* init block cipher */
-	big_key_skcipher = crypto_alloc_skcipher(big_key_alg_name,
-						 0, CRYPTO_ALG_ASYNC);
-	if (IS_ERR(big_key_skcipher)) {
-		big_key_skcipher = NULL;
-		ret = -EFAULT;
-		goto error;
+	cipher = crypto_alloc_skcipher(big_key_alg_name,
+				       0, CRYPTO_ALG_ASYNC);
+	if (IS_ERR(cipher)) {
+		ret = PTR_ERR(cipher);
+		pr_err("Can't alloc crypto: %d\n", ret);
+		goto error_rng;
+	}
+
+	big_key_skcipher = cipher;
+
+	ret = register_key_type(&key_type_big_key);
+	if (ret < 0) {
+		pr_err("Can't register key type: %d\n", ret);
+		goto error_cipher;
 	}
 
 	return 0;
 
-error:
+error_cipher:
+	crypto_free_skcipher(big_key_skcipher);
+error_rng:
 	crypto_free_rng(big_key_rng);
-	big_key_rng = NULL;
+
 	return ret;
 }
 
-device_initcall(big_key_init);
-late_initcall(big_key_crypto_init);
+late_initcall(big_key_init);
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2016-08-11 19:31 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-07-30 20:03 [PATCH] KEYS: Sort out big_key initialisation Kirill Marinushkin
2016-07-30 20:12 ` Joe Perches
2016-08-11 19:17   ` Kirill Marinushkin
  -- strict thread matches above, loose matches on Subject: below --
2016-07-30 16:21 Kirill Marinushkin
2016-07-30 17:07 ` Greg KH

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).