@@ -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,
@@ -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);
}
/*
@@ -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;
@@ -154,13 +153,18 @@ static bool supported_iv_ino_lblk_policy(const struct fscrypt_policy_v2 *policy,
sb->s_cop->get_ino_and_lblk_bits(sb, &ino_bits, &lblk_bits);
if (ino_bits > max_ino_bits) {
fscrypt_warn(inode,
- "Can't use %s policy on filesystem '%s' because its inode numbers are too long",
+ "Can't use %s policy on filesystem '%s' because its maximum inode number is too large",
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))) {