public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] fscrypt: add software key support for filesystem-managed data
@ 2026-04-21  7:57 LiaoYuanhong-vivo
  2026-04-22 23:27 ` Eric Biggers
  0 siblings, 1 reply; 3+ messages in thread
From: LiaoYuanhong-vivo @ 2026-04-21  7:57 UTC (permalink / raw)
  To: ebiggers; +Cc: tytso, jaegeuk, liaoyuanhong, linux-fscrypt, linux-kernel

Some filesystems store small file contents in filesystem-managed regions
rather than in regular data blocks submitted through bios. One example is
F2FS inline_data, where the payload is stored inside the inode node block.
Such regions still need to follow the inode's fscrypt contents encryption
semantics, but they cannot rely on blk-crypto because they are not
submitted as standalone file data bios.

As a result, when blk-crypto is enabled, mechanisms such as inline_data are
typically disabled outright. However, it is desirable to re-enable such
space-saving features while still preserving the required encryption
semantics.

To support this, add fscrypt_crypt_fs_layer_page_inplace(), a helper that
encrypts or decrypts a caller-provided page region in place using
filesystem-layer software crypto and the inode's contents encryption
policy.

This support is limited to v2 encryption policies. v1 policies do not
provide the key setup model used here, so this path returns -EOPNOTSUPP for
v1. Hardware-wrapped keys are not supported either, since deriving a
software skcipher key requires software-accessible key material, which
conflicts with the hardware-wrapped key model.

When the inode's normal contents path uses blk-crypto, fscrypt may not have
a software skcipher key prepared for the inode contents key. Add an
optional filesystem-layer prepared key to fscrypt_inode_info. This key is
derived using the same v2 contents-encryption KDF as the normal contents
key, but is prepared as a software skcipher key and is used only by the new
filesystem-layer helper.

Signed-off-by: LiaoYuanhong-vivo <liaoyuanhong@vivo.com>
---
 fs/crypto/crypto.c          |  89 ++++++++++++++++++++++
 fs/crypto/fscrypt_private.h |  20 +++++
 fs/crypto/keysetup.c        | 143 ++++++++++++++++++++++++++++++++----
 include/linux/fscrypt.h     |  38 ++++++++++
 4 files changed, 277 insertions(+), 13 deletions(-)

diff --git a/fs/crypto/crypto.c b/fs/crypto/crypto.c
index 570a2231c945..63a5e0ad957c 100644
--- a/fs/crypto/crypto.c
+++ b/fs/crypto/crypto.c
@@ -144,6 +144,95 @@ int fscrypt_crypt_data_unit(const struct fscrypt_inode_info *ci,
 	return err;
 }
 
+static const struct fscrypt_prepared_key *
+fscrypt_fs_layer_key(const struct fscrypt_inode_info *ci)
+{
+#ifdef CONFIG_FS_ENCRYPTION_INLINE_CRYPT
+	if (!fscrypt_fs_layer_key_prepared(ci))
+		return NULL;
+	return &ci->ci_fs_layer_key;
+#else
+	return NULL;
+#endif
+}
+
+static int fscrypt_crypt_fs_layer_page_prepare(const struct inode *inode,
+				    const struct fscrypt_inode_info **ci_ret,
+				    const struct fscrypt_prepared_key **prep_key_ret)
+{
+	struct fscrypt_inode_info *ci = fscrypt_get_inode_info(inode);
+	const struct fscrypt_prepared_key *prep_key;
+	int err;
+
+	if (!ci)
+		return -ENOKEY;
+
+	err = fscrypt_prepare_fs_layer_key(ci);
+	if (err)
+		return err;
+	prep_key = fscrypt_fs_layer_key(ci);
+	if (!prep_key || !prep_key->tfm)
+		return -ENOKEY;
+
+	*ci_ret = ci;
+	*prep_key_ret = prep_key;
+	return 0;
+}
+
+static int
+fscrypt_crypt_page_inplace_with_key(const struct fscrypt_inode_info *ci,
+				    const struct fscrypt_prepared_key *prep_key,
+				    struct page *page, unsigned int len,
+				    unsigned int offs, u64 dun, bool encrypt)
+{
+	struct crypto_sync_skcipher *tfm = prep_key->tfm;
+
+	SYNC_SKCIPHER_REQUEST_ON_STACK(req, tfm);
+	union fscrypt_iv iv;
+	struct scatterlist sg;
+	int err;
+
+	if (WARN_ON_ONCE(len <= 0))
+		return -EINVAL;
+	if (WARN_ON_ONCE(len % FSCRYPT_CONTENTS_ALIGNMENT != 0))
+		return -EINVAL;
+
+	fscrypt_generate_iv(&iv, dun, ci);
+
+	skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG |
+				       CRYPTO_TFM_REQ_MAY_SLEEP, NULL, NULL);
+	sg_init_table(&sg, 1);
+	sg_set_page(&sg, page, len, offs);
+	skcipher_request_set_crypt(req, &sg, &sg, len, &iv);
+	if (encrypt)
+		err = crypto_skcipher_encrypt(req);
+	else
+		err = crypto_skcipher_decrypt(req);
+	if (err)
+		fscrypt_err(ci->ci_inode,
+			    "%scryption failed for data unit %llu: %d",
+			    (encrypt ? "En" : "De"), dun, err);
+	return err;
+}
+
+int fscrypt_crypt_fs_layer_page_inplace(const struct inode *inode,
+					struct page *page, unsigned int len,
+					unsigned int offs, u64 dun,
+					bool encrypt)
+{
+	const struct fscrypt_inode_info *ci;
+	const struct fscrypt_prepared_key *prep_key;
+	int err;
+
+	err = fscrypt_crypt_fs_layer_page_prepare(inode, &ci, &prep_key);
+	if (err)
+		return err;
+
+	return fscrypt_crypt_page_inplace_with_key(ci, prep_key, page, len, offs,
+					       dun, encrypt);
+}
+EXPORT_SYMBOL_GPL(fscrypt_crypt_fs_layer_page_inplace);
+
 /**
  * fscrypt_encrypt_pagecache_blocks() - Encrypt data from a pagecache folio
  * @folio: the locked pagecache folio containing the data to encrypt
diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h
index 8d3c278a7591..760e781f3921 100644
--- a/fs/crypto/fscrypt_private.h
+++ b/fs/crypto/fscrypt_private.h
@@ -266,6 +266,13 @@ struct fscrypt_inode_info {
 	 * the traditional filesystem-layer encryption.
 	 */
 	u8 ci_inlinecrypt : 1;
+
+	/*
+	 * Optional filesystem-layer software key for data regions that cannot
+	 * be handled by blk-crypto.
+	 */
+	struct fscrypt_prepared_key ci_fs_layer_key;
+	u8 ci_owns_fs_layer_key : 1;
 #endif
 
 	/* True if ci_dirhash_key is initialized */
@@ -323,6 +330,18 @@ struct fscrypt_inode_info {
 	u8 ci_nonce[FSCRYPT_FILE_NONCE_SIZE];
 };
 
+#ifdef CONFIG_FS_ENCRYPTION_INLINE_CRYPT
+static inline bool
+fscrypt_fs_layer_key_prepared(const struct fscrypt_inode_info *ci)
+{
+	/*
+	 * Pairs with the smp_store_release() in
+	 * fscrypt_prepare_software_key().
+	 */
+	return smp_load_acquire(&ci->ci_fs_layer_key.tfm);
+}
+#endif
+
 typedef enum {
 	FS_DECRYPT = 0,
 	FS_ENCRYPT,
@@ -722,6 +741,7 @@ void fscrypt_destroy_prepared_key(struct super_block *sb,
 
 int fscrypt_set_per_file_enc_key(struct fscrypt_inode_info *ci,
 				 const u8 *raw_key);
+int fscrypt_prepare_fs_layer_key(struct fscrypt_inode_info *ci);
 
 void fscrypt_derive_dirhash_key(struct fscrypt_inode_info *ci,
 				const struct fscrypt_master_key *mk);
diff --git a/fs/crypto/keysetup.c b/fs/crypto/keysetup.c
index ce327bfdada4..3a68175aa664 100644
--- a/fs/crypto/keysetup.c
+++ b/fs/crypto/keysetup.c
@@ -144,6 +144,130 @@ fscrypt_allocate_skcipher(struct fscrypt_mode *mode, const u8 *raw_key,
 	return ERR_PTR(err);
 }
 
+static int fscrypt_prepare_software_key(struct fscrypt_prepared_key *prep_key,
+					const u8 *raw_key,
+					const struct fscrypt_inode_info *ci)
+{
+	struct crypto_sync_skcipher *tfm;
+
+	tfm = fscrypt_allocate_skcipher(ci->ci_mode, raw_key, ci->ci_inode);
+	if (IS_ERR(tfm))
+		return PTR_ERR(tfm);
+	/*
+	 * Pairs with fscrypt_is_key_prepared() and
+	 * fscrypt_fs_layer_key_prepared().
+	 */
+	smp_store_release(&prep_key->tfm, tfm);
+	return 0;
+}
+
+#ifdef CONFIG_FS_ENCRYPTION_INLINE_CRYPT
+static int
+fscrypt_derive_v2_fs_layer_key(const struct fscrypt_inode_info *ci,
+			       const struct fscrypt_master_key *mk,
+			       u8 *raw_key)
+{
+	const struct super_block *sb = ci->ci_inode->i_sb;
+	const u8 mode_num = ci->ci_mode - fscrypt_modes;
+	u8 hkdf_info[sizeof(mode_num) + sizeof(sb->s_uuid)];
+	u8 hkdf_context;
+	unsigned int hkdf_infolen = 0;
+	bool include_fs_uuid = false;
+
+	if (ci->ci_policy.v2.flags & FSCRYPT_POLICY_FLAG_DIRECT_KEY) {
+		hkdf_context = HKDF_CONTEXT_DIRECT_KEY;
+	} else if (ci->ci_policy.v2.flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64) {
+		hkdf_context = HKDF_CONTEXT_IV_INO_LBLK_64_KEY;
+		include_fs_uuid = true;
+	} else if (ci->ci_policy.v2.flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32) {
+		hkdf_context = HKDF_CONTEXT_IV_INO_LBLK_32_KEY;
+		include_fs_uuid = true;
+	} else {
+		fscrypt_hkdf_expand(&mk->mk_secret.hkdf,
+				    HKDF_CONTEXT_PER_FILE_ENC_KEY,
+				    ci->ci_nonce, FSCRYPT_FILE_NONCE_SIZE,
+				    raw_key, ci->ci_mode->keysize);
+		return 0;
+	}
+
+	/* Keep this per-mode KDF in sync with setup_per_mode_enc_key(). */
+	BUILD_BUG_ON(sizeof(mode_num) != 1);
+	BUILD_BUG_ON(sizeof(sb->s_uuid) != 16);
+	BUILD_BUG_ON(sizeof(hkdf_info) != 17);
+	hkdf_info[hkdf_infolen++] = mode_num;
+	if (include_fs_uuid) {
+		memcpy(&hkdf_info[hkdf_infolen], &sb->s_uuid,
+		       sizeof(sb->s_uuid));
+		hkdf_infolen += sizeof(sb->s_uuid);
+	}
+	fscrypt_hkdf_expand(&mk->mk_secret.hkdf, hkdf_context, hkdf_info,
+			    hkdf_infolen, raw_key, ci->ci_mode->keysize);
+	return 0;
+}
+
+static int
+fscrypt_derive_fs_layer_key(const struct fscrypt_inode_info *ci,
+			    const struct fscrypt_master_key *mk,
+			    u8 *raw_key)
+{
+	switch (ci->ci_policy.version) {
+	case FSCRYPT_POLICY_V1:
+		return -EOPNOTSUPP;
+	case FSCRYPT_POLICY_V2:
+		return fscrypt_derive_v2_fs_layer_key(ci, mk, raw_key);
+	default:
+		WARN_ON_ONCE(1);
+		return -EINVAL;
+	}
+}
+
+int fscrypt_prepare_fs_layer_key(struct fscrypt_inode_info *ci)
+{
+	struct fscrypt_master_key *mk = ci->ci_master_key;
+	u8 raw_key[FSCRYPT_MAX_RAW_KEY_SIZE];
+	int err = 0;
+
+	if (!fscrypt_using_inline_encryption(ci))
+		return -EOPNOTSUPP;
+	if (fscrypt_fs_layer_key_prepared(ci))
+		return 0;
+	if (!mk)
+		return -EOPNOTSUPP;
+
+	down_read(&mk->mk_sem);
+	if (!mk->mk_present) {
+		err = -ENOKEY;
+		goto out_unlock_key;
+	}
+	if (mk->mk_secret.is_hw_wrapped) {
+		err = -EOPNOTSUPP;
+		goto out_unlock_key;
+	}
+
+	mutex_lock(&fscrypt_mode_key_setup_mutex);
+	/* Another thread may have prepared the fs-layer key while we waited. */
+	if (fscrypt_fs_layer_key_prepared(ci))
+		goto out_unlock_mutex;
+	err = fscrypt_derive_fs_layer_key(ci, mk, raw_key);
+	if (!err) {
+		ci->ci_owns_fs_layer_key = true;
+		err = fscrypt_prepare_software_key(&ci->ci_fs_layer_key,
+						   raw_key, ci);
+	}
+	memzero_explicit(raw_key, ci->ci_mode->keysize);
+out_unlock_mutex:
+	mutex_unlock(&fscrypt_mode_key_setup_mutex);
+out_unlock_key:
+	up_read(&mk->mk_sem);
+	return err;
+}
+#else
+int fscrypt_prepare_fs_layer_key(struct fscrypt_inode_info *ci)
+{
+	return -EOPNOTSUPP;
+}
+#endif
+
 /*
  * Prepare the crypto transform object or blk-crypto key in @prep_key, given the
  * raw key, encryption mode (@ci->ci_mode), flag indicating which encryption
@@ -153,24 +277,12 @@ fscrypt_allocate_skcipher(struct fscrypt_mode *mode, const u8 *raw_key,
 int fscrypt_prepare_key(struct fscrypt_prepared_key *prep_key,
 			const u8 *raw_key, const struct fscrypt_inode_info *ci)
 {
-	struct crypto_sync_skcipher *tfm;
-
 	if (fscrypt_using_inline_encryption(ci))
 		return fscrypt_prepare_inline_crypt_key(prep_key, raw_key,
 							ci->ci_mode->keysize,
 							false, ci);
 
-	tfm = fscrypt_allocate_skcipher(ci->ci_mode, raw_key, ci->ci_inode);
-	if (IS_ERR(tfm))
-		return PTR_ERR(tfm);
-	/*
-	 * Pairs with the smp_load_acquire() in fscrypt_is_key_prepared().
-	 * I.e., here we publish ->tfm with a RELEASE barrier so that
-	 * concurrent tasks can ACQUIRE it.  Note that this concurrency is only
-	 * possible for per-mode keys, not for per-file keys.
-	 */
-	smp_store_release(&prep_key->tfm, tfm);
-	return 0;
+	return fscrypt_prepare_software_key(prep_key, raw_key, ci);
 }
 
 /* Destroy a crypto transform object and/or blk-crypto key. */
@@ -558,6 +670,11 @@ static void put_crypt_info(struct fscrypt_inode_info *ci)
 	else if (ci->ci_owns_key)
 		fscrypt_destroy_prepared_key(ci->ci_inode->i_sb,
 					     &ci->ci_enc_key);
+#ifdef CONFIG_FS_ENCRYPTION_INLINE_CRYPT
+	if (ci->ci_owns_fs_layer_key)
+		fscrypt_destroy_prepared_key(ci->ci_inode->i_sb,
+					     &ci->ci_fs_layer_key);
+#endif
 
 	mk = ci->ci_master_key;
 	if (mk) {
diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h
index 54712ec61ffb..ede451614461 100644
--- a/include/linux/fscrypt.h
+++ b/include/linux/fscrypt.h
@@ -344,8 +344,38 @@ static inline void fscrypt_prepare_dentry(struct dentry *dentry,
 /* crypto.c */
 void fscrypt_enqueue_decrypt_work(struct work_struct *);
 
+/**
+ * fscrypt_crypt_fs_layer_page_inplace() - encrypt or decrypt one page region
+ *                                         in place
+ * @inode: encrypted inode whose contents encryption policy is used
+ * @page: page containing the region to encrypt or decrypt
+ * @len: length of the region in bytes
+ * @offs: byte offset of the region within @page
+ * @dun: data unit number to use as the IV/index
+ * @encrypt: true to encrypt, false to decrypt
+ *
+ * Encrypt or decrypt @len bytes in @page at @offs using @inode's contents
+ * encryption semantics, but always using filesystem-layer software crypto.
+ * If @inode's normal contents path uses blk-crypto, this may require fscrypt
+ * to derive and prepare an additional filesystem-layer software key.
+ *
+ * This is intended for filesystem-managed data regions that are not submitted
+ * through a bio and therefore cannot be encrypted or decrypted by blk-crypto.
+ * The caller must ensure that @offs and @len stay within @page and satisfy the
+ * block-size requirements of @inode's encryption mode.
+ *
+ * Return: 0 on success, -EINVAL for invalid arguments, -ENOKEY if the inode's
+ * key is unavailable, -EOPNOTSUPP if filesystem-layer software crypto is
+ * unsupported for this inode/key, or another negative error from the crypto
+ * API.
+ */
+int fscrypt_crypt_fs_layer_page_inplace(const struct inode *inode,
+					struct page *page, unsigned int len,
+					unsigned int offs, u64 dun,
+					bool encrypt);
 struct page *fscrypt_encrypt_pagecache_blocks(struct folio *folio,
 		size_t len, size_t offs, gfp_t gfp_flags);
+
 int fscrypt_encrypt_block_inplace(const struct inode *inode, struct page *page,
 				  unsigned int len, unsigned int offs,
 				  u64 lblk_num);
@@ -541,6 +571,14 @@ static inline int fscrypt_decrypt_block_inplace(const struct inode *inode,
 	return -EOPNOTSUPP;
 }
 
+static inline int
+fscrypt_crypt_fs_layer_page_inplace(const struct inode *inode,
+				    struct page *page, unsigned int len,
+				    unsigned int offs, u64 dun, bool encrypt)
+{
+	return -EOPNOTSUPP;
+}
+
 static inline bool fscrypt_is_bounce_page(struct page *page)
 {
 	return false;
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH] fscrypt: add software key support for filesystem-managed data
  2026-04-21  7:57 [PATCH] fscrypt: add software key support for filesystem-managed data LiaoYuanhong-vivo
@ 2026-04-22 23:27 ` Eric Biggers
  2026-04-23 10:41   ` Liao Yuanhong
  0 siblings, 1 reply; 3+ messages in thread
From: Eric Biggers @ 2026-04-22 23:27 UTC (permalink / raw)
  To: LiaoYuanhong-vivo
  Cc: tytso, jaegeuk, linux-fscrypt, linux-kernel, linux-ext4,
	linux-f2fs-devel

On Tue, Apr 21, 2026 at 03:57:17PM +0800, LiaoYuanhong-vivo wrote:
> Some filesystems store small file contents in filesystem-managed regions
> rather than in regular data blocks submitted through bios. One example is
> F2FS inline_data, where the payload is stored inside the inode node block.
> Such regions still need to follow the inode's fscrypt contents encryption
> semantics, but they cannot rely on blk-crypto because they are not
> submitted as standalone file data bios.
> 
> As a result, when blk-crypto is enabled, mechanisms such as inline_data are
> typically disabled outright. However, it is desirable to re-enable such
> space-saving features while still preserving the required encryption
> semantics.
> 
> To support this, add fscrypt_crypt_fs_layer_page_inplace(), a helper that
> encrypts or decrypts a caller-provided page region in place using
> filesystem-layer software crypto and the inode's contents encryption
> policy.
> 
> This support is limited to v2 encryption policies. v1 policies do not
> provide the key setup model used here, so this path returns -EOPNOTSUPP for
> v1. Hardware-wrapped keys are not supported either, since deriving a
> software skcipher key requires software-accessible key material, which
> conflicts with the hardware-wrapped key model.
> 
> When the inode's normal contents path uses blk-crypto, fscrypt may not have
> a software skcipher key prepared for the inode contents key. Add an
> optional filesystem-layer prepared key to fscrypt_inode_info. This key is
> derived using the same v2 contents-encryption KDF as the normal contents
> key, but is prepared as a software skcipher key and is used only by the new
> filesystem-layer helper.
> 
> Signed-off-by: LiaoYuanhong-vivo <liaoyuanhong@vivo.com>

I don't have time for a super detailed review at the moment, but here
are my initial thoughts:

- This needs to be sent along with the code that actually uses it in
  ext4 and f2fs.  Please also Cc the mailing lists for those
  filesystems.

- This is going to require an "incompat" filesystem feature flag.  After
  all, once a filesystem contains files that use this scheme, older
  kernels won't understand it.

- UBIFS and CephFS already use fs/crypto/ but don't support blk-crypto
  (inline encryption).  This new code feels duplicative of that.  It
  should be possible to reuse the existing code instead.  That would
  include, for example, reusing the existing en/decryption functions and
  the existing struct ci_enc_key field.  This would keep the changes
  limited mainly to how the key is being set up.

- Supporting all the different IV generation methods doesn't make sense
  when a per-file key is always used.

- The fact that this is incompatible with hardware-wrapped keys greatly
  limits the usefulness of this.  (Note that technically, it could be
  supported in combination with them anyway.  But the security models
  would be inconsistent, which I assume is what you have in mind.)

Hope this is helpful,

- Eric

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] fscrypt: add software key support for filesystem-managed data
  2026-04-22 23:27 ` Eric Biggers
@ 2026-04-23 10:41   ` Liao Yuanhong
  0 siblings, 0 replies; 3+ messages in thread
From: Liao Yuanhong @ 2026-04-23 10:41 UTC (permalink / raw)
  To: Eric Biggers
  Cc: tytso, jaegeuk, linux-fscrypt, linux-kernel, linux-ext4,
	linux-f2fs-devel

On 4/23/2026 7:27 AM, Eric Biggers wrote:

> I don't have time for a super detailed review at the moment, but here
> are my initial thoughts:
>
> - This needs to be sent along with the code that actually uses it in
>    ext4 and f2fs.  Please also Cc the mailing lists for those
>    filesystems.
>
> - This is going to require an "incompat" filesystem feature flag.  After
>    all, once a filesystem contains files that use this scheme, older
>    kernels won't understand it.
>
> - UBIFS and CephFS already use fs/crypto/ but don't support blk-crypto
>    (inline encryption).  This new code feels duplicative of that.  It
>    should be possible to reuse the existing code instead.  That would
>    include, for example, reusing the existing en/decryption functions and
>    the existing struct ci_enc_key field.  This would keep the changes
>    limited mainly to how the key is being set up.
>
> - Supporting all the different IV generation methods doesn't make sense
>    when a per-file key is always used.
>
> - The fact that this is incompatible with hardware-wrapped keys greatly
>    limits the usefulness of this.  (Note that technically, it could be
>    supported in combination with them anyway.  But the security models
>    would be inconsistent, which I assume is what you have in mind.)
>
> Hope this is helpful,
>
> - Eric

Thanks for the comments. They are very helpful.

I agree that the fscrypt changes should stay much closer to the
existing filesystem-layer encryption code.  I will rework this so
that the fscrypt side is mainly limited to key setup: when
blk-crypto is used for normal file contents, fscrypt can also
prepare the existing software contents crypto state for
filesystem-managed regions that cannot go through bio/blk-crypto.

I will also drop the separate key object / key-selection path, and
try to reuse the existing contents key and software encryption
functions as much as possible.

I agree that supporting all IV generation methods is unnecessary
here.  For the first version, I plan to limit this to the normal v2
per-file-key case.

Regarding hardware-wrapped keys: it may be technically possible to
make this work in some cases, but using a software crypto key for
these regions seems to conflict with the expected hardware-wrapped
key security model.  What would you prefer for the initial version:
should this combination be disallowed, or is there another approach
you would recommend?

Thanks,
Liao Yuanhong

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2026-04-23 10:41 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-21  7:57 [PATCH] fscrypt: add software key support for filesystem-managed data LiaoYuanhong-vivo
2026-04-22 23:27 ` Eric Biggers
2026-04-23 10:41   ` Liao Yuanhong

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox