Commit a6e08912 authored by Eric Biggers's avatar Eric Biggers Committed by Theodore Ts'o

fscrypto: don't use on-stack buffer for key derivation

With the new (in 4.9) option to use a virtually-mapped stack
(CONFIG_VMAP_STACK), stack buffers cannot be used as input/output for
the scatterlist crypto API because they may not be directly mappable to
struct page.  get_crypt_info() was using a stack buffer to hold the
output from the encryption operation used to derive the per-file key.
Fix it by using a heap buffer.

This bug could most easily be observed in a CONFIG_DEBUG_SG kernel
because this allowed the BUG in sg_set_buf() to be triggered.

Cc: stable@vger.kernel.org
Signed-off-by: default avatarEric Biggers <ebiggers@google.com>
Signed-off-by: default avatarTheodore Ts'o <tytso@mit.edu>
parent 08ae877f
...@@ -185,7 +185,7 @@ int get_crypt_info(struct inode *inode) ...@@ -185,7 +185,7 @@ int get_crypt_info(struct inode *inode)
struct crypto_skcipher *ctfm; struct crypto_skcipher *ctfm;
const char *cipher_str; const char *cipher_str;
int keysize; int keysize;
u8 raw_key[FS_MAX_KEY_SIZE]; u8 *raw_key = NULL;
int res; int res;
res = fscrypt_initialize(); res = fscrypt_initialize();
...@@ -238,6 +238,15 @@ int get_crypt_info(struct inode *inode) ...@@ -238,6 +238,15 @@ int get_crypt_info(struct inode *inode)
if (res) if (res)
goto out; goto out;
/*
* This cannot be a stack buffer because it is passed to the scatterlist
* crypto API as part of key derivation.
*/
res = -ENOMEM;
raw_key = kmalloc(FS_MAX_KEY_SIZE, GFP_NOFS);
if (!raw_key)
goto out;
if (fscrypt_dummy_context_enabled(inode)) { if (fscrypt_dummy_context_enabled(inode)) {
memset(raw_key, 0x42, FS_AES_256_XTS_KEY_SIZE); memset(raw_key, 0x42, FS_AES_256_XTS_KEY_SIZE);
goto got_key; goto got_key;
...@@ -276,7 +285,8 @@ int get_crypt_info(struct inode *inode) ...@@ -276,7 +285,8 @@ int get_crypt_info(struct inode *inode)
if (res) if (res)
goto out; goto out;
memzero_explicit(raw_key, sizeof(raw_key)); kzfree(raw_key);
raw_key = NULL;
if (cmpxchg(&inode->i_crypt_info, NULL, crypt_info) != NULL) { if (cmpxchg(&inode->i_crypt_info, NULL, crypt_info) != NULL) {
put_crypt_info(crypt_info); put_crypt_info(crypt_info);
goto retry; goto retry;
...@@ -287,7 +297,7 @@ int get_crypt_info(struct inode *inode) ...@@ -287,7 +297,7 @@ int get_crypt_info(struct inode *inode)
if (res == -ENOKEY) if (res == -ENOKEY)
res = 0; res = 0;
put_crypt_info(crypt_info); put_crypt_info(crypt_info);
memzero_explicit(raw_key, sizeof(raw_key)); kzfree(raw_key);
return res; return res;
} }
......
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