[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)
committerCosmin Tanislav <demonsingur@gmail.com>
Mon, 22 Apr 2024 17:22:12 +0000 (20:22 +0300)
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 b7f33c544645b6cff206e48399b1528b43404d09..9f249af424fe1aabaa309b8de0b234edce20f817 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,
@@ -3144,6 +3145,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 f1b3d014b60b9fed0fb32ffd442e650aa7be9f7a..4c38fc438eeeffe57ed79ee37af397c3e277d778 100644 (file)
@@ -103,7 +103,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);
@@ -151,10 +151,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;
@@ -174,12 +172,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 2ed8e40bb533696e4f4e0288aaa6990c6ace0b29..a5c0ad05825fb9d91f42e1befd612ff4f5cc458b 100644 (file)
@@ -104,7 +104,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;
 
        /*
@@ -258,8 +258,10 @@ struct page *fscrypt_encrypt_page(const struct inode *inode,
        struct page *ciphertext_page = page;
        int err;
 
-       if (fscrypt_disk_encrypted(inode))
-               return NULL;
+#ifdef CONFIG_CRYPTO_DISKCIPHER_DEBUG
+       if (__fscrypt_disk_encrypted(inode))
+               crypto_diskcipher_debug(FS_ENC_WARN, 0);
+#endif
 
        if (inode->i_sb->s_cop->flags & FS_CFLG_OWN_PAGES) {
                /* with inplace-encryption we just encrypt the page */
@@ -321,12 +323,14 @@ 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 (WARN_ON_ONCE(!PageLocked(page) &&
                         !(inode->i_sb->s_cop->flags & FS_CFLG_OWN_PAGES)))
                return -EINVAL;
 
-       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 18bde3175a432a573c2bebb779f8e104bf4ec2c3..0b33f3248903515221aba1bea8c034ee05aceed1 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
@@ -123,7 +122,7 @@ extern bool fscrypt_fname_encrypted_size(const struct inode *inode,
 /* 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 8d4df6cc2e7382c0e120043c39c1417347d290b8..1de64a61df2502f1631ec619a0ff13dda8eb0b0f 100644 (file)
@@ -160,7 +160,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);
@@ -324,8 +324,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 77f688e4709e382b4eda8c72241e0b12f50e26b3..b71d927b9a07e75e34839be73f31b09763859700 100644 (file)
@@ -472,8 +472,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 0e191add08bc96825b3214d694135db45fc24058..1cbc0af84aabd435492094a89d16c6d5bec2c4ba 100644 (file)
@@ -1242,10 +1242,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;
                }
        }
        /*
@@ -3893,14 +3902,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
         */
@@ -4100,7 +4104,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))
@@ -4110,7 +4121,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 d273e559223151947479fef359b8c4897e999d87..d09cd14f0a5aa46a85b5846637e724619ca2de22 100644 (file)
@@ -354,9 +354,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;
@@ -403,11 +406,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));
@@ -487,7 +485,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;
 
                /*
index 143d3818089085de64879ddde8df6c4580671bff..a82b3a122d3d5b81c814dfc551c603dd5ae650c9 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 84b2e59eb569399ab32637168afa712e34d07e85..71e8ae567ff9ccd984634a0e5e6434eb9d4e772e 100644 (file)
 #define _LINUX_FSCRYPT_H
 
 #include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/bio.h>
+#include <linux/dcache.h>
+#include <crypto/skcipher.h>
+#include <uapi/linux/fs.h>
+#include <crypto/diskcipher.h>
 
 #define FS_CRYPTO_BLOCK_SIZE           16
 
index 3f118464b17a84126f33705a69336a5db7dc3e47..9c812ddd137f00d1047798ce19949e471d0d50ec 100644 (file)
@@ -204,11 +204,21 @@ 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;
+}
+
 static inline int __fscrypt_prepare_symlink(struct inode *dir,
                                            unsigned int len,
                                            unsigned int max_len,
index e3604b0196858f22cc291c331a48e3ed019f8e81..36fc214945e68d1f7b600eab80c83e79145f4bbd 100644 (file)
@@ -182,6 +182,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);