[kernel/f18] crypto: info leaks in report API (rhbz 918512 918521)

Josh Boyer jwboyer at fedoraproject.org
Wed Mar 6 13:55:04 UTC 2013


commit c03b60fe04081fb220366d516ca25575916be3a3
Author: Josh Boyer <jwboyer at redhat.com>
Date:   Wed Mar 6 08:53:40 2013 -0500

    crypto: info leaks in report API (rhbz 918512 918521)

 crypto-user-fix-info-leaks-in-report-API.patch |  223 ++++++++++++++++++++++++
 kernel.spec                                    |   11 +-
 2 files changed, 233 insertions(+), 1 deletions(-)
---
diff --git a/crypto-user-fix-info-leaks-in-report-API.patch b/crypto-user-fix-info-leaks-in-report-API.patch
new file mode 100644
index 0000000..1b64e18
--- /dev/null
+++ b/crypto-user-fix-info-leaks-in-report-API.patch
@@ -0,0 +1,223 @@
+From 9a5467bf7b6e9e02ec9c3da4e23747c05faeaac6 Mon Sep 17 00:00:00 2001
+From: Mathias Krause <minipli at googlemail.com>
+Date: Tue, 5 Feb 2013 18:19:13 +0100
+Subject: [PATCH] crypto: user - fix info leaks in report API
+
+Three errors resulting in kernel memory disclosure:
+
+1/ The structures used for the netlink based crypto algorithm report API
+are located on the stack. As snprintf() does not fill the remainder of
+the buffer with null bytes, those stack bytes will be disclosed to users
+of the API. Switch to strncpy() to fix this.
+
+2/ crypto_report_one() does not initialize all field of struct
+crypto_user_alg. Fix this to fix the heap info leak.
+
+3/ For the module name we should copy only as many bytes as
+module_name() returns -- not as much as the destination buffer could
+hold. But the current code does not and therefore copies random data
+from behind the end of the module name, as the module name is always
+shorter than CRYPTO_MAX_ALG_NAME.
+
+Also switch to use strncpy() to copy the algorithm's name and
+driver_name. They are strings, after all.
+
+Signed-off-by: Mathias Krause <minipli at googlemail.com>
+Cc: Steffen Klassert <steffen.klassert at secunet.com>
+Signed-off-by: Herbert Xu <herbert at gondor.apana.org.au>
+---
+ crypto/ablkcipher.c  | 12 ++++++------
+ crypto/aead.c        |  9 ++++-----
+ crypto/ahash.c       |  2 +-
+ crypto/blkcipher.c   |  6 +++---
+ crypto/crypto_user.c | 22 +++++++++++-----------
+ crypto/pcompress.c   |  3 +--
+ crypto/rng.c         |  2 +-
+ crypto/shash.c       |  3 ++-
+ 8 files changed, 29 insertions(+), 30 deletions(-)
+
+diff --git a/crypto/ablkcipher.c b/crypto/ablkcipher.c
+index 533de95..7d4a8d2 100644
+--- a/crypto/ablkcipher.c
++++ b/crypto/ablkcipher.c
+@@ -388,9 +388,9 @@ static int crypto_ablkcipher_report(struct sk_buff *skb, struct crypto_alg *alg)
+ {
+ 	struct crypto_report_blkcipher rblkcipher;
+ 
+-	snprintf(rblkcipher.type, CRYPTO_MAX_ALG_NAME, "%s", "ablkcipher");
+-	snprintf(rblkcipher.geniv, CRYPTO_MAX_ALG_NAME, "%s",
+-		 alg->cra_ablkcipher.geniv ?: "<default>");
++	strncpy(rblkcipher.type, "ablkcipher", sizeof(rblkcipher.type));
++	strncpy(rblkcipher.geniv, alg->cra_ablkcipher.geniv ?: "<default>",
++		sizeof(rblkcipher.geniv));
+ 
+ 	rblkcipher.blocksize = alg->cra_blocksize;
+ 	rblkcipher.min_keysize = alg->cra_ablkcipher.min_keysize;
+@@ -469,9 +469,9 @@ static int crypto_givcipher_report(struct sk_buff *skb, struct crypto_alg *alg)
+ {
+ 	struct crypto_report_blkcipher rblkcipher;
+ 
+-	snprintf(rblkcipher.type, CRYPTO_MAX_ALG_NAME, "%s", "givcipher");
+-	snprintf(rblkcipher.geniv, CRYPTO_MAX_ALG_NAME, "%s",
+-		 alg->cra_ablkcipher.geniv ?: "<built-in>");
++	strncpy(rblkcipher.type, "givcipher", sizeof(rblkcipher.type));
++	strncpy(rblkcipher.geniv, alg->cra_ablkcipher.geniv ?: "<built-in>",
++		sizeof(rblkcipher.geniv));
+ 
+ 	rblkcipher.blocksize = alg->cra_blocksize;
+ 	rblkcipher.min_keysize = alg->cra_ablkcipher.min_keysize;
+diff --git a/crypto/aead.c b/crypto/aead.c
+index 4d04e12..547491e 100644
+--- a/crypto/aead.c
++++ b/crypto/aead.c
+@@ -117,9 +117,8 @@ static int crypto_aead_report(struct sk_buff *skb, struct crypto_alg *alg)
+ 	struct crypto_report_aead raead;
+ 	struct aead_alg *aead = &alg->cra_aead;
+ 
+-	snprintf(raead.type, CRYPTO_MAX_ALG_NAME, "%s", "aead");
+-	snprintf(raead.geniv, CRYPTO_MAX_ALG_NAME, "%s",
+-		 aead->geniv ?: "<built-in>");
++	strncpy(raead.type, "aead", sizeof(raead.type));
++	strncpy(raead.geniv, aead->geniv ?: "<built-in>", sizeof(raead.geniv));
+ 
+ 	raead.blocksize = alg->cra_blocksize;
+ 	raead.maxauthsize = aead->maxauthsize;
+@@ -203,8 +202,8 @@ static int crypto_nivaead_report(struct sk_buff *skb, struct crypto_alg *alg)
+ 	struct crypto_report_aead raead;
+ 	struct aead_alg *aead = &alg->cra_aead;
+ 
+-	snprintf(raead.type, CRYPTO_MAX_ALG_NAME, "%s", "nivaead");
+-	snprintf(raead.geniv, CRYPTO_MAX_ALG_NAME, "%s", aead->geniv);
++	strncpy(raead.type, "nivaead", sizeof(raead.type));
++	strncpy(raead.geniv, aead->geniv, sizeof(raead.geniv));
+ 
+ 	raead.blocksize = alg->cra_blocksize;
+ 	raead.maxauthsize = aead->maxauthsize;
+diff --git a/crypto/ahash.c b/crypto/ahash.c
+index 3887856..793a27f 100644
+--- a/crypto/ahash.c
++++ b/crypto/ahash.c
+@@ -404,7 +404,7 @@ static int crypto_ahash_report(struct sk_buff *skb, struct crypto_alg *alg)
+ {
+ 	struct crypto_report_hash rhash;
+ 
+-	snprintf(rhash.type, CRYPTO_MAX_ALG_NAME, "%s", "ahash");
++	strncpy(rhash.type, "ahash", sizeof(rhash.type));
+ 
+ 	rhash.blocksize = alg->cra_blocksize;
+ 	rhash.digestsize = __crypto_hash_alg_common(alg)->digestsize;
+diff --git a/crypto/blkcipher.c b/crypto/blkcipher.c
+index e9e7244..a79e7e9 100644
+--- a/crypto/blkcipher.c
++++ b/crypto/blkcipher.c
+@@ -499,9 +499,9 @@ static int crypto_blkcipher_report(struct sk_buff *skb, struct crypto_alg *alg)
+ {
+ 	struct crypto_report_blkcipher rblkcipher;
+ 
+-	snprintf(rblkcipher.type, CRYPTO_MAX_ALG_NAME, "%s", "blkcipher");
+-	snprintf(rblkcipher.geniv, CRYPTO_MAX_ALG_NAME, "%s",
+-		 alg->cra_blkcipher.geniv ?: "<default>");
++	strncpy(rblkcipher.type, "blkcipher", sizeof(rblkcipher.type));
++	strncpy(rblkcipher.geniv, alg->cra_blkcipher.geniv ?: "<default>",
++		sizeof(rblkcipher.geniv));
+ 
+ 	rblkcipher.blocksize = alg->cra_blocksize;
+ 	rblkcipher.min_keysize = alg->cra_blkcipher.min_keysize;
+diff --git a/crypto/crypto_user.c b/crypto/crypto_user.c
+index 35d700a..f6d9baf 100644
+--- a/crypto/crypto_user.c
++++ b/crypto/crypto_user.c
+@@ -75,7 +75,7 @@ static int crypto_report_cipher(struct sk_buff *skb, struct crypto_alg *alg)
+ {
+ 	struct crypto_report_cipher rcipher;
+ 
+-	snprintf(rcipher.type, CRYPTO_MAX_ALG_NAME, "%s", "cipher");
++	strncpy(rcipher.type, "cipher", sizeof(rcipher.type));
+ 
+ 	rcipher.blocksize = alg->cra_blocksize;
+ 	rcipher.min_keysize = alg->cra_cipher.cia_min_keysize;
+@@ -94,8 +94,7 @@ static int crypto_report_comp(struct sk_buff *skb, struct crypto_alg *alg)
+ {
+ 	struct crypto_report_comp rcomp;
+ 
+-	snprintf(rcomp.type, CRYPTO_MAX_ALG_NAME, "%s", "compression");
+-
++	strncpy(rcomp.type, "compression", sizeof(rcomp.type));
+ 	if (nla_put(skb, CRYPTOCFGA_REPORT_COMPRESS,
+ 		    sizeof(struct crypto_report_comp), &rcomp))
+ 		goto nla_put_failure;
+@@ -108,12 +107,14 @@ nla_put_failure:
+ static int crypto_report_one(struct crypto_alg *alg,
+ 			     struct crypto_user_alg *ualg, struct sk_buff *skb)
+ {
+-	memcpy(&ualg->cru_name, &alg->cra_name, sizeof(ualg->cru_name));
+-	memcpy(&ualg->cru_driver_name, &alg->cra_driver_name,
+-	       sizeof(ualg->cru_driver_name));
+-	memcpy(&ualg->cru_module_name, module_name(alg->cra_module),
+-	       CRYPTO_MAX_ALG_NAME);
+-
++	strncpy(ualg->cru_name, alg->cra_name, sizeof(ualg->cru_name));
++	strncpy(ualg->cru_driver_name, alg->cra_driver_name,
++		sizeof(ualg->cru_driver_name));
++	strncpy(ualg->cru_module_name, module_name(alg->cra_module),
++		sizeof(ualg->cru_module_name));
++
++	ualg->cru_type = 0;
++	ualg->cru_mask = 0;
+ 	ualg->cru_flags = alg->cra_flags;
+ 	ualg->cru_refcnt = atomic_read(&alg->cra_refcnt);
+ 
+@@ -122,8 +123,7 @@ static int crypto_report_one(struct crypto_alg *alg,
+ 	if (alg->cra_flags & CRYPTO_ALG_LARVAL) {
+ 		struct crypto_report_larval rl;
+ 
+-		snprintf(rl.type, CRYPTO_MAX_ALG_NAME, "%s", "larval");
+-
++		strncpy(rl.type, "larval", sizeof(rl.type));
+ 		if (nla_put(skb, CRYPTOCFGA_REPORT_LARVAL,
+ 			    sizeof(struct crypto_report_larval), &rl))
+ 			goto nla_put_failure;
+diff --git a/crypto/pcompress.c b/crypto/pcompress.c
+index 04e083f..7140fe7 100644
+--- a/crypto/pcompress.c
++++ b/crypto/pcompress.c
+@@ -53,8 +53,7 @@ static int crypto_pcomp_report(struct sk_buff *skb, struct crypto_alg *alg)
+ {
+ 	struct crypto_report_comp rpcomp;
+ 
+-	snprintf(rpcomp.type, CRYPTO_MAX_ALG_NAME, "%s", "pcomp");
+-
++	strncpy(rpcomp.type, "pcomp", sizeof(rpcomp.type));
+ 	if (nla_put(skb, CRYPTOCFGA_REPORT_COMPRESS,
+ 		    sizeof(struct crypto_report_comp), &rpcomp))
+ 		goto nla_put_failure;
+diff --git a/crypto/rng.c b/crypto/rng.c
+index f3b7894..e0a25c2 100644
+--- a/crypto/rng.c
++++ b/crypto/rng.c
+@@ -65,7 +65,7 @@ static int crypto_rng_report(struct sk_buff *skb, struct crypto_alg *alg)
+ {
+ 	struct crypto_report_rng rrng;
+ 
+-	snprintf(rrng.type, CRYPTO_MAX_ALG_NAME, "%s", "rng");
++	strncpy(rrng.type, "rng", sizeof(rrng.type));
+ 
+ 	rrng.seedsize = alg->cra_rng.seedsize;
+ 
+diff --git a/crypto/shash.c b/crypto/shash.c
+index f426330f..929058a 100644
+--- a/crypto/shash.c
++++ b/crypto/shash.c
+@@ -530,7 +530,8 @@ static int crypto_shash_report(struct sk_buff *skb, struct crypto_alg *alg)
+ 	struct crypto_report_hash rhash;
+ 	struct shash_alg *salg = __crypto_shash_alg(alg);
+ 
+-	snprintf(rhash.type, CRYPTO_MAX_ALG_NAME, "%s", "shash");
++	strncpy(rhash.type, "shash", sizeof(rhash.type));
++
+ 	rhash.blocksize = alg->cra_blocksize;
+ 	rhash.digestsize = salg->digestsize;
+ 
+-- 
+1.8.1.2
+
diff --git a/kernel.spec b/kernel.spec
index fa33e72..8686d86 100644
--- a/kernel.spec
+++ b/kernel.spec
@@ -62,7 +62,7 @@ Summary: The Linux kernel
 # For non-released -rc kernels, this will be appended after the rcX and
 # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3"
 #
-%global baserelease 203
+%global baserelease 204
 %global fedora_build %{baserelease}
 
 # base_sublevel is the kernel version we're starting with and patching
@@ -758,6 +758,9 @@ Patch22263: 0001-drivers-crypto-nx-fix-init-race-alignmasks-and-GCM-b.patch
 #rhbz 917984
 Patch22264: efi-fixes-3.8.patch
 
+#rhbz 918512 918521
+Patch22265: crypto-user-fix-info-leaks-in-report-API.patch
+
 #rhbz 812111
 Patch24000: alps.patch
 
@@ -1474,6 +1477,9 @@ ApplyPatch 0001-drivers-crypto-nx-fix-init-race-alignmasks-and-GCM-b.patch
 #rhbz 917984
 ApplyPatch efi-fixes-3.8.patch
 
+#rhbz 918512 918521
+ApplyPatch crypto-user-fix-info-leaks-in-report-API.patch
+
 ApplyPatch userns-avoid-recursion-in-put_user_ns.patch
 
 
@@ -2335,6 +2341,9 @@ fi
 #                 ||----w |
 #                 ||     ||
 %changelog
+* Wed Mar 06 2013 Josh Boyer <jwboyer at redhat.com>
+- crypto: info leaks in report API (rhbz 918512 918521)
+
 * Tue Mar  5 2013 Peter Robinson <pbrobinson at fedoraproject.org>
 - Fix Beagle (omap), update vexpress
 


More information about the scm-commits mailing list