* [PATCH] fscrypt: allow filesystems to disable symlink target caching
@ 2026-10-15 17:46 Alex Markuze
2026-10-15 18:35 ` Eric Biggers
0 siblings, 1 reply; 5+ messages in thread
From: Alex Markuze @ 2026-10-15 17:46 UTC (permalink / raw)
To: linux-fscrypt
Cc: Alex Markuze, Eric Biggers, Theodore Y. Ts'o, Jaegeuk Kim,
Ilya Dryomov, Xiubo Li, Viacheslav Dubeyko, ceph-devel,
linux-kernel
fscrypt stores decrypted symlink targets in inode->i_link. The VFS can
use this field without calling the filesystem's ->get_link() callback.
The target can remain valid after the access policy changes.
The CephFS subvolume quarantine series adds access checks to
->get_link(). Quarantine can revoke access after a target is cached. The
VFS cache can bypass these checks.
The no_symlink_cache option in fscrypt_operations gives filesystems
control of this cache. It applies during target creation, lookup and
getattr. With this option set, the helpers do not read or update
->i_link. The filesystem callback can then revalidate access.
Uncached targets use the existing delayed-free callback. Each uncached
lookup allocates a temporary buffer and decrypts or encodes the target.
This lets Ceph reuse fscrypt's target validation and buffer ownership.
The default setting keeps the current cache behavior for other
filesystems. Ceph selects the option so cached targets cannot bypass its
->get_link() checks.
Signed-off-by: Alex Markuze <amarkuze@redhat.com>
---
fs/ceph/crypto.c | 1 +
fs/crypto/hooks.c | 37 ++++++++++++++++++++++---------------
include/linux/fscrypt.h | 7 +++++++
3 files changed, 30 insertions(+), 15 deletions(-)
diff --git a/fs/ceph/crypto.c b/fs/ceph/crypto.c
index 9e0ebb071840..de786a0e626c 100644
--- a/fs/ceph/crypto.c
+++ b/fs/ceph/crypto.c
@@ -92,6 +92,7 @@ static struct fscrypt_operations ceph_fscrypt_ops = {
.inode_info_offs = (int)offsetof(struct ceph_inode_info, i_crypt_info) -
(int)offsetof(struct ceph_inode_info, netfs.inode),
.needs_bounce_pages = 1,
+ .no_symlink_cache = 1,
.get_context = ceph_crypt_get_context,
.set_context = ceph_crypt_set_context,
.get_dummy_policy = ceph_get_dummy_policy,
diff --git a/fs/crypto/hooks.c b/fs/crypto/hooks.c
index a7a8a3f581a0..e1eb0fce7948 100644
--- a/fs/crypto/hooks.c
+++ b/fs/crypto/hooks.c
@@ -321,11 +321,13 @@ int __fscrypt_encrypt_symlink(struct inode *inode, const char *target,
*/
sd->encrypted_path[ciphertext_len] = '\0';
- /* Cache the plaintext symlink target for later use by get_link() */
- err = -ENOMEM;
- inode->i_link = kmemdup(target, len + 1, GFP_NOFS);
- if (!inode->i_link)
- goto err_free_sd;
+ /* Cache the plaintext symlink target if the filesystem allows it. */
+ if (!inode->i_sb->s_cop->no_symlink_cache) {
+ err = -ENOMEM;
+ inode->i_link = kmemdup(target, len + 1, GFP_NOFS);
+ if (!inode->i_link)
+ goto err_free_sd;
+ }
if (!disk_link->name)
disk_link->name = (unsigned char *)sd;
@@ -358,17 +360,21 @@ const char *fscrypt_get_symlink(struct inode *inode, const void *caddr,
{
const struct fscrypt_symlink_data *sd;
struct fscrypt_str cstr, pstr;
- bool has_key;
+ bool has_key, cache;
int err;
/* This is for encrypted symlinks only */
if (WARN_ON_ONCE(!IS_ENCRYPTED(inode)))
return ERR_PTR(-EINVAL);
+ cache = !inode->i_sb->s_cop->no_symlink_cache;
+
/* If the decrypted target is already cached, just return it. */
- pstr.name = READ_ONCE(inode->i_link);
- if (pstr.name)
- return pstr.name;
+ if (cache) {
+ pstr.name = READ_ONCE(inode->i_link);
+ if (pstr.name)
+ return pstr.name;
+ }
/*
* Try to set up the symlink's encryption key, but we can continue
@@ -411,12 +417,12 @@ const char *fscrypt_get_symlink(struct inode *inode, const void *caddr,
pstr.name[pstr.len] = '\0';
/*
- * Cache decrypted symlink targets in i_link for later use. Don't cache
- * symlink targets encoded without the key, since those become outdated
- * once the key is added. This pairs with the READ_ONCE() above and in
- * the VFS path lookup code.
+ * Cache decrypted symlink targets in i_link if the filesystem allows it.
+ * Don't cache symlink targets encoded without the key, since those
+ * become outdated once the key is added. This pairs with the
+ * READ_ONCE() above and in the VFS path lookup code.
*/
- if (!has_key ||
+ if (!cache || !has_key ||
cmpxchg_release(&inode->i_link, NULL, pstr.name) != NULL)
set_delayed_call(done, kfree_link, pstr.name);
@@ -460,7 +466,8 @@ int fscrypt_symlink_getattr(const struct path *path, struct kstat *stat)
* decrypted target or the no-key encoded target), we can just get it in
* the same way the VFS does during path resolution and readlink().
*/
- link = READ_ONCE(inode->i_link);
+ link = inode->i_sb->s_cop->no_symlink_cache ?
+ NULL : READ_ONCE(inode->i_link);
if (!link) {
link = inode->i_op->get_link(dentry, inode, &done);
if (IS_ERR(link))
diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h
index 28f2108e29f3..faeff5812885 100644
--- a/include/linux/fscrypt.h
+++ b/include/linux/fscrypt.h
@@ -107,6 +107,13 @@ struct fscrypt_operations {
*/
unsigned int supports_subblock_data_units : 1;
+ /*
+ * If set, don't cache decrypted symlink targets in ->i_link. This
+ * ensures that the VFS calls ->get_link() for every access, allowing
+ * the filesystem to revalidate the symlink before returning its target.
+ */
+ unsigned int no_symlink_cache : 1;
+
/*
* This field exists only for backwards compatibility reasons and should
* only be set by the filesystems that are setting it already. It
base-commit: ed0502cb11f84fff29f374238e526ae94d9bdfde
--
2.34.1
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] fscrypt: allow filesystems to disable symlink target caching
2026-10-15 17:46 [PATCH] fscrypt: allow filesystems to disable symlink target caching Alex Markuze
@ 2026-10-15 18:35 ` Eric Biggers
2026-10-15 18:52 ` Alex Markuze
0 siblings, 1 reply; 5+ messages in thread
From: Eric Biggers @ 2026-10-15 18:35 UTC (permalink / raw)
To: Alex Markuze
Cc: linux-fscrypt, Theodore Y. Ts'o, Jaegeuk Kim, Ilya Dryomov,
Xiubo Li, Viacheslav Dubeyko, ceph-devel, linux-kernel
On Thu, Oct 15, 2026 at 05:46:24PM +0000, Alex Markuze wrote:
> fscrypt stores decrypted symlink targets in inode->i_link. The VFS can
> use this field without calling the filesystem's ->get_link() callback.
> The target can remain valid after the access policy changes.
>
> The CephFS subvolume quarantine series adds access checks to
> ->get_link(). Quarantine can revoke access after a target is cached. The
> VFS cache can bypass these checks.
>
> The no_symlink_cache option in fscrypt_operations gives filesystems
> control of this cache. It applies during target creation, lookup and
> getattr. With this option set, the helpers do not read or update
> ->i_link. The filesystem callback can then revalidate access.
>
> Uncached targets use the existing delayed-free callback. Each uncached
> lookup allocates a temporary buffer and decrypts or encodes the target.
> This lets Ceph reuse fscrypt's target validation and buffer ownership.
>
> The default setting keeps the current cache behavior for other
> filesystems. Ceph selects the option so cached targets cannot bypass its
> ->get_link() checks.
>
> Signed-off-by: Alex Markuze <amarkuze@redhat.com>
This sounds like a bug fix? If so, which commit is it fixing?
- Eric
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] fscrypt: allow filesystems to disable symlink target caching
2026-10-15 18:35 ` Eric Biggers
@ 2026-10-15 18:52 ` Alex Markuze
2026-10-15 19:38 ` Eric Biggers
0 siblings, 1 reply; 5+ messages in thread
From: Alex Markuze @ 2026-10-15 18:52 UTC (permalink / raw)
To: Eric Biggers
Cc: linux-fscrypt, Theodore Y. Ts'o, Jaegeuk Kim, Ilya Dryomov,
Xiubo Li, Viacheslav Dubeyko, ceph-devel, linux-kernel
Hi Eric,
This supports the concurrent CephFS subvolume quarantine series.
There’s no Fixes: tag since this isn't addressing an existing upstream
regression.
The quarantine series adds checks to Ceph's ->get_link(). However, if
an encrypted symlink target was cached prior to quarantine, the VFS
bypasses that callback entirely when following or reading it. While
the target data is still valid, access now needs to be denied.
This patch adds an opt-out for symlink caching and enables it for
Ceph, handling the encrypted-symlink case for the concurrent series
without affecting other filesystems.
On Thu, Oct 15, 2026 at 9:35 PM Eric Biggers <ebiggers@kernel.org> wrote:
>
> On Thu, Oct 15, 2026 at 05:46:24PM +0000, Alex Markuze wrote:
> > fscrypt stores decrypted symlink targets in inode->i_link. The VFS can
> > use this field without calling the filesystem's ->get_link() callback.
> > The target can remain valid after the access policy changes.
> >
> > The CephFS subvolume quarantine series adds access checks to
> > ->get_link(). Quarantine can revoke access after a target is cached. The
> > VFS cache can bypass these checks.
> >
> > The no_symlink_cache option in fscrypt_operations gives filesystems
> > control of this cache. It applies during target creation, lookup and
> > getattr. With this option set, the helpers do not read or update
> > ->i_link. The filesystem callback can then revalidate access.
> >
> > Uncached targets use the existing delayed-free callback. Each uncached
> > lookup allocates a temporary buffer and decrypts or encodes the target.
> > This lets Ceph reuse fscrypt's target validation and buffer ownership.
> >
> > The default setting keeps the current cache behavior for other
> > filesystems. Ceph selects the option so cached targets cannot bypass its
> > ->get_link() checks.
> >
> > Signed-off-by: Alex Markuze <amarkuze@redhat.com>
>
> This sounds like a bug fix? If so, which commit is it fixing?
>
> - Eric
>
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] fscrypt: allow filesystems to disable symlink target caching
2026-10-15 18:52 ` Alex Markuze
@ 2026-10-15 19:38 ` Eric Biggers
2026-10-15 19:45 ` Alex Markuze
0 siblings, 1 reply; 5+ messages in thread
From: Eric Biggers @ 2026-10-15 19:38 UTC (permalink / raw)
To: Alex Markuze
Cc: linux-fscrypt, Theodore Y. Ts'o, Jaegeuk Kim, Ilya Dryomov,
Xiubo Li, Viacheslav Dubeyko, ceph-devel, linux-kernel
On Thu, Oct 15, 2026 at 09:52:11PM +0300, Alex Markuze wrote:
> Hi Eric,
>
> This supports the concurrent CephFS subvolume quarantine series.
> There’s no Fixes: tag since this isn't addressing an existing upstream
> regression.
>
> The quarantine series adds checks to Ceph's ->get_link(). However, if
> an encrypted symlink target was cached prior to quarantine, the VFS
> bypasses that callback entirely when following or reading it. While
> the target data is still valid, access now needs to be denied.
>
> This patch adds an opt-out for symlink caching and enables it for
> Ceph, handling the encrypted-symlink case for the concurrent series
> without affecting other filesystems.
>
That series wasn't sent to me. Is it
https://lore.kernel.org/r/cover.1792074165.git.amarkuze@redhat.com/ ?
It would make more sense to add this patch to that series so that they
can be reviewed together. I can potentially apply a prerequisite patch
by itself, but we'd first need to know that the rest has been reviewed
and will be accepted too, otherwise it will be unused code.
- Eric
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] fscrypt: allow filesystems to disable symlink target caching
2026-10-15 19:38 ` Eric Biggers
@ 2026-10-15 19:45 ` Alex Markuze
0 siblings, 0 replies; 5+ messages in thread
From: Alex Markuze @ 2026-10-15 19:45 UTC (permalink / raw)
To: Eric Biggers
Cc: linux-fscrypt, Theodore Y. Ts'o, Jaegeuk Kim, Ilya Dryomov,
Xiubo Li, Viacheslav Dubeyko, ceph-devel, linux-kernel
I didn't want to conflate fscrypt patches with Ceph features; arguably
two distinct patchsets.
I will CC you folks when this is acked then.
On Thu, Oct 15, 2026 at 10:38 PM Eric Biggers <ebiggers@kernel.org> wrote:
>
> On Thu, Oct 15, 2026 at 09:52:11PM +0300, Alex Markuze wrote:
> > Hi Eric,
> >
> > This supports the concurrent CephFS subvolume quarantine series.
> > There’s no Fixes: tag since this isn't addressing an existing upstream
> > regression.
> >
> > The quarantine series adds checks to Ceph's ->get_link(). However, if
> > an encrypted symlink target was cached prior to quarantine, the VFS
> > bypasses that callback entirely when following or reading it. While
> > the target data is still valid, access now needs to be denied.
> >
> > This patch adds an opt-out for symlink caching and enables it for
> > Ceph, handling the encrypted-symlink case for the concurrent series
> > without affecting other filesystems.
> >
>
> That series wasn't sent to me. Is it
> https://lore.kernel.org/r/cover.1792074165.git.amarkuze@redhat.com/ ?
> It would make more sense to add this patch to that series so that they
> can be reviewed together. I can potentially apply a prerequisite patch
> by itself, but we'd first need to know that the rest has been reviewed
> and will be accepted too, otherwise it will be unused code.
>
> - Eric
>
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-10-15 19:45 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-15 17:46 [PATCH] fscrypt: allow filesystems to disable symlink target caching Alex Markuze
2026-10-15 18:35 ` Eric Biggers
2026-10-15 18:52 ` Alex Markuze
2026-10-15 19:38 ` Eric Biggers
2026-10-15 19:45 ` Alex Markuze
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®