From: Boojin Kim Date: Thu, 25 Oct 2018 03:20:58 +0000 (+0900) Subject: [RAMEN9610-8702][COMMON] f2fs: support fmp encryption X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=51cc621509de826e05d9388699e95c040208b7ae;p=GitHub%2FLineageOS%2Fandroid_kernel_motorola_exynos9610.git [RAMEN9610-8702][COMMON] f2fs: support fmp encryption Change-Id: I9ce6fdb2367c031a0b776cb77fb54fac3944a43a Signed-off-by: Boojin Kim --- diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 0f42c7ae35e6..5f86acecfc81 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -67,6 +67,37 @@ struct bio_post_read_ctx { unsigned int enabled_steps; }; +static inline bool f2fs_may_encrypt_bio(struct inode *inode, + struct f2fs_io_info *fio) +{ + if (fio && (fio->type != DATA || fio->encrypted_page)) + return false; + + return (f2fs_encrypted_file(inode) && + fscrypt_disk_encrypted(inode)); +} + +static inline bool f2fs_bio_disk_encrypted(unsigned int bi_opf) +{ + if (bi_opf & REQ_CRYPT) + return true; + else + return false; +} + +static bool f2fs_mergeable_bio(struct bio *bio, void *ci, bool bio_encrypted) +{ + if (!bio) + return true; + + /* if both of them are not encrypted, no further check is needed */ + if (!f2fs_bio_disk_encrypted(bio->bi_opf) && !bio_encrypted) + return true; + + /* ICE allows only consecutive iv_key stream. */ + return bio->bi_aux_private == ci; +} + static void __read_end_io(struct bio *bio) { struct page *page; @@ -132,6 +163,9 @@ static void f2fs_read_end_io(struct bio *bio) } #endif + if(f2fs_bio_disk_encrypted(bio->bi_opf)) + goto end_io; + if (f2fs_bio_post_read_required(bio)) { struct bio_post_read_ctx *ctx = bio->bi_private; @@ -140,6 +174,7 @@ static void f2fs_read_end_io(struct bio *bio) return; } +end_io: __read_end_io(bio); } @@ -307,7 +342,10 @@ static void __submit_merged_bio(struct f2fs_bio_info *io) if (!io->bio) return; - bio_set_op_attrs(io->bio, fio->op, fio->op_flags); + if (f2fs_bio_disk_encrypted(io->bio->bi_opf)) + bio_set_op_attrs(io->bio, fio->op, fio->op_flags | REQ_CRYPT); + else + bio_set_op_attrs(io->bio, fio->op, fio->op_flags); if (is_read_io(fio->op)) trace_f2fs_prepare_read_bio(io->sbi->sb, fio->type, io->bio); @@ -439,6 +477,7 @@ int f2fs_submit_page_bio(struct f2fs_io_info *fio) struct bio *bio; struct page *page = fio->encrypted_page ? fio->encrypted_page : fio->page; + struct inode *inode = fio->page->mapping->host; verify_block_addr(fio, fio->new_blkaddr); trace_f2fs_submit_page_bio(page, fio); @@ -455,6 +494,9 @@ int f2fs_submit_page_bio(struct f2fs_io_info *fio) fio->op_flags |= fio->encrypted_page ? REQ_NOENCRYPT : 0; bio_set_op_attrs(bio, fio->op, fio->op_flags); + if (f2fs_may_encrypt_bio(inode, fio)) + fscrypt_set_bio(inode, bio); + __submit_bio(fio->sbi, bio, fio->type); if (!is_read_io(fio->op)) @@ -469,6 +511,8 @@ int f2fs_submit_page_write(struct f2fs_io_info *fio) struct f2fs_bio_info *io = sbi->write_io[btype] + fio->temp; struct page *bio_page; int err = 0; + struct inode *inode; + bool bio_encrypted; f2fs_bug_on(sbi, is_read_io(fio->op)); @@ -491,6 +535,8 @@ next: verify_block_addr(fio, fio->new_blkaddr); bio_page = fio->encrypted_page ? fio->encrypted_page : fio->page; + inode = fio->page->mapping->host; + bio_encrypted = f2fs_may_encrypt_bio(inode, fio); fio->op_flags |= fio->encrypted_page ? REQ_NOENCRYPT : 0; /* set submitted = true as a return value */ @@ -502,6 +548,10 @@ next: (io->fio.op != fio->op || io->fio.op_flags != fio->op_flags) || !__same_bdev(sbi, fio->new_blkaddr, io->bio))) __submit_merged_bio(io); + + if (!f2fs_mergeable_bio(io->bio, fscrypt_get_diskcipher(inode), bio_encrypted)) + __submit_merged_bio(io); + alloc_new: if (io->bio == NULL) { if ((fio->type == DATA || fio->type == NODE) && @@ -513,6 +563,9 @@ alloc_new: io->bio = __bio_alloc(sbi, fio->new_blkaddr, fio->io_wbc, BIO_MAX_PAGES, false, fio->type, fio->temp); + if (bio_encrypted) + fscrypt_set_bio(inode, io->bio); + io->fio = *fio; } @@ -551,7 +604,7 @@ static struct bio *f2fs_grab_read_bio(struct inode *inode, block_t blkaddr, bio->bi_end_io = f2fs_read_end_io; bio_set_op_attrs(bio, REQ_OP_READ, 0); - if (f2fs_encrypted_file(inode)) + if (f2fs_encrypted_file(inode) && !fscrypt_disk_encrypted(inode)) post_read_steps |= 1 << STEP_DECRYPT; if (post_read_steps) { ctx = mempool_alloc(bio_post_read_ctx_pool, GFP_NOFS); @@ -587,6 +640,10 @@ static int f2fs_submit_page_read(struct inode *inode, struct page *page, bio_put(bio); return -EFAULT; } + + if (f2fs_may_encrypt_bio(inode, NULL)) + fscrypt_set_bio(inode, bio); + __submit_bio(F2FS_I_SB(inode), bio, DATA); return 0; } @@ -1442,6 +1499,7 @@ static int f2fs_mpage_readpages(struct address_space *mapping, sector_t last_block_in_file; sector_t block_nr; struct f2fs_map_blocks map; + bool bio_encrypted; map.m_pblk = 0; map.m_lblk = 0; @@ -1519,12 +1577,21 @@ submit_and_realloc: __submit_bio(F2FS_I_SB(inode), bio, DATA); bio = NULL; } + + bio_encrypted = f2fs_may_encrypt_bio(inode, NULL); + if (!f2fs_mergeable_bio(bio, fscrypt_get_diskcipher(inode), bio_encrypted)) { + __submit_bio(F2FS_I_SB(inode), bio, DATA); + bio = NULL; + } + if (bio == NULL) { bio = f2fs_grab_read_bio(inode, block_nr, nr_pages); if (IS_ERR(bio)) { bio = NULL; goto set_error_page; } + if (f2fs_may_encrypt_bio(inode, NULL)) + fscrypt_set_bio(inode, bio); } if (bio_add_page(bio, page, blocksize, 0) < blocksize) @@ -1596,6 +1663,9 @@ static int encrypt_one_page(struct f2fs_io_info *fio) f2fs_wait_on_block_writeback(fio->sbi, fio->old_blkaddr); retry_encrypt: + if (fscrypt_disk_encrypted(inode)) + return 0; + fio->encrypted_page = fscrypt_encrypt_page(inode, fio->page, PAGE_SIZE, 0, fio->page->index, gfp_flags); if (!IS_ERR(fio->encrypted_page)) diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index bc633925d7b7..5be16660cd74 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -3279,7 +3279,8 @@ static inline bool f2fs_may_encrypt(struct inode *inode) static inline bool f2fs_force_buffered_io(struct inode *inode, int rw) { - return (f2fs_post_read_required(inode) || + return ((f2fs_post_read_required(inode) && + !fscrypt_disk_encrypted(inode)) || (rw == WRITE && test_opt(F2FS_I_SB(inode), LFS)) || F2FS_I_SB(inode)->s_ndevs); }