From d44ddbf4172be11302e7bfca4e5eec42378414f8 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 16 Nov 2020 10:13:31 -0800 Subject: [PATCH] ANDROID: revert fscrypt direct I/O support Revert the direct I/O support for encrypted files so that we can bring in the latest version of the patches from the mailing list. This is needed because in v5.5 and later, the ext4 support (via fs/iomap/) is broken as-is -- not only is the second call to fscrypt_limit_dio_pages() in the wrong place, but bios can exceed the intended nr_pages limit due to multipage bvecs. In order to fix this we need the v6 patches which make fs/ext4/ handle the limiting instead of fs/iomap/. On android-mainline, this fixes a failure in vts_kernel_encryption_test (specifically, FBEPolicyTest#TestAesEmmcOptimizedPolicy) when run on a device that uses the inlinecrypt mount option on ext4 (e.g. db845c). Bug: 162255927 Bug: 171462575 Change-Id: I0da753dc9e0e7bc8d84bbcadfdfcdb9328cdb8d8 Signed-off-by: Eric Biggers Signed-off-by: Satya Tangirala --- fs/crypto/crypto.c | 8 ----- fs/crypto/inline_crypt.c | 72 ---------------------------------------- fs/direct-io.c | 15 +-------- fs/ext4/file.c | 10 +++--- fs/f2fs/f2fs.h | 6 +--- fs/iomap/direct-io.c | 8 ----- include/linux/fscrypt.h | 19 ----------- 7 files changed, 6 insertions(+), 132 deletions(-) diff --git a/fs/crypto/crypto.c b/fs/crypto/crypto.c index 171500f51a49..4ef3f714046a 100644 --- a/fs/crypto/crypto.c +++ b/fs/crypto/crypto.c @@ -69,14 +69,6 @@ void fscrypt_free_bounce_page(struct page *bounce_page) } EXPORT_SYMBOL(fscrypt_free_bounce_page); -/* - * Generate the IV for the given logical block number within the given file. - * For filenames encryption, lblk_num == 0. - * - * Keep this in sync with fscrypt_limit_dio_pages(). fscrypt_limit_dio_pages() - * needs to know about any IV generation methods where the low bits of IV don't - * simply contain the lblk_num (e.g., IV_INO_LBLK_32). - */ void fscrypt_generate_iv(union fscrypt_iv *iv, u64 lblk_num, const struct fscrypt_info *ci) { diff --git a/fs/crypto/inline_crypt.c b/fs/crypto/inline_crypt.c index bf2c46c2784a..6b25211fa553 100644 --- a/fs/crypto/inline_crypt.c +++ b/fs/crypto/inline_crypt.c @@ -18,7 +18,6 @@ #include #include #include -#include #include "fscrypt_private.h" @@ -400,74 +399,3 @@ bool fscrypt_mergeable_bio_bh(struct bio *bio, return fscrypt_mergeable_bio(bio, inode, next_lblk); } EXPORT_SYMBOL_GPL(fscrypt_mergeable_bio_bh); - -/** - * fscrypt_dio_supported() - check whether a direct I/O request is unsupported - * due to encryption constraints - * @iocb: the file and position the I/O is targeting - * @iter: the I/O data segment(s) - * - * Return: true if direct I/O is supported - */ -bool fscrypt_dio_supported(struct kiocb *iocb, struct iov_iter *iter) -{ - const struct inode *inode = file_inode(iocb->ki_filp); - const unsigned int blocksize = i_blocksize(inode); - - /* If the file is unencrypted, no veto from us. */ - if (!fscrypt_needs_contents_encryption(inode)) - return true; - - /* We only support direct I/O with inline crypto, not fs-layer crypto */ - if (!fscrypt_inode_uses_inline_crypto(inode)) - return false; - - /* - * Since the granularity of encryption is filesystem blocks, the I/O - * must be block aligned -- not just disk sector aligned. - */ - if (!IS_ALIGNED(iocb->ki_pos | iov_iter_alignment(iter), blocksize)) - return false; - - return true; -} -EXPORT_SYMBOL_GPL(fscrypt_dio_supported); - -/** - * fscrypt_limit_dio_pages() - limit I/O pages to avoid discontiguous DUNs - * @inode: the file on which I/O is being done - * @pos: the file position (in bytes) at which the I/O is being done - * @nr_pages: the number of pages we want to submit starting at @pos - * - * For direct I/O: limit the number of pages that will be submitted in the bio - * targeting @pos, in order to avoid crossing a data unit number (DUN) - * discontinuity. This is only needed for certain IV generation methods. - * - * This assumes block_size == PAGE_SIZE; see fscrypt_dio_supported(). - * - * Return: the actual number of pages that can be submitted - */ -int fscrypt_limit_dio_pages(const struct inode *inode, loff_t pos, int nr_pages) -{ - const struct fscrypt_info *ci = inode->i_crypt_info; - u32 dun; - - if (!fscrypt_inode_uses_inline_crypto(inode)) - return nr_pages; - - if (nr_pages <= 1) - return nr_pages; - - if (!(fscrypt_policy_flags(&ci->ci_policy) & - FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32)) - return nr_pages; - - if (WARN_ON_ONCE(i_blocksize(inode) != PAGE_SIZE)) - return 1; - - /* With IV_INO_LBLK_32, the DUN can wrap around from U32_MAX to 0. */ - - dun = ci->ci_hashed_ino + (pos >> inode->i_blkbits); - - return min_t(u64, nr_pages, (u64)U32_MAX + 1 - dun); -} diff --git a/fs/direct-io.c b/fs/direct-io.c index f6672c4030e3..d53fa92a1ab6 100644 --- a/fs/direct-io.c +++ b/fs/direct-io.c @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include @@ -393,7 +392,6 @@ dio_bio_alloc(struct dio *dio, struct dio_submit *sdio, sector_t first_sector, int nr_vecs) { struct bio *bio; - struct inode *inode = dio->inode; /* * bio_alloc() is guaranteed to return a bio when allowed to sleep and @@ -401,9 +399,6 @@ dio_bio_alloc(struct dio *dio, struct dio_submit *sdio, */ bio = bio_alloc(GFP_KERNEL, nr_vecs); - fscrypt_set_bio_crypt_ctx(bio, inode, - sdio->cur_page_fs_offset >> inode->i_blkbits, - GFP_KERNEL); bio_set_dev(bio, bdev); bio->bi_iter.bi_sector = first_sector; bio_set_op_attrs(bio, dio->op, dio->op_flags); @@ -768,17 +763,9 @@ static inline int dio_send_cur_page(struct dio *dio, struct dio_submit *sdio, * current logical offset in the file does not equal what would * be the next logical offset in the bio, submit the bio we * have. - * - * When fscrypt inline encryption is used, data unit number - * (DUN) contiguity is also required. Normally that's implied - * by logical contiguity. However, certain IV generation - * methods (e.g. IV_INO_LBLK_32) don't guarantee it. So, we - * must explicitly check fscrypt_mergeable_bio() too. */ if (sdio->final_block_in_bio != sdio->cur_page_block || - cur_offset != bio_next_offset || - !fscrypt_mergeable_bio(sdio->bio, dio->inode, - cur_offset >> dio->inode->i_blkbits)) + cur_offset != bio_next_offset) dio_bio_submit(dio, sdio); } diff --git a/fs/ext4/file.c b/fs/ext4/file.c index 0480e07c60b2..b692355b8c77 100644 --- a/fs/ext4/file.c +++ b/fs/ext4/file.c @@ -36,11 +36,9 @@ #include "acl.h" #include "truncate.h" -static bool ext4_dio_supported(struct kiocb *iocb, struct iov_iter *iter) +static bool ext4_dio_supported(struct inode *inode) { - struct inode *inode = file_inode(iocb->ki_filp); - - if (!fscrypt_dio_supported(iocb, iter)) + if (IS_ENABLED(CONFIG_FS_ENCRYPTION) && IS_ENCRYPTED(inode)) return false; if (fsverity_active(inode)) return false; @@ -63,7 +61,7 @@ static ssize_t ext4_dio_read_iter(struct kiocb *iocb, struct iov_iter *to) inode_lock_shared(inode); } - if (!ext4_dio_supported(iocb, to)) { + if (!ext4_dio_supported(inode)) { inode_unlock_shared(inode); /* * Fallback to buffered I/O if the operation being performed on @@ -497,7 +495,7 @@ static ssize_t ext4_dio_write_iter(struct kiocb *iocb, struct iov_iter *from) } /* Fallback to buffered I/O if the inode does not support direct I/O. */ - if (!ext4_dio_supported(iocb, from)) { + if (!ext4_dio_supported(inode)) { if (ilock_shared) inode_unlock_shared(inode); else diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 5130423a13e7..bb11759191dc 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -4091,11 +4091,7 @@ static inline bool f2fs_force_buffered_io(struct inode *inode, struct f2fs_sb_info *sbi = F2FS_I_SB(inode); int rw = iov_iter_rw(iter); - if (!fscrypt_dio_supported(iocb, iter)) - return true; - if (fsverity_active(inode)) - return true; - if (f2fs_compressed_file(inode)) + if (f2fs_post_read_required(inode)) return true; if (f2fs_is_multi_device(sbi)) return true; diff --git a/fs/iomap/direct-io.c b/fs/iomap/direct-io.c index 70488904a778..933f234d5bec 100644 --- a/fs/iomap/direct-io.c +++ b/fs/iomap/direct-io.c @@ -6,7 +6,6 @@ #include #include #include -#include #include #include #include @@ -186,14 +185,11 @@ static void iomap_dio_zero(struct iomap_dio *dio, struct iomap *iomap, loff_t pos, unsigned len) { - struct inode *inode = file_inode(dio->iocb->ki_filp); struct page *page = ZERO_PAGE(0); int flags = REQ_SYNC | REQ_IDLE; struct bio *bio; bio = bio_alloc(GFP_KERNEL, 1); - fscrypt_set_bio_crypt_ctx(bio, inode, pos >> inode->i_blkbits, - GFP_KERNEL); bio_set_dev(bio, iomap->bdev); bio->bi_iter.bi_sector = iomap_sector(iomap, pos); bio->bi_private = dio; @@ -259,7 +255,6 @@ iomap_dio_bio_actor(struct inode *inode, loff_t pos, loff_t length, ret = nr_pages; goto out; } - nr_pages = fscrypt_limit_dio_pages(inode, pos, nr_pages); if (need_zeroout) { /* zero out from the start of the block to the write offset */ @@ -277,8 +272,6 @@ iomap_dio_bio_actor(struct inode *inode, loff_t pos, loff_t length, } bio = bio_alloc(GFP_KERNEL, nr_pages); - fscrypt_set_bio_crypt_ctx(bio, inode, pos >> inode->i_blkbits, - GFP_KERNEL); bio_set_dev(bio, iomap->bdev); bio->bi_iter.bi_sector = iomap_sector(iomap, pos); bio->bi_write_hint = dio->iocb->ki_hint; @@ -316,7 +309,6 @@ iomap_dio_bio_actor(struct inode *inode, loff_t pos, loff_t length, copied += n; nr_pages = iov_iter_npages(dio->submit.iter, BIO_MAX_PAGES); - nr_pages = fscrypt_limit_dio_pages(inode, pos, nr_pages); iomap_dio_submit_bio(dio, iomap, bio, pos); pos += n; } while (nr_pages); diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h index 1a5e3d8dc0b5..1c691f6fb48e 100644 --- a/include/linux/fscrypt.h +++ b/include/linux/fscrypt.h @@ -609,11 +609,6 @@ bool fscrypt_mergeable_bio(struct bio *bio, const struct inode *inode, bool fscrypt_mergeable_bio_bh(struct bio *bio, const struct buffer_head *next_bh); -bool fscrypt_dio_supported(struct kiocb *iocb, struct iov_iter *iter); - -int fscrypt_limit_dio_pages(const struct inode *inode, loff_t pos, - int nr_pages); - #else /* CONFIG_FS_ENCRYPTION_INLINE_CRYPT */ static inline bool __fscrypt_inode_uses_inline_crypto(const struct inode *inode) @@ -642,20 +637,6 @@ static inline bool fscrypt_mergeable_bio_bh(struct bio *bio, { return true; } - -static inline bool fscrypt_dio_supported(struct kiocb *iocb, - struct iov_iter *iter) -{ - const struct inode *inode = file_inode(iocb->ki_filp); - - return !fscrypt_needs_contents_encryption(inode); -} - -static inline int fscrypt_limit_dio_pages(const struct inode *inode, loff_t pos, - int nr_pages) -{ - return nr_pages; -} #endif /* !CONFIG_FS_ENCRYPTION_INLINE_CRYPT */ #if IS_ENABLED(CONFIG_FS_ENCRYPTION) && IS_ENABLED(CONFIG_DM_DEFAULT_KEY)