diff options
Diffstat (limited to 'fs/crypto')
-rw-r--r-- | fs/crypto/fscrypt_private.h | 10 | ||||
-rw-r--r-- | fs/crypto/inline_crypt.c | 7 | ||||
-rw-r--r-- | fs/crypto/policy.c | 18 |
3 files changed, 22 insertions, 13 deletions
diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h index 2d63da48635a..4b113214b53a 100644 --- a/fs/crypto/fscrypt_private.h +++ b/fs/crypto/fscrypt_private.h @@ -296,6 +296,16 @@ union fscrypt_iv { void fscrypt_generate_iv(union fscrypt_iv *iv, u64 lblk_num, const struct fscrypt_info *ci); +/* + * Return the number of bits used by the maximum file logical block number that + * is possible on the given filesystem. + */ +static inline int +fscrypt_max_file_lblk_bits(const struct super_block *sb) +{ + return fls64(sb->s_maxbytes - 1) - sb->s_blocksize_bits; +} + /* fname.c */ bool __fscrypt_fname_encrypted_size(const union fscrypt_policy *policy, u32 orig_len, u32 max_len, diff --git a/fs/crypto/inline_crypt.c b/fs/crypto/inline_crypt.c index 8bfb3ce86476..7d9f6c167de5 100644 --- a/fs/crypto/inline_crypt.c +++ b/fs/crypto/inline_crypt.c @@ -41,9 +41,8 @@ static struct block_device **fscrypt_get_devices(struct super_block *sb, static unsigned int fscrypt_get_dun_bytes(const struct fscrypt_info *ci) { - struct super_block *sb = ci->ci_inode->i_sb; + const struct super_block *sb = ci->ci_inode->i_sb; unsigned int flags = fscrypt_policy_flags(&ci->ci_policy); - int ino_bits = 64, lblk_bits = 64; if (flags & FSCRYPT_POLICY_FLAG_DIRECT_KEY) return offsetofend(union fscrypt_iv, nonce); @@ -55,9 +54,7 @@ static unsigned int fscrypt_get_dun_bytes(const struct fscrypt_info *ci) return sizeof(__le32); /* Default case: IVs are just the file logical block number */ - if (sb->s_cop->get_ino_and_lblk_bits) - sb->s_cop->get_ino_and_lblk_bits(sb, &ino_bits, &lblk_bits); - return DIV_ROUND_UP(lblk_bits, 8); + return DIV_ROUND_UP(fscrypt_max_file_lblk_bits(sb), 8); } /* diff --git a/fs/crypto/policy.c b/fs/crypto/policy.c index f4456ecb3f87..7b34949e49de 100644 --- a/fs/crypto/policy.c +++ b/fs/crypto/policy.c @@ -119,8 +119,7 @@ static bool supported_direct_key_modes(const struct inode *inode, static bool supported_iv_ino_lblk_policy(const struct fscrypt_policy_v2 *policy, const struct inode *inode, - const char *type, - int max_ino_bits, int max_lblk_bits) + const char *type, int max_ino_bits) { struct super_block *sb = inode->i_sb; int ino_bits = 64, lblk_bits = 64; @@ -158,9 +157,14 @@ static bool supported_iv_ino_lblk_policy(const struct fscrypt_policy_v2 *policy, type, sb->s_id); return false; } - if (lblk_bits > max_lblk_bits) { + + /* + * IV_INO_LBLK_64 and IV_INO_LBLK_32 both require that file logical + * block numbers fit in 32 bits. + */ + if (fscrypt_max_file_lblk_bits(sb) > 32) { fscrypt_warn(inode, - "Can't use %s policy on filesystem '%s' because its block numbers are too long", + "Can't use %s policy on filesystem '%s' because its maximum file size is too large", type, sb->s_id); return false; } @@ -239,8 +243,7 @@ static bool fscrypt_supported_v2_policy(const struct fscrypt_policy_v2 *policy, return false; if ((policy->flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64) && - !supported_iv_ino_lblk_policy(policy, inode, "IV_INO_LBLK_64", - 32, 32)) + !supported_iv_ino_lblk_policy(policy, inode, "IV_INO_LBLK_64", 32)) return false; /* @@ -250,8 +253,7 @@ static bool fscrypt_supported_v2_policy(const struct fscrypt_policy_v2 *policy, * implementation limit is 32 bits. */ if ((policy->flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32) && - !supported_iv_ino_lblk_policy(policy, inode, "IV_INO_LBLK_32", - 32, 32)) + !supported_iv_ino_lblk_policy(policy, inode, "IV_INO_LBLK_32", 32)) return false; if (memchr_inv(policy->__reserved, 0, sizeof(policy->__reserved))) { |