For extent-based file contents encryption, filenames will need to generate an IV based on the inode context, while file contents will need to generate an IV based on the extent context. Currently filenames and the first block of file contents both pass fscrypt_generate_iv() a block number of 0, making it hard to distinguish the two cases. To enable distinguishing these two cases for extent-based encryption, this change adjusts all callers to pass U64_MAX when requesting an IV for filename encryption, and then changes fscrypt_generate_iv() to convert U64_MAX to 0 for traditional inode-context encryption. For extent-based encryption, any block number other than U64_MAX will get an IV from the extent context, while U64_MAX will indicate falling back to inode contexts. Signed-off-by: Sweet Tea Dorminy <sweettea-kernel@xxxxxxxxxx> --- fs/crypto/crypto.c | 9 ++++++++- fs/crypto/fname.c | 4 ++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/fs/crypto/crypto.c b/fs/crypto/crypto.c index e78be66bbf01..7fe5979fbea2 100644 --- a/fs/crypto/crypto.c +++ b/fs/crypto/crypto.c @@ -71,7 +71,7 @@ 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. + * For filenames encryption, lblk_num == U64_MAX. * * Keep this in sync with fscrypt_limit_io_blocks(). fscrypt_limit_io_blocks() * needs to know about any IV generation methods where the low bits of IV don't @@ -84,6 +84,13 @@ void fscrypt_generate_iv(union fscrypt_iv *iv, u64 lblk_num, memset(iv, 0, ci->ci_mode->ivsize); + /* + * Filename encryption. For inode-based policies, filenames are + * encrypted as though they are lblk 0. + */ + if (lblk_num == U64_MAX) + lblk_num = 0; + if (flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64) { WARN_ON_ONCE(lblk_num > U32_MAX); WARN_ON_ONCE(ci->ci_inode->i_ino > U32_MAX); diff --git a/fs/crypto/fname.c b/fs/crypto/fname.c index 6c092a1533f7..b3e7e3a66312 100644 --- a/fs/crypto/fname.c +++ b/fs/crypto/fname.c @@ -79,7 +79,7 @@ int fscrypt_fname_encrypt(const struct inode *inode, const struct qstr *iname, memset(out + iname->len, 0, olen - iname->len); /* Initialize the IV */ - fscrypt_generate_iv(&iv, 0, ci); + fscrypt_generate_iv(&iv, U64_MAX, ci); /* Set up the encryption request */ req = skcipher_request_alloc(tfm, GFP_NOFS); @@ -134,7 +134,7 @@ static int fname_decrypt(const struct inode *inode, crypto_req_done, &wait); /* Initialize IV */ - fscrypt_generate_iv(&iv, 0, ci); + fscrypt_generate_iv(&iv, U64_MAX, ci); /* Create decryption request */ sg_init_one(&src_sg, iname->name, iname->len); -- 2.35.1