Commit 43937003 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security

Pull key fixes from James Morris:

 - fix a buffer overflow when displaying /proc/keys [CVE-2016-7042].

 - fix broken initialisation in the big_key implementation that can
   result in an oops.

 - make big_key depend on having a random number generator available in
   Kconfig.

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security:
  security/keys: make BIG_KEYS dependent on stdrng.
  KEYS: Sort out big_key initialisation
  KEYS: Fix short sprintf buffer in /proc/keys show function
parents 14970f20 31e6ec45
...@@ -41,7 +41,7 @@ config BIG_KEYS ...@@ -41,7 +41,7 @@ config BIG_KEYS
bool "Large payload keys" bool "Large payload keys"
depends on KEYS depends on KEYS
depends on TMPFS depends on TMPFS
select CRYPTO depends on (CRYPTO_ANSI_CPRNG = y || CRYPTO_DRBG = y)
select CRYPTO_AES select CRYPTO_AES
select CRYPTO_ECB select CRYPTO_ECB
select CRYPTO_RNG select CRYPTO_RNG
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
* 2 of the Licence, or (at your option) any later version. * 2 of the Licence, or (at your option) any later version.
*/ */
#define pr_fmt(fmt) "big_key: "fmt
#include <linux/init.h> #include <linux/init.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include <linux/file.h> #include <linux/file.h>
...@@ -341,44 +342,48 @@ long big_key_read(const struct key *key, char __user *buffer, size_t buflen) ...@@ -341,44 +342,48 @@ long big_key_read(const struct key *key, char __user *buffer, size_t buflen)
*/ */
static int __init big_key_init(void) static int __init big_key_init(void)
{ {
return register_key_type(&key_type_big_key); struct crypto_skcipher *cipher;
} struct crypto_rng *rng;
int ret;
/*
* Initialize big_key crypto and RNG algorithms
*/
static int __init big_key_crypto_init(void)
{
int ret = -EINVAL;
/* init RNG */ rng = crypto_alloc_rng(big_key_rng_name, 0, 0);
big_key_rng = crypto_alloc_rng(big_key_rng_name, 0, 0); if (IS_ERR(rng)) {
if (IS_ERR(big_key_rng)) { pr_err("Can't alloc rng: %ld\n", PTR_ERR(rng));
big_key_rng = NULL; return PTR_ERR(rng);
return -EFAULT;
} }
big_key_rng = rng;
/* seed RNG */ /* seed RNG */
ret = crypto_rng_reset(big_key_rng, NULL, crypto_rng_seedsize(big_key_rng)); ret = crypto_rng_reset(rng, NULL, crypto_rng_seedsize(rng));
if (ret) if (ret) {
goto error; pr_err("Can't reset rng: %d\n", ret);
goto error_rng;
}
/* init block cipher */ /* init block cipher */
big_key_skcipher = crypto_alloc_skcipher(big_key_alg_name, cipher = crypto_alloc_skcipher(big_key_alg_name, 0, CRYPTO_ALG_ASYNC);
0, CRYPTO_ALG_ASYNC); if (IS_ERR(cipher)) {
if (IS_ERR(big_key_skcipher)) { ret = PTR_ERR(cipher);
big_key_skcipher = NULL; pr_err("Can't alloc crypto: %d\n", ret);
ret = -EFAULT; goto error_rng;
goto error; }
big_key_skcipher = cipher;
ret = register_key_type(&key_type_big_key);
if (ret < 0) {
pr_err("Can't register type: %d\n", ret);
goto error_cipher;
} }
return 0; return 0;
error: error_cipher:
crypto_free_skcipher(big_key_skcipher);
error_rng:
crypto_free_rng(big_key_rng); crypto_free_rng(big_key_rng);
big_key_rng = NULL;
return ret; return ret;
} }
device_initcall(big_key_init); late_initcall(big_key_init);
late_initcall(big_key_crypto_init);
...@@ -181,7 +181,7 @@ static int proc_keys_show(struct seq_file *m, void *v) ...@@ -181,7 +181,7 @@ static int proc_keys_show(struct seq_file *m, void *v)
struct timespec now; struct timespec now;
unsigned long timo; unsigned long timo;
key_ref_t key_ref, skey_ref; key_ref_t key_ref, skey_ref;
char xbuf[12]; char xbuf[16];
int rc; int rc;
struct keyring_search_context ctx = { struct keyring_search_context ctx = {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment