From: Baokun Li <libaokun@linux.alibaba.com>
To: linux-fscrypt@vger.kernel.org
Cc: ebiggers@kernel.org, jaegeuk@kernel.org, tytso@mit.edu,
linux-ext4@vger.kernel.org, adilger.kernel@dilger.ca,
jack@suse.cz, yi.zhang@huawei.com, ojaswin@linux.ibm.com,
ritesh.list@gmail.com, linux-kernel@vger.kernel.org
Subject: [PATCH 1/4] fscrypt: Cap data units at the page size
Date: Tue, 3 Nov 2026 23:31:29 +0800 [thread overview]
Message-ID: <20261103153132.4154855-2-libaokun@linux.alibaba.com> (raw)
In-Reply-To: <20261103153132.4154855-1-libaokun@linux.alibaba.com>
blk-crypto-fallback cannot handle a data unit larger than a page:
it walks the bio one page-sized segment at a time, so a data unit
that spans multiple pages never ends on a segment boundary and
the bio fails with BLK_STS_INVAL after the I/O was already
reported to userspace as successful, losing data.
Fix this in fscrypt_supported_v2_policy() by rejecting any v2 policy
that explicitly specifies a data unit size larger than the page size.
A v1 policy always uses the block size as its data unit size,
so fscrypt_supported_v1_policy() has to reject any v1 policy on
a filesystem with a block size larger than the page size (e.g. ext4).
A v2 policy with no data unit size specified uses the block size too,
but rejection is not necessary there: sub-block data units are
supported, so it is enough to cap the data unit bits at PAGE_SHIFT in
fscrypt_policy_v2_du_bits().
Note that a filesystem whose block size exceeds 4K then cannot be
made compatible across page sizes (e.g. 4K and 64K); this can be
avoided by explicitly specifying a data unit size of 4K or smaller.
Suggested-by: Eric Biggers <ebiggers@kernel.org>
Link: https://lore.kernel.org/r/20261015185325.GG2170687@google.com
Signed-off-by: Baokun Li <libaokun@linux.alibaba.com>
---
Documentation/filesystems/fscrypt.rst | 19 +++++++++++++++----
fs/crypto/fscrypt_private.h | 4 +++-
fs/crypto/policy.c | 11 ++++++++++-
3 files changed, 28 insertions(+), 6 deletions(-)
diff --git a/Documentation/filesystems/fscrypt.rst b/Documentation/filesystems/fscrypt.rst
index 6e2e511a70bb..78251a9706ba 100644
--- a/Documentation/filesystems/fscrypt.rst
+++ b/Documentation/filesystems/fscrypt.rst
@@ -649,8 +649,9 @@ This structure must be initialized as follows:
Not all filesystems support setting ``log2_data_unit_size``. ext4
and f2fs support it since Linux v6.7. On filesystems that support
it, the supported nonzero values are 9 through the log2 of the
- filesystem block size, inclusively. The default value of 0 selects
- the filesystem block size.
+ filesystem block size, inclusively, but no greater than the log2 of
+ the page size. The default value of 0 selects the filesystem block
+ size, or the page size if the block size is larger.
The main use case for ``log2_data_unit_size`` is for selecting a
data unit size smaller than the filesystem block size for
@@ -659,8 +660,18 @@ This structure must be initialized as follows:
useful for checking which data unit sizes are supported by a
particular system's inline encryption hardware.
- Leave this field zeroed unless you are certain you need it. Using
- an unnecessarily small data unit size reduces performance.
+ A v1 policy has no ``log2_data_unit_size`` and always uses the
+ filesystem block size, so it cannot be used on a filesystem whose
+ block size is larger than the page size.
+
+ A v2 policy on such a filesystem falls back to the page size, so
+ the data unit size depends on the machine's page size and the data
+ becomes unreadable elsewhere. An image portable across page sizes
+ should explicitly specify a data unit size of 4096 or smaller.
+
+ Leave this field zeroed unless you are certain one of the reasons
+ above applies. Using an unnecessarily small data unit size reduces
+ performance.
- For v2 encryption policies, ``__reserved`` must be zeroed.
diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h
index e602c31b3844..0dc158563e71 100644
--- a/fs/crypto/fscrypt_private.h
+++ b/fs/crypto/fscrypt_private.h
@@ -203,7 +203,9 @@ static inline int
fscrypt_policy_v2_du_bits(const struct fscrypt_policy_v2 *policy,
const struct inode *inode)
{
- return policy->log2_data_unit_size ?: inode->i_blkbits;
+ if (policy->log2_data_unit_size)
+ return policy->log2_data_unit_size;
+ return min_t(unsigned int, inode->i_blkbits, PAGE_SHIFT);
}
static inline int
diff --git a/fs/crypto/policy.c b/fs/crypto/policy.c
index 6dd510f93e6d..84c496da248e 100644
--- a/fs/crypto/policy.c
+++ b/fs/crypto/policy.c
@@ -228,6 +228,14 @@ static bool fscrypt_supported_v1_policy(const struct fscrypt_policy_v1 *policy,
return false;
}
+ if (inode->i_sb->s_cop->is_block_based &&
+ inode->i_blkbits > PAGE_SHIFT) {
+ /* v1 has no way to select a sub-block data unit size. */
+ fscrypt_warn(inode,
+ "v1 policies can't be used on fs with block size > page size");
+ return false;
+ }
+
return true;
}
@@ -270,7 +278,8 @@ static bool fscrypt_supported_v2_policy(const struct fscrypt_policy_v2 *policy,
return false;
}
if (policy->log2_data_unit_size > inode->i_blkbits ||
- policy->log2_data_unit_size < SECTOR_SHIFT /* 9 */) {
+ policy->log2_data_unit_size < SECTOR_SHIFT /* 9 */ ||
+ policy->log2_data_unit_size > PAGE_SHIFT) {
fscrypt_warn(inode,
"Unsupported log2_data_unit_size in encryption policy: %d",
policy->log2_data_unit_size);
--
2.43.7
next prev parent reply other threads:[~2026-11-03 15:32 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-03 15:31 [PATCH 0/4] ext4: support encryption with block size larger than " Baokun Li
2026-11-03 15:31 ` Baokun Li [this message]
2026-11-03 22:40 ` [PATCH 1/4] fscrypt: Cap data units at the " Eric Biggers
2026-11-03 15:31 ` [PATCH 2/4] fscrypt: Validate the test_dummy_encryption policy for new inodes Baokun Li
2026-11-03 15:31 ` [PATCH 3/4] ext4: don't put a DUN wraparound in the middle of a read bio Baokun Li
2026-11-03 15:31 ` [PATCH 4/4] ext4: allow large folios and bs > ps encryption Baokun Li
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261103153132.4154855-2-libaokun@linux.alibaba.com \
--to=libaokun@linux.alibaba.com \
--cc=adilger.kernel@dilger.ca \
--cc=ebiggers@kernel.org \
--cc=jack@suse.cz \
--cc=jaegeuk@kernel.org \
--cc=linux-ext4@vger.kernel.org \
--cc=linux-fscrypt@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=ojaswin@linux.ibm.com \
--cc=ritesh.list@gmail.com \
--cc=tytso@mit.edu \
--cc=yi.zhang@huawei.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®