[COMMON] fs: add diskcipher free_req and debug
authorBoojin Kim <boojin.kim@samsung.com>
Tue, 15 May 2018 15:09:30 +0000 (00:09 +0900)
committerJunho Choi <junhosj.choi@samsung.com>
Thu, 24 May 2018 00:02:04 +0000 (09:02 +0900)
Change-Id: Ib5cfb98ed1b0ac43eff6ec3d9cbe3507a191b7b5
Signed-off-by: Boojin Kim <boojin.kim@samsung.com>
12 files changed:
fs/buffer.c
fs/crypto/bio.c
fs/crypto/crypto.c
fs/crypto/fscrypt_private.h
fs/crypto/keyinfo.c
fs/direct-io.c
fs/ext4/inode.c
fs/ext4/page-io.c
fs/ext4/readpage.c
include/linux/fscrypt.h
include/linux/fscrypt_notsupp.h
include/linux/fscrypt_supp.h

index 81434292082e603cfbc861feb26043dec86442c6..fd41645f26eb9cb11114a42f9a794d3b408076d7 100644 (file)
@@ -46,6 +46,7 @@
 #include <linux/bit_spinlock.h>
 #include <linux/pagevec.h>
 #include <trace/events/block.h>
+#include <linux/fscrypt.h> /* for CONFIG_CRYPTO_DISKCIPHER_DEBUG */
 
 static int fsync_buffers_list(spinlock_t *lock, struct list_head *list);
 static int submit_bh_wbc(int op, int op_flags, struct buffer_head *bh,
@@ -3141,6 +3142,7 @@ static int submit_bh_wbc(int op, int op_flags, struct buffer_head *bh,
                op_flags |= REQ_PRIO;
        bio_set_op_attrs(bio, op, op_flags);
 
+       crypto_diskcipher_debug(BLK_BH, op_flags);
        if (bio->bi_opf & REQ_AUX_PRIV)
                bio->bi_aux_private = bh->b_private;
        submit_bio(bio);
index b182c1afd080fe64e54ceb95ebddb3b5c4d0e6d0..0968c4f1d20e72dfe51357649efe12467c92b6f5 100644 (file)
@@ -94,7 +94,7 @@ int fscrypt_zeroout_range(const struct inode *inode, pgoff_t lblk,
 
        BUG_ON(inode->i_sb->s_blocksize != PAGE_SIZE);
 
-       if (fscrypt_disk_encrypted(inode)) {
+       if (__fscrypt_disk_encrypted(inode)) {
                ciphertext_page = fscrypt_alloc_bounce_page(NULL, GFP_NOWAIT);
                if (!ciphertext_page || IS_ERR(ciphertext_page)) {
                        err = PTR_ERR(ciphertext_page);
@@ -142,10 +142,8 @@ int fscrypt_zeroout_range(const struct inode *inode, pgoff_t lblk,
                        err = -EIO;
                        goto errout;
                }
-#ifdef CONFIG_CRYPTO_DISKCIPHER
-               if (fscrypt_has_encryption_key(inode))
-                       fscrypt_set_bio(inode, bio);
-#endif
+               fscrypt_set_bio(inode, bio);
+               crypto_diskcipher_debug(FS_ZEROPAGE, bio->bi_opf);
                err = submit_bio_wait(bio);
                if (err == 0 && bio->bi_status)
                        err = -EIO;
@@ -165,12 +163,25 @@ errout:
 }
 EXPORT_SYMBOL(fscrypt_zeroout_range);
 
+int fscrypt_disk_encrypted(const struct inode *inode)
+{
+       return __fscrypt_disk_encrypted(inode);
+}
+
 void fscrypt_set_bio(const struct inode *inode, struct bio *bio)
 {
 #ifdef CONFIG_CRYPTO_DISKCIPHER
-       if (inode->i_crypt_info->ci_dtfm)
+       if (__fscrypt_disk_encrypted(inode))
                crypto_diskcipher_set(bio, inode->i_crypt_info->ci_dtfm);
-#else
+#endif
        return;
+}
+
+void *fscrypt_get_diskcipher(const struct inode *inode)
+{
+#ifdef CONFIG_CRYPTO_DISKCIPHER
+       if (fscrypt_has_encryption_key(inode))
+               return inode->i_crypt_info->ci_dtfm;
 #endif
+       return NULL;
 }
index f65237d137f9fa65e513e92b307dc6323df6ef7d..f5ee6141a02806b1b2343443d4940c3369fbb551 100644 (file)
@@ -97,7 +97,7 @@ struct fscrypt_ctx *fscrypt_get_ctx(const struct inode *inode, gfp_t gfp_flags)
        if (ci == NULL)
                return ERR_PTR(-ENOKEY);
 
-       if (fscrypt_disk_encrypted(inode))
+       if (__fscrypt_disk_encrypted(inode))
                return NULL;
 
        /*
@@ -251,10 +251,12 @@ struct page *fscrypt_encrypt_page(const struct inode *inode,
        struct page *ciphertext_page = page;
        int err;
 
-       BUG_ON(len % FS_CRYPTO_BLOCK_SIZE != 0);
+#ifdef CONFIG_CRYPTO_DISKCIPHER_DEBUG
+       if (__fscrypt_disk_encrypted(inode))
+               crypto_diskcipher_debug(FS_ENC_WARN, 0);
+#endif
 
-       if (fscrypt_disk_encrypted(inode))
-               return NULL;
+       BUG_ON(len % FS_CRYPTO_BLOCK_SIZE != 0);
 
        if (inode->i_sb->s_cop->flags & FS_CFLG_OWN_PAGES) {
                /* with inplace-encryption we just encrypt the page */
@@ -315,11 +317,13 @@ EXPORT_SYMBOL(fscrypt_encrypt_page);
 int fscrypt_decrypt_page(const struct inode *inode, struct page *page,
                        unsigned int len, unsigned int offs, u64 lblk_num)
 {
+#ifdef CONFIG_CRYPTO_DISKCIPHER_DEBUG
+       if (__fscrypt_disk_encrypted(inode))
+               crypto_diskcipher_debug(FS_DEC_WARN, 0);
+#endif
        if (!(inode->i_sb->s_cop->flags & FS_CFLG_OWN_PAGES))
                BUG_ON(!PageLocked(page));
 
-       if (fscrypt_disk_encrypted(page->mapping->host))
-               return 0;
        return fscrypt_do_page_crypto(inode, FS_DECRYPT, lblk_num, page, page,
                                      len, offs, GFP_NOFS);
 }
index 06e0f47660507f0677a14d4d9aa717c42c40a0bb..bd53a2a624b20061914eaaa02a61f4b8fefef91d 100644 (file)
@@ -15,7 +15,6 @@
 #define __FS_HAS_ENCRYPTION 1
 #include <linux/fscrypt.h>
 #include <crypto/hash.h>
-#include <crypto/diskcipher.h>
 
 /* Encryption parameters */
 #define FS_IV_SIZE                     16
@@ -91,7 +90,7 @@ extern void fscrypt_free_bounce_page(void *pool);
 /* keyinfo.c */
 extern void __exit fscrypt_essiv_cleanup(void);
 
-static inline int fscrypt_disk_encrypted(const struct inode *inode)
+static inline int __fscrypt_disk_encrypted(const struct inode *inode)
 {
 #if IS_ENABLED(CONFIG_FS_ENCRYPTION)
 #if IS_ENABLED(CONFIG_CRYPTO_DISKCIPHER)
index 628b22030503e19af6c8f054f385237bb39cd692..08269e3c8d413e9f6bc23ade37cd1dc83f5882d0 100644 (file)
@@ -170,7 +170,7 @@ static void put_crypt_info(struct fscrypt_info *ci)
 
 #if defined(CONFIG_CRYPTO_DISKCIPHER)
        if (ci->ci_dtfm)
-               crypto_free_diskcipher(ci->ci_dtfm);
+               crypto_free_req_diskcipher(ci->ci_dtfm);
 #endif
        crypto_free_skcipher(ci->ci_ctfm);
        crypto_free_cipher(ci->ci_essiv_tfm);
@@ -333,8 +333,8 @@ int fscrypt_get_encryption_info(struct inode *inode)
                        if (!res) {
                                if (cmpxchg(&inode->i_crypt_info, NULL, crypt_info) == NULL)
                                        crypt_info = NULL;
-                               pr_debug("%s: (inode %lu) uses diskcipher tfm\n",
-                                       __func__, inode->i_ino);
+                               pr_debug("%s: (inode %p:%lu, fscrypt:%p) uses diskcipher tfm\n",
+                                       __func__, inode, inode->i_ino, inode->i_crypt_info);
                                goto out;
                        } else {
                                pr_warn("%s: error %d fails to set diskciher key\n",
index 4aa11cdbfe2c85446e0c4a18abf51b5e3547e9ac..4b5610f88024edef1c82008cd55e31601d92ef0d 100644 (file)
@@ -450,8 +450,10 @@ static inline void dio_bio_submit(struct dio *dio, struct dio_submit *sdio)
        spin_unlock_irqrestore(&dio->bio_lock, flags);
 
 #if defined(CONFIG_EXT4_FS_ENCRYPTION) && defined(CONFIG_CRYPTO_DISKCIPHER)
-       if (dio->inode && fscrypt_has_encryption_key(dio->inode))
+       if (dio->inode && fscrypt_has_encryption_key(dio->inode)) {
                fscrypt_set_bio(dio->inode, bio);
+               crypto_diskcipher_debug(FS_DIO, bio->bi_opf);
+       }
 #endif
        if (dio->is_async && dio->op == REQ_OP_READ && dio->should_dirty)
                bio_set_pages_dirty(bio);
index 51b70932d0453da60511758dde5ddbcc4d461cf0..e947526ac964735494f296101f14357a6e5c5ec5 100644 (file)
@@ -1215,10 +1215,19 @@ static int ext4_block_write_begin(struct page *page, loff_t pos, unsigned len,
                if (!buffer_uptodate(bh) && !buffer_delay(bh) &&
                    !buffer_unwritten(bh) &&
                    (block_start < from || block_end > to)) {
-                       ll_rw_block(REQ_OP_READ, 0, 1, &bh);
+                   int bi_opf = 0;
+
+                       if (S_ISREG(inode->i_mode) && ext4_encrypted_inode(inode)
+                                       && fscrypt_has_encryption_key(inode)) {
+                                       bh->b_private = fscrypt_get_diskcipher(inode);
+                                       if (bh->b_private)
+                                               bi_opf = REQ_CRYPT | REQ_AUX_PRIV;
+                               }
+                       ll_rw_block(REQ_OP_READ, bi_opf, 1, &bh);
+                       crypto_diskcipher_debug(FS_BLOCK_WRITE, bi_opf);
                        *wait_bh++ = bh;
                        decrypt = ext4_encrypted_inode(inode) &&
-                               S_ISREG(inode->i_mode);
+                               S_ISREG(inode->i_mode) && !bh->b_private;
                }
        }
        /*
@@ -3823,14 +3832,9 @@ static ssize_t ext4_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
        ssize_t ret;
        int rw = iov_iter_rw(iter);
 
-#if defined(CONFIG_EXT4_FS_ENCRYPTION) && !defined(CONFIG_CRYPTO_DISKCIPHER)
-       if (ext4_encrypted_inode(inode) && S_ISREG(inode->i_mode))
+       if (ext4_encrypted_inode(inode) && S_ISREG(inode->i_mode)
+                       && !fscrypt_disk_encrypted(inode))
                return 0;
-#elif defined(CONFIG_CRYPTO_DISKCIPHER)
-       if (ext4_encrypted_inode(inode) && !fscrypt_has_encryption_key(inode))
-               return 0;
-#endif
-
        /*
         * If we are doing data journalling we don't support O_DIRECT
         */
@@ -4030,7 +4034,14 @@ static int __ext4_block_zero_page_range(handle_t *handle,
 
        if (!buffer_uptodate(bh)) {
                err = -EIO;
-               ll_rw_block(REQ_OP_READ, 0, 1, &bh);
+               if (S_ISREG(inode->i_mode) && ext4_encrypted_inode(inode)
+                               && fscrypt_has_encryption_key(inode))
+                       bh->b_private = fscrypt_get_diskcipher(inode);
+               if (bh->b_private)
+                       ll_rw_block(REQ_OP_READ, REQ_CRYPT, 1, &bh);
+               else
+                       ll_rw_block(REQ_OP_READ, 0, 1, &bh);
+
                wait_on_buffer(bh);
                /* Uhhuh. Read error. Complain and punt. */
                if (!buffer_uptodate(bh))
@@ -4040,7 +4051,9 @@ static int __ext4_block_zero_page_range(handle_t *handle,
                        /* We expect the key to be set. */
                        BUG_ON(!fscrypt_has_encryption_key(inode));
                        BUG_ON(blocksize != PAGE_SIZE);
-                       WARN_ON_ONCE(fscrypt_decrypt_page(page->mapping->host,
+
+                       if (!bh->b_private)
+                               WARN_ON_ONCE(fscrypt_decrypt_page(page->mapping->host,
                                                page, PAGE_SIZE, 0, page->index));
                }
        }
index b769a6e8b80bd429c4d86acd4856b8f8466a5c14..f3f96aacae0d6fdaddeefdff3740b3f4716a29c9 100644 (file)
@@ -352,9 +352,12 @@ void ext4_io_submit(struct ext4_io_submit *io)
                int io_op_flags = io->io_wbc->sync_mode == WB_SYNC_ALL ?
                                  REQ_SYNC : 0;
                io->io_bio->bi_write_hint = io->io_end->inode->i_write_hint;
-               if (bio->bi_opf & REQ_CRYPT)
-                       io_op_flags |= (REQ_CRYPT | REQ_AUX_PRIV);
                bio_set_op_attrs(io->io_bio, REQ_OP_WRITE, io_op_flags);
+               if (ext4_encrypted_inode(io->io_end->inode) &&
+                               S_ISREG(io->io_end->inode->i_mode)) {
+                       fscrypt_set_bio(io->io_end->inode, io->io_bio);
+                       crypto_diskcipher_debug(FS_PAGEIO, io->io_bio->bi_opf);
+               }
                submit_bio(io->io_bio);
        }
        io->io_bio = NULL;
@@ -401,11 +404,6 @@ submit_and_retry:
                ret = io_submit_init_bio(io, bh);
                if (ret)
                        return ret;
-#if defined(CONFIG_EXT4_FS_ENCRYPTION) && defined(CONFIG_CRYPTO_DISKCIPHER)
-               if (ext4_encrypted_inode(inode) &&
-                       S_ISREG(inode->i_mode) && fscrypt_has_encryption_key(inode))
-                       fscrypt_set_bio(inode, io->io_bio);
-#endif
                io->io_bio->bi_write_hint = inode->i_write_hint;
        }
        ret = bio_add_page(io->io_bio, page, bh->b_size, bh_offset(bh));
@@ -485,7 +483,7 @@ int ext4_bio_write_page(struct ext4_io_submit *io,
        bh = head = page_buffers(page);
 
        if (ext4_encrypted_inode(inode) && S_ISREG(inode->i_mode) &&
-           nr_to_submit) {
+           nr_to_submit && !fscrypt_disk_encrypted(inode)) {
                gfp_t gfp_flags = GFP_NOFS;
 
        retry_encrypt:
index 25797025c1b311babd7399ba3ca62af1da5a1e6e..55ae5362880bdb07df334350c80451f49ec9a714 100644 (file)
@@ -303,11 +303,10 @@ int ext4_mpage_readpages(struct address_space *mapping,
                        bio->bi_end_io = mpage_end_io;
                        bio->bi_private = ctx;
                        bio_set_op_attrs(bio, REQ_OP_READ, 0);
-#if defined(CONFIG_EXT4_FS_ENCRYPTION) && defined(CONFIG_CRYPTO_DISKCIPHER)
-                       if (ext4_encrypted_inode(inode) &&
-                               S_ISREG(inode->i_mode) && fscrypt_has_encryption_key(inode))
+                       if (ext4_encrypted_inode(inode) && S_ISREG(inode->i_mode)) {
                                fscrypt_set_bio(inode, bio);
-#endif
+                               crypto_diskcipher_debug(FS_READP, bio->bi_opf);
+                       }
                }
 
                length = first_hole << blkbits;
index 5257e495bf3bd56cd7edfc005ed3e0950762db21..6f6da7a28416ca4ca1f957ac57c869eec23434d3 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/dcache.h>
 #include <crypto/skcipher.h>
 #include <uapi/linux/fs.h>
+#include <crypto/diskcipher.h>
 
 #define FS_CRYPTO_BLOCK_SIZE           16
 
index 9ea9625f0f7bd7b843b16ec107690806d8d9f716..47b03b3deaf3c9104b99e03c5913ecbd9c94900a 100644 (file)
@@ -208,8 +208,18 @@ static inline int __fscrypt_prepare_lookup(struct inode *dir,
        return -EOPNOTSUPP;
 }
 
+static inline int fscrypt_disk_encrypted(const struct inode *inode)
+{
+       return;
+}
+
 static inline void fscrypt_set_bio(const struct inode *inode, struct bio *bio)
 {
        return;
 }
+
+static inline void *fscrypt_get_diskcipher(const struct inode *inode)
+{
+       return NULL;
+}
 #endif /* _LINUX_FSCRYPT_NOTSUPP_H */
index 79c6a02a055836c6a7007bd63df1d34614386a93..5e004ff66e47ba7a64aa56c478be22bc67db8dd5 100644 (file)
@@ -144,6 +144,9 @@ extern void fscrypt_pullback_bio_page(struct page **, bool);
 extern int fscrypt_zeroout_range(const struct inode *, pgoff_t, sector_t,
                                 unsigned int);
 void fscrypt_set_bio(const struct inode *inode, struct bio *bio);
+void *fscrypt_get_diskcipher(const struct inode *inode);
+int fscrypt_disk_encrypted(const struct inode *inode);
+
 /* hooks.c */
 extern int fscrypt_file_open(struct inode *inode, struct file *filp);
 extern int __fscrypt_prepare_link(struct inode *inode, struct inode *dir);