]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
Merge tag 'ecryptfs-3.11-rc1-cleanup' of git://git.kernel.org/pub/scm/linux/kernel...
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 11 Jul 2013 17:20:18 +0000 (10:20 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 11 Jul 2013 17:20:18 +0000 (10:20 -0700)
Pull eCryptfs updates from Tyler Hicks:
 "Code cleanups and improved buffer handling during page crypto
  operations:
   - Remove redundant code by merging some encrypt and decrypt functions
   - Get rid of a helper page allocation during page decryption by using
     in-place decryption
   - Better use of entire pages during page crypto operations
   - Several code cleanups"

* tag 'ecryptfs-3.11-rc1-cleanup' of git://git.kernel.org/pub/scm/linux/kernel/git/tyhicks/ecryptfs:
  Use ecryptfs_dentry_to_lower_path in a couple of places
  eCryptfs: Make extent and scatterlist crypt function parameters similar
  eCryptfs: Collapse crypt_page_offset() into crypt_extent()
  eCryptfs: Merge ecryptfs_encrypt_extent() and ecryptfs_decrypt_extent()
  eCryptfs: Combine page_offset crypto functions
  eCryptfs: Combine encrypt_scatterlist() and decrypt_scatterlist()
  eCryptfs: Decrypt pages in-place
  eCryptfs: Accept one offset parameter in page offset crypto functions
  eCryptfs: Simplify lower file offset calculation
  eCryptfs: Read/write entire page during page IO
  eCryptfs: Use entire helper page during page crypto operations
  eCryptfs: Cocci spatch "memdup.spatch"

fs/ecryptfs/crypto.c
fs/ecryptfs/file.c
fs/ecryptfs/main.c
fs/ecryptfs/messaging.c

index cfa109a4d5a21ac6f784f1a4e8a16b534c9e8d0d..d10757635b9c9360288e18217b28de298fc48407 100644 (file)
 #include <asm/unaligned.h>
 #include "ecryptfs_kernel.h"
 
-static int
-ecryptfs_decrypt_page_offset(struct ecryptfs_crypt_stat *crypt_stat,
-                            struct page *dst_page, int dst_offset,
-                            struct page *src_page, int src_offset, int size,
-                            unsigned char *iv);
-static int
-ecryptfs_encrypt_page_offset(struct ecryptfs_crypt_stat *crypt_stat,
-                            struct page *dst_page, int dst_offset,
-                            struct page *src_page, int src_offset, int size,
-                            unsigned char *iv);
+#define DECRYPT                0
+#define ENCRYPT                1
 
 /**
  * ecryptfs_to_hex
@@ -336,19 +328,20 @@ static void extent_crypt_complete(struct crypto_async_request *req, int rc)
 }
 
 /**
- * encrypt_scatterlist
+ * crypt_scatterlist
  * @crypt_stat: Pointer to the crypt_stat struct to initialize.
- * @dest_sg: Destination of encrypted data
- * @src_sg: Data to be encrypted
- * @size: Length of data to be encrypted
- * @iv: iv to use during encryption
+ * @dst_sg: Destination of the data after performing the crypto operation
+ * @src_sg: Data to be encrypted or decrypted
+ * @size: Length of data
+ * @iv: IV to use
+ * @op: ENCRYPT or DECRYPT to indicate the desired operation
  *
- * Returns the number of bytes encrypted; negative value on error
+ * Returns the number of bytes encrypted or decrypted; negative value on error
  */
-static int encrypt_scatterlist(struct ecryptfs_crypt_stat *crypt_stat,
-                              struct scatterlist *dest_sg,
-                              struct scatterlist *src_sg, int size,
-                              unsigned char *iv)
+static int crypt_scatterlist(struct ecryptfs_crypt_stat *crypt_stat,
+                            struct scatterlist *dst_sg,
+                            struct scatterlist *src_sg, int size,
+                            unsigned char *iv, int op)
 {
        struct ablkcipher_request *req = NULL;
        struct extent_crypt_result ecr;
@@ -391,9 +384,9 @@ static int encrypt_scatterlist(struct ecryptfs_crypt_stat *crypt_stat,
                crypt_stat->flags |= ECRYPTFS_KEY_SET;
        }
        mutex_unlock(&crypt_stat->cs_tfm_mutex);
-       ecryptfs_printk(KERN_DEBUG, "Encrypting [%d] bytes.\n", size);
-       ablkcipher_request_set_crypt(req, src_sg, dest_sg, size, iv);
-       rc = crypto_ablkcipher_encrypt(req);
+       ablkcipher_request_set_crypt(req, src_sg, dst_sg, size, iv);
+       rc = op == ENCRYPT ? crypto_ablkcipher_encrypt(req) :
+                            crypto_ablkcipher_decrypt(req);
        if (rc == -EINPROGRESS || rc == -EBUSY) {
                struct extent_crypt_result *ecr = req->base.data;
 
@@ -407,41 +400,43 @@ out:
 }
 
 /**
- * ecryptfs_lower_offset_for_extent
+ * lower_offset_for_page
  *
  * Convert an eCryptfs page index into a lower byte offset
  */
-static void ecryptfs_lower_offset_for_extent(loff_t *offset, loff_t extent_num,
-                                            struct ecryptfs_crypt_stat *crypt_stat)
+static loff_t lower_offset_for_page(struct ecryptfs_crypt_stat *crypt_stat,
+                                   struct page *page)
 {
-       (*offset) = ecryptfs_lower_header_size(crypt_stat)
-                   + (crypt_stat->extent_size * extent_num);
+       return ecryptfs_lower_header_size(crypt_stat) +
+              (page->index << PAGE_CACHE_SHIFT);
 }
 
 /**
- * ecryptfs_encrypt_extent
- * @enc_extent_page: Allocated page into which to encrypt the data in
- *                   @page
+ * crypt_extent
  * @crypt_stat: crypt_stat containing cryptographic context for the
  *              encryption operation
- * @page: Page containing plaintext data extent to encrypt
+ * @dst_page: The page to write the result into
+ * @src_page: The page to read from
  * @extent_offset: Page extent offset for use in generating IV
+ * @op: ENCRYPT or DECRYPT to indicate the desired operation
  *
- * Encrypts one extent of data.
+ * Encrypts or decrypts one extent of data.
  *
  * Return zero on success; non-zero otherwise
  */
-static int ecryptfs_encrypt_extent(struct page *enc_extent_page,
-                                  struct ecryptfs_crypt_stat *crypt_stat,
-                                  struct page *page,
-                                  unsigned long extent_offset)
+static int crypt_extent(struct ecryptfs_crypt_stat *crypt_stat,
+                       struct page *dst_page,
+                       struct page *src_page,
+                       unsigned long extent_offset, int op)
 {
+       pgoff_t page_index = op == ENCRYPT ? src_page->index : dst_page->index;
        loff_t extent_base;
        char extent_iv[ECRYPTFS_MAX_IV_BYTES];
+       struct scatterlist src_sg, dst_sg;
+       size_t extent_size = crypt_stat->extent_size;
        int rc;
 
-       extent_base = (((loff_t)page->index)
-                      * (PAGE_CACHE_SIZE / crypt_stat->extent_size));
+       extent_base = (((loff_t)page_index) * (PAGE_CACHE_SIZE / extent_size));
        rc = ecryptfs_derive_iv(extent_iv, crypt_stat,
                                (extent_base + extent_offset));
        if (rc) {
@@ -450,15 +445,21 @@ static int ecryptfs_encrypt_extent(struct page *enc_extent_page,
                        (unsigned long long)(extent_base + extent_offset), rc);
                goto out;
        }
-       rc = ecryptfs_encrypt_page_offset(crypt_stat, enc_extent_page, 0,
-                                         page, (extent_offset
-                                                * crypt_stat->extent_size),
-                                         crypt_stat->extent_size, extent_iv);
+
+       sg_init_table(&src_sg, 1);
+       sg_init_table(&dst_sg, 1);
+
+       sg_set_page(&src_sg, src_page, extent_size,
+                   extent_offset * extent_size);
+       sg_set_page(&dst_sg, dst_page, extent_size,
+                   extent_offset * extent_size);
+
+       rc = crypt_scatterlist(crypt_stat, &dst_sg, &src_sg, extent_size,
+                              extent_iv, op);
        if (rc < 0) {
-               printk(KERN_ERR "%s: Error attempting to encrypt page with "
-                      "page->index = [%ld], extent_offset = [%ld]; "
-                      "rc = [%d]\n", __func__, page->index, extent_offset,
-                      rc);
+               printk(KERN_ERR "%s: Error attempting to crypt page with "
+                      "page_index = [%ld], extent_offset = [%ld]; "
+                      "rc = [%d]\n", __func__, page_index, extent_offset, rc);
                goto out;
        }
        rc = 0;
@@ -489,6 +490,7 @@ int ecryptfs_encrypt_page(struct page *page)
        char *enc_extent_virt;
        struct page *enc_extent_page = NULL;
        loff_t extent_offset;
+       loff_t lower_offset;
        int rc = 0;
 
        ecryptfs_inode = page->mapping->host;
@@ -502,75 +504,35 @@ int ecryptfs_encrypt_page(struct page *page)
                                "encrypted extent\n");
                goto out;
        }
-       enc_extent_virt = kmap(enc_extent_page);
+
        for (extent_offset = 0;
             extent_offset < (PAGE_CACHE_SIZE / crypt_stat->extent_size);
             extent_offset++) {
-               loff_t offset;
-
-               rc = ecryptfs_encrypt_extent(enc_extent_page, crypt_stat, page,
-                                            extent_offset);
+               rc = crypt_extent(crypt_stat, enc_extent_page, page,
+                                 extent_offset, ENCRYPT);
                if (rc) {
                        printk(KERN_ERR "%s: Error encrypting extent; "
                               "rc = [%d]\n", __func__, rc);
                        goto out;
                }
-               ecryptfs_lower_offset_for_extent(
-                       &offset, ((((loff_t)page->index)
-                                  * (PAGE_CACHE_SIZE
-                                     / crypt_stat->extent_size))
-                                 + extent_offset), crypt_stat);
-               rc = ecryptfs_write_lower(ecryptfs_inode, enc_extent_virt,
-                                         offset, crypt_stat->extent_size);
-               if (rc < 0) {
-                       ecryptfs_printk(KERN_ERR, "Error attempting "
-                                       "to write lower page; rc = [%d]"
-                                       "\n", rc);
-                       goto out;
-               }
-       }
-       rc = 0;
-out:
-       if (enc_extent_page) {
-               kunmap(enc_extent_page);
-               __free_page(enc_extent_page);
        }
-       return rc;
-}
 
-static int ecryptfs_decrypt_extent(struct page *page,
-                                  struct ecryptfs_crypt_stat *crypt_stat,
-                                  struct page *enc_extent_page,
-                                  unsigned long extent_offset)
-{
-       loff_t extent_base;
-       char extent_iv[ECRYPTFS_MAX_IV_BYTES];
-       int rc;
-
-       extent_base = (((loff_t)page->index)
-                      * (PAGE_CACHE_SIZE / crypt_stat->extent_size));
-       rc = ecryptfs_derive_iv(extent_iv, crypt_stat,
-                               (extent_base + extent_offset));
-       if (rc) {
-               ecryptfs_printk(KERN_ERR, "Error attempting to derive IV for "
-                       "extent [0x%.16llx]; rc = [%d]\n",
-                       (unsigned long long)(extent_base + extent_offset), rc);
-               goto out;
-       }
-       rc = ecryptfs_decrypt_page_offset(crypt_stat, page,
-                                         (extent_offset
-                                          * crypt_stat->extent_size),
-                                         enc_extent_page, 0,
-                                         crypt_stat->extent_size, extent_iv);
+       lower_offset = lower_offset_for_page(crypt_stat, page);
+       enc_extent_virt = kmap(enc_extent_page);
+       rc = ecryptfs_write_lower(ecryptfs_inode, enc_extent_virt, lower_offset,
+                                 PAGE_CACHE_SIZE);
+       kunmap(enc_extent_page);
        if (rc < 0) {
-               printk(KERN_ERR "%s: Error attempting to decrypt to page with "
-                      "page->index = [%ld], extent_offset = [%ld]; "
-                      "rc = [%d]\n", __func__, page->index, extent_offset,
-                      rc);
+               ecryptfs_printk(KERN_ERR,
+                       "Error attempting to write lower page; rc = [%d]\n",
+                       rc);
                goto out;
        }
        rc = 0;
 out:
+       if (enc_extent_page) {
+               __free_page(enc_extent_page);
+       }
        return rc;
 }
 
@@ -594,43 +556,33 @@ int ecryptfs_decrypt_page(struct page *page)
 {
        struct inode *ecryptfs_inode;
        struct ecryptfs_crypt_stat *crypt_stat;
-       char *enc_extent_virt;
-       struct page *enc_extent_page = NULL;
+       char *page_virt;
        unsigned long extent_offset;
+       loff_t lower_offset;
        int rc = 0;
 
        ecryptfs_inode = page->mapping->host;
        crypt_stat =
                &(ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat);
        BUG_ON(!(crypt_stat->flags & ECRYPTFS_ENCRYPTED));
-       enc_extent_page = alloc_page(GFP_USER);
-       if (!enc_extent_page) {
-               rc = -ENOMEM;
-               ecryptfs_printk(KERN_ERR, "Error allocating memory for "
-                               "encrypted extent\n");
+
+       lower_offset = lower_offset_for_page(crypt_stat, page);
+       page_virt = kmap(page);
+       rc = ecryptfs_read_lower(page_virt, lower_offset, PAGE_CACHE_SIZE,
+                                ecryptfs_inode);
+       kunmap(page);
+       if (rc < 0) {
+               ecryptfs_printk(KERN_ERR,
+                       "Error attempting to read lower page; rc = [%d]\n",
+                       rc);
                goto out;
        }
-       enc_extent_virt = kmap(enc_extent_page);
+
        for (extent_offset = 0;
             extent_offset < (PAGE_CACHE_SIZE / crypt_stat->extent_size);
             extent_offset++) {
-               loff_t offset;
-
-               ecryptfs_lower_offset_for_extent(
-                       &offset, ((page->index * (PAGE_CACHE_SIZE
-                                                 / crypt_stat->extent_size))
-                                 + extent_offset), crypt_stat);
-               rc = ecryptfs_read_lower(enc_extent_virt, offset,
-                                        crypt_stat->extent_size,
-                                        ecryptfs_inode);
-               if (rc < 0) {
-                       ecryptfs_printk(KERN_ERR, "Error attempting "
-                                       "to read lower page; rc = [%d]"
-                                       "\n", rc);
-                       goto out;
-               }
-               rc = ecryptfs_decrypt_extent(page, crypt_stat, enc_extent_page,
-                                            extent_offset);
+               rc = crypt_extent(crypt_stat, page, page,
+                                 extent_offset, DECRYPT);
                if (rc) {
                        printk(KERN_ERR "%s: Error encrypting extent; "
                               "rc = [%d]\n", __func__, rc);
@@ -638,140 +590,7 @@ int ecryptfs_decrypt_page(struct page *page)
                }
        }
 out:
-       if (enc_extent_page) {
-               kunmap(enc_extent_page);
-               __free_page(enc_extent_page);
-       }
-       return rc;
-}
-
-/**
- * decrypt_scatterlist
- * @crypt_stat: Cryptographic context
- * @dest_sg: The destination scatterlist to decrypt into
- * @src_sg: The source scatterlist to decrypt from
- * @size: The number of bytes to decrypt
- * @iv: The initialization vector to use for the decryption
- *
- * Returns the number of bytes decrypted; negative value on error
- */
-static int decrypt_scatterlist(struct ecryptfs_crypt_stat *crypt_stat,
-                              struct scatterlist *dest_sg,
-                              struct scatterlist *src_sg, int size,
-                              unsigned char *iv)
-{
-       struct ablkcipher_request *req = NULL;
-       struct extent_crypt_result ecr;
-       int rc = 0;
-
-       BUG_ON(!crypt_stat || !crypt_stat->tfm
-              || !(crypt_stat->flags & ECRYPTFS_STRUCT_INITIALIZED));
-       if (unlikely(ecryptfs_verbosity > 0)) {
-               ecryptfs_printk(KERN_DEBUG, "Key size [%zd]; key:\n",
-                               crypt_stat->key_size);
-               ecryptfs_dump_hex(crypt_stat->key,
-                                 crypt_stat->key_size);
-       }
-
-       init_completion(&ecr.completion);
-
-       mutex_lock(&crypt_stat->cs_tfm_mutex);
-       req = ablkcipher_request_alloc(crypt_stat->tfm, GFP_NOFS);
-       if (!req) {
-               mutex_unlock(&crypt_stat->cs_tfm_mutex);
-               rc = -ENOMEM;
-               goto out;
-       }
-
-       ablkcipher_request_set_callback(req,
-                       CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP,
-                       extent_crypt_complete, &ecr);
-       /* Consider doing this once, when the file is opened */
-       if (!(crypt_stat->flags & ECRYPTFS_KEY_SET)) {
-               rc = crypto_ablkcipher_setkey(crypt_stat->tfm, crypt_stat->key,
-                                             crypt_stat->key_size);
-               if (rc) {
-                       ecryptfs_printk(KERN_ERR,
-                                       "Error setting key; rc = [%d]\n",
-                                       rc);
-                       mutex_unlock(&crypt_stat->cs_tfm_mutex);
-                       rc = -EINVAL;
-                       goto out;
-               }
-               crypt_stat->flags |= ECRYPTFS_KEY_SET;
-       }
-       mutex_unlock(&crypt_stat->cs_tfm_mutex);
-       ecryptfs_printk(KERN_DEBUG, "Decrypting [%d] bytes.\n", size);
-       ablkcipher_request_set_crypt(req, src_sg, dest_sg, size, iv);
-       rc = crypto_ablkcipher_decrypt(req);
-       if (rc == -EINPROGRESS || rc == -EBUSY) {
-               struct extent_crypt_result *ecr = req->base.data;
-
-               wait_for_completion(&ecr->completion);
-               rc = ecr->rc;
-               INIT_COMPLETION(ecr->completion);
-       }
-out:
-       ablkcipher_request_free(req);
        return rc;
-
-}
-
-/**
- * ecryptfs_encrypt_page_offset
- * @crypt_stat: The cryptographic context
- * @dst_page: The page to encrypt into
- * @dst_offset: The offset in the page to encrypt into
- * @src_page: The page to encrypt from
- * @src_offset: The offset in the page to encrypt from
- * @size: The number of bytes to encrypt
- * @iv: The initialization vector to use for the encryption
- *
- * Returns the number of bytes encrypted
- */
-static int
-ecryptfs_encrypt_page_offset(struct ecryptfs_crypt_stat *crypt_stat,
-                            struct page *dst_page, int dst_offset,
-                            struct page *src_page, int src_offset, int size,
-                            unsigned char *iv)
-{
-       struct scatterlist src_sg, dst_sg;
-
-       sg_init_table(&src_sg, 1);
-       sg_init_table(&dst_sg, 1);
-
-       sg_set_page(&src_sg, src_page, size, src_offset);
-       sg_set_page(&dst_sg, dst_page, size, dst_offset);
-       return encrypt_scatterlist(crypt_stat, &dst_sg, &src_sg, size, iv);
-}
-
-/**
- * ecryptfs_decrypt_page_offset
- * @crypt_stat: The cryptographic context
- * @dst_page: The page to decrypt into
- * @dst_offset: The offset in the page to decrypt into
- * @src_page: The page to decrypt from
- * @src_offset: The offset in the page to decrypt from
- * @size: The number of bytes to decrypt
- * @iv: The initialization vector to use for the decryption
- *
- * Returns the number of bytes decrypted
- */
-static int
-ecryptfs_decrypt_page_offset(struct ecryptfs_crypt_stat *crypt_stat,
-                            struct page *dst_page, int dst_offset,
-                            struct page *src_page, int src_offset, int size,
-                            unsigned char *iv)
-{
-       struct scatterlist src_sg, dst_sg;
-
-       sg_init_table(&src_sg, 1);
-       sg_set_page(&src_sg, src_page, size, src_offset);
-
-       sg_init_table(&dst_sg, 1);
-       sg_set_page(&dst_sg, dst_page, size, dst_offset);
-
-       return decrypt_scatterlist(crypt_stat, &dst_sg, &src_sg, size, iv);
 }
 
 #define ECRYPTFS_MAX_SCATTERLIST_LEN 4
index 24f1105fda3ab5edfccc7a748f97dd624bf6f0fb..992cf95830b5792a5d510f7d588049d27c139a94 100644 (file)
@@ -49,7 +49,7 @@ static ssize_t ecryptfs_read_update_atime(struct kiocb *iocb,
                                unsigned long nr_segs, loff_t pos)
 {
        ssize_t rc;
-       struct path lower;
+       struct path *path;
        struct file *file = iocb->ki_filp;
 
        rc = generic_file_aio_read(iocb, iov, nr_segs, pos);
@@ -60,9 +60,8 @@ static ssize_t ecryptfs_read_update_atime(struct kiocb *iocb,
        if (-EIOCBQUEUED == rc)
                rc = wait_on_sync_kiocb(iocb);
        if (rc >= 0) {
-               lower.dentry = ecryptfs_dentry_to_lower(file->f_path.dentry);
-               lower.mnt = ecryptfs_dentry_to_lower_mnt(file->f_path.dentry);
-               touch_atime(&lower);
+               path = ecryptfs_dentry_to_lower_path(file->f_path.dentry);
+               touch_atime(path);
        }
        return rc;
 }
index e924cf45aad9559533214814cccbb05aa7a06b44..eb1c5979ecaf673d7e984b6b78219217e63c9bc4 100644 (file)
@@ -120,16 +120,15 @@ static int ecryptfs_init_lower_file(struct dentry *dentry,
                                    struct file **lower_file)
 {
        const struct cred *cred = current_cred();
-       struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry);
-       struct vfsmount *lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry);
+       struct path *path = ecryptfs_dentry_to_lower_path(dentry);
        int rc;
 
-       rc = ecryptfs_privileged_open(lower_file, lower_dentry, lower_mnt,
+       rc = ecryptfs_privileged_open(lower_file, path->dentry, path->mnt,
                                      cred);
        if (rc) {
                printk(KERN_ERR "Error opening lower file "
                       "for lower_dentry [0x%p] and lower_mnt [0x%p]; "
-                      "rc = [%d]\n", lower_dentry, lower_mnt, rc);
+                      "rc = [%d]\n", path->dentry, path->mnt, rc);
                (*lower_file) = NULL;
        }
        return rc;
index 49ff8ea08f1ca88252d82a34c98d77d0c490ff86..e57380e5f6bd78fb983b10e292919d29eba19abc 100644 (file)
@@ -247,14 +247,13 @@ int ecryptfs_process_response(struct ecryptfs_daemon *daemon,
                goto unlock;
        }
        msg_size = (sizeof(*msg) + msg->data_len);
-       msg_ctx->msg = kmalloc(msg_size, GFP_KERNEL);
+       msg_ctx->msg = kmemdup(msg, msg_size, GFP_KERNEL);
        if (!msg_ctx->msg) {
                rc = -ENOMEM;
                printk(KERN_ERR "%s: Failed to allocate [%zd] bytes of "
                       "GFP_KERNEL memory\n", __func__, msg_size);
                goto unlock;
        }
-       memcpy(msg_ctx->msg, msg, msg_size);
        msg_ctx->state = ECRYPTFS_MSG_CTX_STATE_DONE;
        wake_up_process(msg_ctx->task);
        rc = 0;