Commit ac97b9f9 authored by Michael Halcrow's avatar Michael Halcrow Committed by Linus Torvalds

eCryptfs: Allocate up to two scatterlists for crypto ops on keys

I have received some reports of out-of-memory errors on some older AMD
architectures.  These errors are what I would expect to see if
crypt_stat->key were split between two separate pages.  eCryptfs should
not assume that any of the memory sent through virt_to_scatterlist() is
all contained in a single page, and so this patch allocates two
scatterlist structs instead of one when processing keys.  I have received
confirmation from one person affected by this bug that this patch resolves
the issue for him, and so I am submitting it for inclusion in a future
stable release.

Note that virt_to_scatterlist() runs sg_init_table() on the scatterlist
structs passed to it, so the calls to sg_init_table() in
decrypt_passphrase_encrypted_session_key() are redundant.
Signed-off-by: default avatarMichael Halcrow <mhalcrow@us.ibm.com>
Reported-by: default avatarPaulo J. S. Silva <pjssilva@ime.usp.br>
Cc: "Leon Woestenberg" <leon.woestenberg@gmail.com>
Cc: Tim Gardner <tim.gardner@canonical.com>
Cc: <stable@kernel.org>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 3b45d638
...@@ -1037,17 +1037,14 @@ static int ...@@ -1037,17 +1037,14 @@ static int
decrypt_passphrase_encrypted_session_key(struct ecryptfs_auth_tok *auth_tok, decrypt_passphrase_encrypted_session_key(struct ecryptfs_auth_tok *auth_tok,
struct ecryptfs_crypt_stat *crypt_stat) struct ecryptfs_crypt_stat *crypt_stat)
{ {
struct scatterlist dst_sg; struct scatterlist dst_sg[2];
struct scatterlist src_sg; struct scatterlist src_sg[2];
struct mutex *tfm_mutex; struct mutex *tfm_mutex;
struct blkcipher_desc desc = { struct blkcipher_desc desc = {
.flags = CRYPTO_TFM_REQ_MAY_SLEEP .flags = CRYPTO_TFM_REQ_MAY_SLEEP
}; };
int rc = 0; int rc = 0;
sg_init_table(&dst_sg, 1);
sg_init_table(&src_sg, 1);
if (unlikely(ecryptfs_verbosity > 0)) { if (unlikely(ecryptfs_verbosity > 0)) {
ecryptfs_printk( ecryptfs_printk(
KERN_DEBUG, "Session key encryption key (size [%d]):\n", KERN_DEBUG, "Session key encryption key (size [%d]):\n",
...@@ -1066,8 +1063,8 @@ decrypt_passphrase_encrypted_session_key(struct ecryptfs_auth_tok *auth_tok, ...@@ -1066,8 +1063,8 @@ decrypt_passphrase_encrypted_session_key(struct ecryptfs_auth_tok *auth_tok,
} }
rc = virt_to_scatterlist(auth_tok->session_key.encrypted_key, rc = virt_to_scatterlist(auth_tok->session_key.encrypted_key,
auth_tok->session_key.encrypted_key_size, auth_tok->session_key.encrypted_key_size,
&src_sg, 1); src_sg, 2);
if (rc != 1) { if (rc < 1 || rc > 2) {
printk(KERN_ERR "Internal error whilst attempting to convert " printk(KERN_ERR "Internal error whilst attempting to convert "
"auth_tok->session_key.encrypted_key to scatterlist; " "auth_tok->session_key.encrypted_key to scatterlist; "
"expected rc = 1; got rc = [%d]. " "expected rc = 1; got rc = [%d]. "
...@@ -1079,8 +1076,8 @@ decrypt_passphrase_encrypted_session_key(struct ecryptfs_auth_tok *auth_tok, ...@@ -1079,8 +1076,8 @@ decrypt_passphrase_encrypted_session_key(struct ecryptfs_auth_tok *auth_tok,
auth_tok->session_key.encrypted_key_size; auth_tok->session_key.encrypted_key_size;
rc = virt_to_scatterlist(auth_tok->session_key.decrypted_key, rc = virt_to_scatterlist(auth_tok->session_key.decrypted_key,
auth_tok->session_key.decrypted_key_size, auth_tok->session_key.decrypted_key_size,
&dst_sg, 1); dst_sg, 2);
if (rc != 1) { if (rc < 1 || rc > 2) {
printk(KERN_ERR "Internal error whilst attempting to convert " printk(KERN_ERR "Internal error whilst attempting to convert "
"auth_tok->session_key.decrypted_key to scatterlist; " "auth_tok->session_key.decrypted_key to scatterlist; "
"expected rc = 1; got rc = [%d]\n", rc); "expected rc = 1; got rc = [%d]\n", rc);
...@@ -1096,7 +1093,7 @@ decrypt_passphrase_encrypted_session_key(struct ecryptfs_auth_tok *auth_tok, ...@@ -1096,7 +1093,7 @@ decrypt_passphrase_encrypted_session_key(struct ecryptfs_auth_tok *auth_tok,
rc = -EINVAL; rc = -EINVAL;
goto out; goto out;
} }
rc = crypto_blkcipher_decrypt(&desc, &dst_sg, &src_sg, rc = crypto_blkcipher_decrypt(&desc, dst_sg, src_sg,
auth_tok->session_key.encrypted_key_size); auth_tok->session_key.encrypted_key_size);
mutex_unlock(tfm_mutex); mutex_unlock(tfm_mutex);
if (unlikely(rc)) { if (unlikely(rc)) {
...@@ -1539,8 +1536,8 @@ write_tag_3_packet(char *dest, size_t *remaining_bytes, ...@@ -1539,8 +1536,8 @@ write_tag_3_packet(char *dest, size_t *remaining_bytes,
size_t i; size_t i;
size_t encrypted_session_key_valid = 0; size_t encrypted_session_key_valid = 0;
char session_key_encryption_key[ECRYPTFS_MAX_KEY_BYTES]; char session_key_encryption_key[ECRYPTFS_MAX_KEY_BYTES];
struct scatterlist dst_sg; struct scatterlist dst_sg[2];
struct scatterlist src_sg; struct scatterlist src_sg[2];
struct mutex *tfm_mutex = NULL; struct mutex *tfm_mutex = NULL;
u8 cipher_code; u8 cipher_code;
size_t packet_size_length; size_t packet_size_length;
...@@ -1619,8 +1616,8 @@ write_tag_3_packet(char *dest, size_t *remaining_bytes, ...@@ -1619,8 +1616,8 @@ write_tag_3_packet(char *dest, size_t *remaining_bytes,
ecryptfs_dump_hex(session_key_encryption_key, 16); ecryptfs_dump_hex(session_key_encryption_key, 16);
} }
rc = virt_to_scatterlist(crypt_stat->key, key_rec->enc_key_size, rc = virt_to_scatterlist(crypt_stat->key, key_rec->enc_key_size,
&src_sg, 1); src_sg, 2);
if (rc != 1) { if (rc < 1 || rc > 2) {
ecryptfs_printk(KERN_ERR, "Error generating scatterlist " ecryptfs_printk(KERN_ERR, "Error generating scatterlist "
"for crypt_stat session key; expected rc = 1; " "for crypt_stat session key; expected rc = 1; "
"got rc = [%d]. key_rec->enc_key_size = [%d]\n", "got rc = [%d]. key_rec->enc_key_size = [%d]\n",
...@@ -1629,8 +1626,8 @@ write_tag_3_packet(char *dest, size_t *remaining_bytes, ...@@ -1629,8 +1626,8 @@ write_tag_3_packet(char *dest, size_t *remaining_bytes,
goto out; goto out;
} }
rc = virt_to_scatterlist(key_rec->enc_key, key_rec->enc_key_size, rc = virt_to_scatterlist(key_rec->enc_key, key_rec->enc_key_size,
&dst_sg, 1); dst_sg, 2);
if (rc != 1) { if (rc < 1 || rc > 2) {
ecryptfs_printk(KERN_ERR, "Error generating scatterlist " ecryptfs_printk(KERN_ERR, "Error generating scatterlist "
"for crypt_stat encrypted session key; " "for crypt_stat encrypted session key; "
"expected rc = 1; got rc = [%d]. " "expected rc = 1; got rc = [%d]. "
...@@ -1651,7 +1648,7 @@ write_tag_3_packet(char *dest, size_t *remaining_bytes, ...@@ -1651,7 +1648,7 @@ write_tag_3_packet(char *dest, size_t *remaining_bytes,
rc = 0; rc = 0;
ecryptfs_printk(KERN_DEBUG, "Encrypting [%d] bytes of the key\n", ecryptfs_printk(KERN_DEBUG, "Encrypting [%d] bytes of the key\n",
crypt_stat->key_size); crypt_stat->key_size);
rc = crypto_blkcipher_encrypt(&desc, &dst_sg, &src_sg, rc = crypto_blkcipher_encrypt(&desc, dst_sg, src_sg,
(*key_rec).enc_key_size); (*key_rec).enc_key_size);
mutex_unlock(tfm_mutex); mutex_unlock(tfm_mutex);
if (rc) { if (rc) {
......
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