Linux EXT4 FS development
 help / color / mirror / Atom feed
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


  reply	other threads:[~2026-11-03 15:32 UTC|newest]

Thread overview: 10+ 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 page size Baokun Li
2026-11-03 15:31 ` Baokun Li [this message]
2026-11-03 15:44   ` [PATCH 1/4] fscrypt: Cap data units at the " sashiko-bot
2026-11-03 22:40   ` 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:45   ` sashiko-bot
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:40   ` sashiko-bot
2026-11-03 15:31 ` [PATCH 4/4] ext4: allow large folios and bs > ps encryption Baokun Li
2026-11-03 15:42   ` sashiko-bot

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