Skip to content

Commit

Permalink
dm-default-key, f2fs, ICE: support dm-default-key with f2fs/ICE
Browse files Browse the repository at this point in the history
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 <[email protected]>
Signed-off-by: Shivaprasad Hongal <[email protected]>
[[email protected]: resolved merged conflicts, compilation issues.]
Signed-off-by: Neeraj Soni <[email protected]>
  • Loading branch information
Jaegeuk Kim authored and Gerrit - the friendly Code Review server committed Nov 5, 2018
1 parent 137abbe commit fab48fe
Show file tree
Hide file tree
Showing 6 changed files with 46 additions and 11 deletions.
5 changes: 4 additions & 1 deletion block/bio.c
Original file line number Diff line number Diff line change
Expand Up @@ -568,8 +568,11 @@ EXPORT_SYMBOL(bio_phys_segments);
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
}
Expand Down
15 changes: 14 additions & 1 deletion fs/crypto/fscrypt_ice.c
Original file line number Diff line number Diff line change
Expand Up @@ -126,16 +126,29 @@ void fscrypt_set_ice_dun(const struct inode *inode, struct bio *bio, u64 dun)
}
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;
Expand Down
11 changes: 7 additions & 4 deletions fs/f2fs/data.c
Original file line number Diff line number Diff line change
Expand Up @@ -448,7 +448,8 @@ int f2fs_submit_page_bio(struct f2fs_io_info *fio)
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);
Expand All @@ -471,6 +472,7 @@ int f2fs_submit_page_write(struct f2fs_io_info *fio)
struct page *bio_page;
struct inode *inode;
bool bio_encrypted;
int bi_crypt_skip;
u64 dun;
int err = 0;

Expand All @@ -497,6 +499,7 @@ int f2fs_submit_page_write(struct f2fs_io_info *fio)
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 */
Expand All @@ -510,7 +513,7 @@ int f2fs_submit_page_write(struct f2fs_io_info *fio)
__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:
Expand All @@ -526,7 +529,7 @@ int f2fs_submit_page_write(struct f2fs_io_info *fio)
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;
}

Expand Down Expand Up @@ -1538,7 +1541,7 @@ static int f2fs_mpage_readpages(struct address_space *mapping,

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;
}
Expand Down
3 changes: 3 additions & 0 deletions include/linux/blk_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ struct bio {
*/
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 */

Expand Down
10 changes: 8 additions & 2 deletions include/linux/fscrypt.h
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,9 @@ static inline int fscrypt_encrypt_symlink(struct inode *inode,
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)
{
Expand All @@ -270,8 +272,12 @@ static inline void fscrypt_set_ice_dun(const struct inode *inode,
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;
}
Expand Down
13 changes: 10 additions & 3 deletions security/pfe/pfk.c
Original file line number Diff line number Diff line change
Expand Up @@ -287,8 +287,8 @@ static int pfk_get_key_for_bio(const struct bio *bio,
{
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);
Expand All @@ -307,7 +307,9 @@ static int pfk_get_key_for_bio(const struct bio *bio,
* 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;
Expand Down Expand Up @@ -469,13 +471,18 @@ int pfk_load_key_end(const struct bio *bio, bool *is_pfe)
*/
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;

Expand Down

0 comments on commit fab48fe

Please sign in to comment.