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;