eCryptfs: Allow 2 scatterlist entries for encrypted filenames
Tyler Hicks [Tue, 17 May 2011 05:50:33 +0000 (00:50 -0500)]
The buffers allocated while encrypting and decrypting long filenames can
sometimes straddle two pages. In this situation, virt_to_scatterlist()
will return -ENOMEM, causing the operation to fail and the user will get
scary error messages in their logs:

kernel: ecryptfs_write_tag_70_packet: Internal error whilst attempting
to convert filename memory to scatterlist; expected rc = 1; got rc =
[-12]. block_aligned_filename_size = [272]
kernel: ecryptfs_encrypt_filename: Error attempting to generate tag 70
packet; rc = [-12]
kernel: ecryptfs_encrypt_and_encode_filename: Error attempting to
encrypt filename; rc = [-12]
kernel: ecryptfs_lookup: Error attempting to encrypt and encode
filename; rc = [-12]

The solution is to allow up to 2 scatterlist entries to be used.

Signed-off-by: Tyler Hicks <tyhicks@linux.vnet.ibm.com>
Cc: <stable@kernel.org>

fs/ecryptfs/keystore.c

index 03e609c..27a7fef 100644 (file)
@@ -599,8 +599,8 @@ struct ecryptfs_write_tag_70_packet_silly_stack {
        struct mutex *tfm_mutex;
        char *block_aligned_filename;
        struct ecryptfs_auth_tok *auth_tok;
-       struct scatterlist src_sg;
-       struct scatterlist dst_sg;
+       struct scatterlist src_sg[2];
+       struct scatterlist dst_sg[2];
        struct blkcipher_desc desc;
        char iv[ECRYPTFS_MAX_IV_BYTES];
        char hash[ECRYPTFS_TAG_70_DIGEST_SIZE];
@@ -816,23 +816,21 @@ ecryptfs_write_tag_70_packet(char *dest, size_t *remaining_bytes,
        memcpy(&s->block_aligned_filename[s->num_rand_bytes], filename,
               filename_size);
        rc = virt_to_scatterlist(s->block_aligned_filename,
-                                s->block_aligned_filename_size, &s->src_sg, 1);
-       if (rc != 1) {
+                                s->block_aligned_filename_size, s->src_sg, 2);
+       if (rc < 1) {
                printk(KERN_ERR "%s: Internal error whilst attempting to "
-                      "convert filename memory to scatterlist; "
-                      "expected rc = 1; got rc = [%d]. "
+                      "convert filename memory to scatterlist; rc = [%d]. "
                       "block_aligned_filename_size = [%zd]\n", __func__, rc,
                       s->block_aligned_filename_size);
                goto out_release_free_unlock;
        }
        rc = virt_to_scatterlist(&dest[s->i], s->block_aligned_filename_size,
-                                &s->dst_sg, 1);
-       if (rc != 1) {
+                                s->dst_sg, 2);
+       if (rc < 1) {
                printk(KERN_ERR "%s: Internal error whilst attempting to "
                       "convert encrypted filename memory to scatterlist; "
-                      "expected rc = 1; got rc = [%d]. "
-                      "block_aligned_filename_size = [%zd]\n", __func__, rc,
-                      s->block_aligned_filename_size);
+                      "rc = [%d]. block_aligned_filename_size = [%zd]\n",
+                      __func__, rc, s->block_aligned_filename_size);
                goto out_release_free_unlock;
        }
        /* The characters in the first block effectively do the job
@@ -855,7 +853,7 @@ ecryptfs_write_tag_70_packet(char *dest, size_t *remaining_bytes,
                       mount_crypt_stat->global_default_fn_cipher_key_bytes);
                goto out_release_free_unlock;
        }
-       rc = crypto_blkcipher_encrypt_iv(&s->desc, &s->dst_sg, &s->src_sg,
+       rc = crypto_blkcipher_encrypt_iv(&s->desc, s->dst_sg, s->src_sg,
                                         s->block_aligned_filename_size);
        if (rc) {
                printk(KERN_ERR "%s: Error attempting to encrypt filename; "
@@ -891,8 +889,8 @@ struct ecryptfs_parse_tag_70_packet_silly_stack {
        struct mutex *tfm_mutex;
        char *decrypted_filename;
        struct ecryptfs_auth_tok *auth_tok;
-       struct scatterlist src_sg;
-       struct scatterlist dst_sg;
+       struct scatterlist src_sg[2];
+       struct scatterlist dst_sg[2];
        struct blkcipher_desc desc;
        char fnek_sig_hex[ECRYPTFS_SIG_SIZE_HEX + 1];
        char iv[ECRYPTFS_MAX_IV_BYTES];
@@ -1008,13 +1006,12 @@ ecryptfs_parse_tag_70_packet(char **filename, size_t *filename_size,
        }
        mutex_lock(s->tfm_mutex);
        rc = virt_to_scatterlist(&data[(*packet_size)],
-                                s->block_aligned_filename_size, &s->src_sg, 1);
-       if (rc != 1) {
+                                s->block_aligned_filename_size, s->src_sg, 2);
+       if (rc < 1) {
                printk(KERN_ERR "%s: Internal error whilst attempting to "
                       "convert encrypted filename memory to scatterlist; "
-                      "expected rc = 1; got rc = [%d]. "
-                      "block_aligned_filename_size = [%zd]\n", __func__, rc,
-                      s->block_aligned_filename_size);
+                      "rc = [%d]. block_aligned_filename_size = [%zd]\n",
+                      __func__, rc, s->block_aligned_filename_size);
                goto out_unlock;
        }
        (*packet_size) += s->block_aligned_filename_size;
@@ -1028,13 +1025,12 @@ ecryptfs_parse_tag_70_packet(char **filename, size_t *filename_size,
                goto out_unlock;
        }
        rc = virt_to_scatterlist(s->decrypted_filename,
-                                s->block_aligned_filename_size, &s->dst_sg, 1);
-       if (rc != 1) {
+                                s->block_aligned_filename_size, s->dst_sg, 2);
+       if (rc < 1) {
                printk(KERN_ERR "%s: Internal error whilst attempting to "
                       "convert decrypted filename memory to scatterlist; "
-                      "expected rc = 1; got rc = [%d]. "
-                      "block_aligned_filename_size = [%zd]\n", __func__, rc,
-                      s->block_aligned_filename_size);
+                      "rc = [%d]. block_aligned_filename_size = [%zd]\n",
+                      __func__, rc, s->block_aligned_filename_size);
                goto out_free_unlock;
        }
        /* The characters in the first block effectively do the job of
@@ -1065,7 +1061,7 @@ ecryptfs_parse_tag_70_packet(char **filename, size_t *filename_size,
                       mount_crypt_stat->global_default_fn_cipher_key_bytes);
                goto out_free_unlock;
        }
-       rc = crypto_blkcipher_decrypt_iv(&s->desc, &s->dst_sg, &s->src_sg,
+       rc = crypto_blkcipher_decrypt_iv(&s->desc, s->dst_sg, s->src_sg,
                                         s->block_aligned_filename_size);
        if (rc) {
                printk(KERN_ERR "%s: Error attempting to decrypt filename; "