From c03b60fe04081fb220366d516ca25575916be3a3 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 6 Mar 2013 08:53:40 -0500 Subject: [PATCH] crypto: info leaks in report API (rhbz 918512 918521) --- ...to-user-fix-info-leaks-in-report-API.patch | 223 ++++++++++++++++++ kernel.spec | 11 +- 2 files changed, 233 insertions(+), 1 deletion(-) create mode 100644 crypto-user-fix-info-leaks-in-report-API.patch 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 000000000..1b64e1844 --- /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 +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 +Cc: Steffen Klassert +Signed-off-by: Herbert Xu +--- + 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 ?: ""); ++ strncpy(rblkcipher.type, "ablkcipher", sizeof(rblkcipher.type)); ++ strncpy(rblkcipher.geniv, alg->cra_ablkcipher.geniv ?: "", ++ 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 ?: ""); ++ strncpy(rblkcipher.type, "givcipher", sizeof(rblkcipher.type)); ++ strncpy(rblkcipher.geniv, alg->cra_ablkcipher.geniv ?: "", ++ 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 ?: ""); ++ strncpy(raead.type, "aead", sizeof(raead.type)); ++ strncpy(raead.geniv, aead->geniv ?: "", 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 ?: ""); ++ strncpy(rblkcipher.type, "blkcipher", sizeof(rblkcipher.type)); ++ strncpy(rblkcipher.geniv, alg->cra_blkcipher.geniv ?: "", ++ 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 fa33e72e4..8686d86cd 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 +- crypto: info leaks in report API (rhbz 918512 918521) + * Tue Mar 5 2013 Peter Robinson - Fix Beagle (omap), update vexpress