fscrypt: Let fs select encryption index/tweak
authorDavid Gstir <david@sigma-star.at>
Sun, 13 Nov 2016 21:20:48 +0000 (22:20 +0100)
committerTheodore Ts'o <tytso@mit.edu>
Mon, 14 Nov 2016 01:18:16 +0000 (20:18 -0500)
Avoid re-use of page index as tweak for AES-XTS when multiple parts of
same page are encrypted. This will happen on multiple (partial) calls of
fscrypt_encrypt_page on same page.
page->index is only valid for writeback pages.

Signed-off-by: David Gstir <david@sigma-star.at>
Signed-off-by: Richard Weinberger <richard@nod.at>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
fs/crypto/crypto.c
fs/ext4/inode.c
fs/ext4/page-io.c
fs/f2fs/data.c
include/linux/fscrypto.h

index f5c5e84ea9db59254af2cf6916b2dbd180bb338b..b6029785714c58d3a192aed66fc59fa086b23204 100644 (file)
@@ -218,6 +218,8 @@ static struct page *alloc_bounce_page(struct fscrypt_ctx *ctx, gfp_t gfp_flags)
  * @plaintext_page:   The page to encrypt. Must be locked.
  * @plaintext_len:    Length of plaintext within page
  * @plaintext_offset: Offset of plaintext within page
+ * @index:            Index for encryption. This is mainly the page index, but
+ *                    but might be different for multiple calls on same page.
  * @gfp_flags:        The gfp flag for memory allocation
  *
  * Encrypts plaintext_page using the ctx encryption context. If
@@ -235,7 +237,7 @@ struct page *fscrypt_encrypt_page(const struct inode *inode,
                                struct page *plaintext_page,
                                unsigned int plaintext_len,
                                unsigned int plaintext_offset,
-                               gfp_t gfp_flags)
+                               pgoff_t index, gfp_t gfp_flags)
 
 {
        struct fscrypt_ctx *ctx;
@@ -256,7 +258,7 @@ struct page *fscrypt_encrypt_page(const struct inode *inode,
        }
 
        ctx->w.control_page = plaintext_page;
-       err = do_page_crypto(inode, FS_ENCRYPT, plaintext_page->index,
+       err = do_page_crypto(inode, FS_ENCRYPT, index,
                                        plaintext_page, ciphertext_page,
                                        plaintext_len, plaintext_offset,
                                        gfp_flags);
@@ -283,6 +285,7 @@ EXPORT_SYMBOL(fscrypt_encrypt_page);
  * @page:  The page to decrypt. Must be locked.
  * @len:   Number of bytes in @page to be decrypted.
  * @offs:  Start of data in @page.
+ * @index: Index for encryption.
  *
  * Decrypts page in-place using the ctx encryption context.
  *
@@ -291,7 +294,7 @@ EXPORT_SYMBOL(fscrypt_encrypt_page);
  * Return: Zero on success, non-zero otherwise.
  */
 int fscrypt_decrypt_page(const struct inode *inode, struct page *page,
-                       unsigned int len, unsigned int offs)
+                       unsigned int len, unsigned int offs, pgoff_t index)
 {
        return do_page_crypto(inode, FS_DECRYPT, page->index, page, page, len, offs,
                        GFP_NOFS);
@@ -430,7 +433,7 @@ static void completion_pages(struct work_struct *work)
        bio_for_each_segment_all(bv, bio, i) {
                struct page *page = bv->bv_page;
                int ret = fscrypt_decrypt_page(page->mapping->host, page,
-                               PAGE_SIZE, 0);
+                               PAGE_SIZE, 0, page->index);
 
                if (ret) {
                        WARN_ON_ONCE(1);
index 1d498c5e2990e0cc013ec510f7c463da2945bdac..1485ac273bfbf85d7cee60ccf818f1782220428a 100644 (file)
@@ -1167,7 +1167,7 @@ static int ext4_block_write_begin(struct page *page, loff_t pos, unsigned len,
                page_zero_new_buffers(page, from, to);
        else if (decrypt)
                err = fscrypt_decrypt_page(page->mapping->host, page,
-                               PAGE_SIZE, 0);
+                               PAGE_SIZE, 0, page->index);
        return err;
 }
 #endif
@@ -3746,7 +3746,7 @@ static int __ext4_block_zero_page_range(handle_t *handle,
                        BUG_ON(blocksize != PAGE_SIZE);
                        BUG_ON(!PageLocked(page));
                        WARN_ON_ONCE(fscrypt_decrypt_page(page->mapping->host,
-                                               page, PAGE_SIZE, 0));
+                                               page, PAGE_SIZE, 0, page->index));
                }
        }
        if (ext4_should_journal_data(inode)) {
index 3d1d3d0f4303aa28ca334dc35931b524eadc1efc..902a3e3059b3442b1d47ffb939f68ab5df8950f8 100644 (file)
@@ -470,7 +470,8 @@ int ext4_bio_write_page(struct ext4_io_submit *io,
                gfp_t gfp_flags = GFP_NOFS;
 
        retry_encrypt:
-               data_page = fscrypt_encrypt_page(inode, page, PAGE_SIZE, 0, gfp_flags);
+               data_page = fscrypt_encrypt_page(inode, page, PAGE_SIZE, 0,
+                                               page->index, gfp_flags);
                if (IS_ERR(data_page)) {
                        ret = PTR_ERR(data_page);
                        if (ret == -ENOMEM && wbc->sync_mode == WB_SYNC_ALL) {
index fac207254e8dd2bcb1a6d8e441795af6ca314977..435590c4b341b20966771722013c13f5e1a425b9 100644 (file)
@@ -1196,8 +1196,9 @@ int do_write_data_page(struct f2fs_io_info *fio)
 retry_encrypt:
                BUG_ON(!PageLocked(fio->page));
                fio->encrypted_page = fscrypt_encrypt_page(inode, fio->page,
-                                                               PAGE_SIZE, 0,
-                                                               gfp_flags);
+                                                       PAGE_SIZE, 0,
+                                                       fio->page->index,
+                                                       gfp_flags);
                if (IS_ERR(fio->encrypted_page)) {
                        err = PTR_ERR(fio->encrypted_page);
                        if (err == -ENOMEM) {
index e9be944a324c41d89a3c1c5f49eafc3b6fd2b4ec..98c71e973a960b9ee41039c93c42519ac7591091 100644 (file)
@@ -250,9 +250,9 @@ extern struct fscrypt_ctx *fscrypt_get_ctx(const struct inode *, gfp_t);
 extern void fscrypt_release_ctx(struct fscrypt_ctx *);
 extern struct page *fscrypt_encrypt_page(const struct inode *, struct page *,
                                                unsigned int, unsigned int,
-                                               gfp_t);
+                                               pgoff_t, gfp_t);
 extern int fscrypt_decrypt_page(const struct inode *, struct page *, unsigned int,
-                               unsigned int);
+                               unsigned int, pgoff_t);
 extern void fscrypt_decrypt_bio_pages(struct fscrypt_ctx *, struct bio *);
 extern void fscrypt_pullback_bio_page(struct page **, bool);
 extern void fscrypt_restore_control_page(struct page *);
@@ -299,13 +299,14 @@ static inline struct page *fscrypt_notsupp_encrypt_page(const struct inode *i,
                                                struct page *p,
                                                unsigned int len,
                                                unsigned int offs,
-                                               gfp_t f)
+                                               pgoff_t index, gfp_t f)
 {
        return ERR_PTR(-EOPNOTSUPP);
 }
 
 static inline int fscrypt_notsupp_decrypt_page(const struct inode *i, struct page *p,
-                                               unsigned int len, unsigned int offs)
+                                               unsigned int len, unsigned int offs,
+                                               pgoff_t index)
 {
        return -EOPNOTSUPP;
 }