dm-default-key, f2fs, ICE: support dm-default-key with f2fs/ICE

This patch fixes assigning bi_crypt_key for moving data which was previously
encrypted by f2fs.

Note that, dm-default-key should not assign bi_crypt_key, if bi_crypt_skip is
set.

The issue sceanrios is:

1. write data with user key by f2fs
  -  ENC(KU, IVU, DATA)
2. log out user key
3. read data #1 w/o user key from LBA #a
4. dm-default-key assigns default key
  - DEC(KD, LBA#a, ENC(KU, IVU, DATA))
5. write data #1 w/o user key into LBA #b
6. dm-default-key assigns default key
  - ENC(KD, LBA#b, DEC(KD, LBA#a, ENC(KU, IVU, DATA)))
7. Read DATA out with valid logged-in user key
  - DEC(KU, IVU, ENC(KD, LBA#b, DEC(KD, LBA#a, ENC(KU, IVU, DATA))))

So, this patch introduces bi_crypt_skip to avoid 4. ~ 6 with right flow:
1. write data with user key by f2fs
  -  ENC(KU, IVU, DATA)
2. log out user key
3. read data #1 w/o user key from LBA #a
4. dm-default-key skip to assign default key
  - ENC(KU, IVU, DATA)
5. write data #1 w/o user key into LBA #b
6. dm-default-key skips to assign default key
  - ENC(KU, IVU, DATA)
7. Try to read DATA with valid logged-in user key
  - DEC(KU, IVU, ENC(KU, IVU, DATA))

Issue: 68721442
Change-Id: Icefe85f608b7c3c84beb2bfa4267efd0f3787453
Signed-off-by: Jaegeuk Kim <jaegeuk@google.com>
Signed-off-by: Shivaprasad Hongal <shongal@codeaurora.org>
[neersoni@codeaurora.corg: resolved merged conflicts, compilation issues.]
Signed-off-by: Neeraj Soni <neersoni@codeaurora.org>
diff --git a/block/bio.c b/block/bio.c
index a4c8c99..a44b525 100644
--- a/block/bio.c
+++ b/block/bio.c
@@ -568,8 +568,11 @@
 static inline void bio_clone_crypt_key(struct bio *dst, const struct bio *src)
 {
 #ifdef CONFIG_PFK
-	dst->bi_crypt_key = src->bi_crypt_key;
 	dst->bi_iter.bi_dun = src->bi_iter.bi_dun;
+#ifdef CONFIG_DM_DEFAULT_KEY
+	dst->bi_crypt_key = src->bi_crypt_key;
+	dst->bi_crypt_skip = src->bi_crypt_skip;
+#endif
 	dst->bi_dio_inode = src->bi_dio_inode;
 #endif
 }
diff --git a/fs/crypto/fscrypt_ice.c b/fs/crypto/fscrypt_ice.c
index a76fecf..cd84469 100644
--- a/fs/crypto/fscrypt_ice.c
+++ b/fs/crypto/fscrypt_ice.c
@@ -157,16 +157,29 @@
 }
 EXPORT_SYMBOL(fscrypt_set_ice_dun);
 
+void fscrypt_set_ice_skip(struct bio *bio, int bi_crypt_skip)
+{
+#ifdef CONFIG_DM_DEFAULT_KEY
+	bio->bi_crypt_skip = bi_crypt_skip;
+#endif
+}
+EXPORT_SYMBOL(fscrypt_set_ice_skip);
+
 /*
  * This function will be used for filesystem when deciding to merge bios.
  * Basic assumption is, if inline_encryption is set, single bio has to
  * guarantee consecutive LBAs as well as ino|pg->index.
  */
-bool fscrypt_mergeable_bio(struct bio *bio, u64 dun, bool bio_encrypted)
+bool fscrypt_mergeable_bio(struct bio *bio, u64 dun, bool bio_encrypted,
+						int bi_crypt_skip)
 {
 	if (!bio)
 		return true;
 
+#ifdef CONFIG_DM_DEFAULT_KEY
+	if (bi_crypt_skip != bio->bi_crypt_skip)
+		return false;
+#endif
 	/* if both of them are not encrypted, no further check is needed */
 	if (!bio_dun(bio) && !bio_encrypted)
 		return true;
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index 2a4a4fb..f7f2c13 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -450,7 +450,8 @@
 				1, is_read_io(fio->op), fio->type, fio->temp);
 
 	if (f2fs_may_encrypt_bio(inode, fio))
-	fscrypt_set_ice_dun(inode, bio, PG_DUN(inode, fio->page));
+		fscrypt_set_ice_dun(inode, bio, PG_DUN(inode, fio->page));
+	fscrypt_set_ice_skip(bio, fio->encrypted_page ? 1 : 0);
 
 	if (bio_add_page(bio, page, PAGE_SIZE, 0) < PAGE_SIZE) {
 		bio_put(bio);
@@ -473,6 +474,7 @@
 	struct page *bio_page;
 	struct inode *inode;
 	bool bio_encrypted;
+	int bi_crypt_skip;
 	u64 dun;
 
 	f2fs_bug_on(sbi, is_read_io(fio->op));
@@ -498,6 +500,7 @@
 	bio_page = fio->encrypted_page ? fio->encrypted_page : fio->page;
 	inode = fio->page->mapping->host;
 	dun = PG_DUN(inode, fio->page);
+	bi_crypt_skip = fio->encrypted_page ? 1 : 0;
 	bio_encrypted = f2fs_may_encrypt_bio(inode, fio);
 
 	/* set submitted = true as a return value */
@@ -511,7 +514,7 @@
 		__submit_merged_bio(io);
 
 	/* ICE support */
-	if (!fscrypt_mergeable_bio(io->bio, dun, bio_encrypted))
+	if (!fscrypt_mergeable_bio(io->bio, dun, bio_encrypted, bi_crypt_skip))
 		__submit_merged_bio(io);
 
 alloc_new:
@@ -527,7 +530,7 @@
 						fio->type, fio->temp);
 		if (bio_encrypted)
 			fscrypt_set_ice_dun(inode, io->bio, dun);
-
+		fscrypt_set_ice_skip(io->bio, bi_crypt_skip);
 		io->fio = *fio;
 	}
 
@@ -1539,7 +1542,7 @@
 
 		dun = PG_DUN(inode, page);
 		bio_encrypted = f2fs_may_encrypt_bio(inode, NULL);
-		if (!fscrypt_mergeable_bio(bio, dun, bio_encrypted)) {
+		if (!fscrypt_mergeable_bio(bio, dun, bio_encrypted, 0)) {
 			__submit_bio(F2FS_I_SB(inode), bio, DATA);
 			bio = NULL;
 		}
diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h
index 42ad6b5..a149671 100644
--- a/include/linux/blk_types.h
+++ b/include/linux/blk_types.h
@@ -78,6 +78,9 @@
 	*/
 	struct inode            *bi_dio_inode;
 #endif
+#ifdef CONFIG_DM_DEFAULT_KEY
+	int bi_crypt_skip;
+#endif
 
 	unsigned short		bi_vcnt;	/* how many bio_vec's */
 
diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h
index 1e03614..f5371c2 100644
--- a/include/linux/fscrypt.h
+++ b/include/linux/fscrypt.h
@@ -257,7 +257,9 @@
 extern int fscrypt_using_hardware_encryption(const struct inode *inode);
 extern void fscrypt_set_ice_dun(const struct inode *inode,
 	struct bio *bio, u64 dun);
-extern bool fscrypt_mergeable_bio(struct bio *bio, u64 dun, bool bio_encrypted);
+extern bool fscrypt_mergeable_bio(struct bio *bio, u64 dun, bool bio_encrypted,
+		int bi_crypt_skip);
+extern void fscrypt_set_ice_skip(struct bio *bio, int bi_crypt_skip);
 #else
 static inline int fscrypt_using_hardware_encryption(const struct inode *inode)
 {
@@ -270,8 +272,12 @@
 	return;
 }
 
+static inline void fscrypt_set_ice_skip(struct bio *bio, int bi_crypt_skip)
+{
+}
+
 static inline bool fscrypt_mergeable_bio(struct bio *bio,
-	u64 dun, bool bio_encrypted)
+	u64 dun, bool bio_encrypted, int bi_crypt_skip)
 {
 	return true;
 }
diff --git a/security/pfe/pfk.c b/security/pfe/pfk.c
index f9a6292..6518ac9 100644
--- a/security/pfe/pfk.c
+++ b/security/pfe/pfk.c
@@ -287,8 +287,8 @@
 {
 	const struct inode *inode;
 	enum pfe_type which_pfe;
-	const struct blk_encryption_key *key;
 	char *s_type = NULL;
+	const struct blk_encryption_key *key = NULL;
 
 	inode = pfk_bio_get_inode(bio);
 	which_pfe = pfk_get_pfe_type(inode);
@@ -307,7 +307,9 @@
 	 * bio is not for an encrypted file.  Use ->bi_crypt_key if it was set.
 	 * Otherwise, don't encrypt/decrypt the bio.
 	 */
+#ifdef CONFIG_DM_DEFAULT_KEY
 	key = bio->bi_crypt_key;
+#endif
 	if (!key) {
 		*is_pfe = false;
 		return -EINVAL;
@@ -469,13 +471,18 @@
  */
 bool pfk_allow_merge_bio(const struct bio *bio1, const struct bio *bio2)
 {
-	const struct blk_encryption_key *key1;
-	const struct blk_encryption_key *key2;
+	const struct blk_encryption_key *key1 = NULL;
+	const struct blk_encryption_key *key2 = NULL;
 	const struct inode *inode1;
 	const struct inode *inode2;
 	enum pfe_type which_pfe1;
 	enum pfe_type which_pfe2;
 
+#ifdef CONFIG_DM_DEFAULT_KEY
+	key1 = bio1->bi_crypt_key;
+	key2 = bio2->bi_crypt_key;
+#endif
+
 	if (!pfk_is_ready())
 		return false;