From: Luis Henriques <luis@igalia.com>
To: Ilya Dryomov <idryomov@gmail.com>
Cc: Viacheslav Dubeyko <Slava.Dubeyko@ibm.com>,
"pengpeng@iscas.ac.cn" <pengpeng@iscas.ac.cn>,
Alex Markuze <amarkuze@redhat.com>,
"ceph-devel@vger.kernel.org" <ceph-devel@vger.kernel.org>,
"slava@dubeyko.com" <slava@dubeyko.com>,
"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>,
Xiubo Li <xiubli@redhat.com>
Subject: Re: [PATCH v4] ceph: bound encrypted snapshot suffix formatting
Date: Fri, 24 Apr 2026 09:15:15 +0100 [thread overview]
Message-ID: <87eck4oju4.fsf@igalia.com> (raw)
In-Reply-To: <CAOi1vP96JuBi5BhTdiVeL491ziy_hwJUm79TqOb=iPaxck1eyg@mail.gmail.com> (Ilya Dryomov's message of "Wed, 22 Apr 2026 11:53:29 +0200")
On Wed, Apr 22 2026, Ilya Dryomov wrote:
> On Fri, Apr 10, 2026 at 10:46 PM Viacheslav Dubeyko
> <Slava.Dubeyko@ibm.com> wrote:
>>
>> On Fri, 2026-04-10 at 20:40 +0000, Viacheslav Dubeyko wrote:
>> > On Thu, 2026-04-09 at 18:09 +0000, Viacheslav Dubeyko wrote:
>> > > On Thu, 2026-04-09 at 10:39 +0800, Pengpeng Hou wrote:
>> > > > ceph_encode_encrypted_dname() base64-encodes the encrypted snapshot
>> > > > name into the caller buffer and then, for long snapshot names, appends
>> > > > _<ino> with sprintf(p + elen, ...).
>> > > >
>> > > > Some callers only provide NAME_MAX bytes. For long snapshot names, a
>> > > > large inode suffix can push the final encoded name past NAME_MAX even
>> > > > though the encrypted prefix stayed within the documented 240-byte
>> > > > budget.
>> > > >
>> > > > Format the suffix into a small local buffer first and reject names
>> > > > whose suffix would exceed the caller's NAME_MAX output buffer.
>> > > >
>> > > > Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
>> > > > ---
>> > > > Changes since v3:
>> > > > - reject `elen > 240` explicitly instead of relying only on the earlier
>> > > > `WARN_ON()`
>> > > > - rewrite the NAME_MAX bound check in terms of the final total length
>> > > > instead of `NAME_MAX - prefix_len - elen`
>> > > >
>> > > > fs/ceph/crypto.c | 31 +++++++++++++++++++++++++++++--
>> > > > 1 file changed, 29 insertions(+), 2 deletions(-)
>> > > >
>> > > > diff --git a/fs/ceph/crypto.c b/fs/ceph/crypto.c
>> > > > index f3de43ccb470..42e3fff34697 100644
>> > > > --- a/fs/ceph/crypto.c
>> > > > +++ b/fs/ceph/crypto.c
>> > > > @@ -15,6 +15,12 @@
>> > > > #include "mds_client.h"
>> > > > #include "crypto.h"
>> > > >
>> > > > +/*
>> > > > + * Reserve room for '_' + decimal 64-bit inode number + trailing NUL.
>> > > > + * ceph_encode_encrypted_dname() copies only the visible suffix bytes.
>> > > > + */
>> > > > +#define CEPH_ENCRYPTED_SNAP_INO_SUFFIX_MAX sizeof("_18446744073709551615")
>> > > > +
>> > > > static int ceph_crypt_get_context(struct inode *inode, void *ctx, size_t len)
>> > > > {
>> > > > struct ceph_inode_info *ci = ceph_inode(inode);
>> > > > @@ -209,6 +215,7 @@ int ceph_encode_encrypted_dname(struct inode *parent, char *buf, int elen)
>> > > > struct inode *dir = parent;
>> > > > char *p = buf;
>> > > > u32 len;
>> > > > + int prefix_len = 0;
>> > > > int name_len = elen;
>> > > > int ret;
>> > > > u8 *cryptbuf = NULL;
>> > > > @@ -219,6 +226,7 @@ int ceph_encode_encrypted_dname(struct inode *parent, char *buf, int elen)
>> > > > if (IS_ERR(dir))
>> > > > return PTR_ERR(dir);
>> > > > p++; /* skip initial '_' */
>> > > > + prefix_len = 1;
>> > > > }
>> > > >
>> > > > if (!fscrypt_has_encryption_key(dir))
>> > > > @@ -271,8 +279,27 @@ int ceph_encode_encrypted_dname(struct inode *parent, char *buf, int elen)
>> > > >
>> > > > /* To understand the 240 limit, see CEPH_NOHASH_NAME_MAX comments */
>> > > > WARN_ON(elen > 240);
>> > > > - if (dir != parent) // leading _ is already there; append _<inum>
>> > > > - elen += 1 + sprintf(p + elen, "_%ld", dir->i_ino);
>> > > > + if (elen > 240) {
>> > > > + elen = -ENAMETOOLONG;
>> > > > + goto out;
>> > > > + }
>> > > > +
>> > > > + if (dir != parent) {
>> > > > + int total_len;
>> > > > + /* leading '_' is already there; append _<inum> */
>> > > > + char suffix[CEPH_ENCRYPTED_SNAP_INO_SUFFIX_MAX];
>> > > > +
>> > > > + ret = snprintf(suffix, sizeof(suffix), "_%lu", dir->i_ino);
>> > > > + total_len = prefix_len + elen + ret;
>> > > > + if (total_len > NAME_MAX) {
>> > > > + elen = -ENAMETOOLONG;
>> > > > + goto out;
>> > > > + }
>> > > > +
>> > > > + memcpy(p + elen, suffix, ret);
>> > > > + /* Include the leading '_' skipped by p. */
>> > > > + elen = total_len;
>> > > > + }
>> > > >
>> > > > out:
>> > > > kfree(cryptbuf);
>> > >
>> > > Looks good.
>> > >
>> > > Reviewed-by: Viacheslav Dubeyko <Slava.Dubeyko@ibm.com>
>> > >
>> > > Let me run xfstests for the patch to double check that everything is OK. I'll
>> > > share the result ASAP.
>> > >
>> >
>> > The xfstests run was successful. I don't see any issues with the patch.
>> >
>> > Tested-by: Viacheslav Dubeyko <Slava.Dubeyko@ibm.com>
>> >
>> >
>>
>> Applied on testing branch of CephFS kernel client git tree.
>
> Hi Pengpeng, Slava,
>
> This patch raised my attention because my understanding was that the
> entire CEPH_NOHASH_NAME_MAX + sha256() was put in place precisely to
> handle longer names nicely and make them fit into NAME_MAX-sized buffer.
> Simply rejecting longer names seemed to be in direct contradiction with
> that and yet the patch on its own was clearly merited given
>
> * (240 bytes is the maximum size allowed for snapshot names to take into
> * account the format: '_<SNAPSHOT-NAME>_<INODE-NUMBER>'.)
>
> comment on CEPH_NOHASH_NAME_MAX definition.
>
> I dug a bit deeper and started a discussion in [1]. The preliminary
> conclusion is that the 240 bytes assumption was a mistake -- somehow
> the minimum number of characters needed for <inum> ended up being used
> instead of the maximum. CEPH_NOHASH_NAME_MAX value is likely incorrect
> and should have been smaller -- something along the lines of 174 -
> SHA256_DIGEST_SIZE instead of 180 - SHA256_DIGEST_SIZE.
FWIW I _think_ Ilya may be correct, and there's actually an issue when
these constants were defined. I spent quite some time last evening trying
to dig into the details on why the inode length was assumed to be 13.
Apparently, it was just a mistake that no one spotted at the time :-(
Unfortunately, my bandwidth to look into this is quite limited. But I
believe it should be easy to verify that this is indeed a bug by simply
creating snapshots on an encrypted directory that has an inode number
bigger than 2^40 and then checking the large snapshot name in the '.snap'
directory of a subdirectory.
Cheers,
--
Luís
> I kept this patch in the testing branch but not including it for 7.1
> pending further investigation.
>
> [1] https://github.com/ceph/ceph/pull/45312
>
> Thanks,
>
> Ilya
next prev parent reply other threads:[~2026-04-24 8:15 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-04-03 8:56 [PATCH] ceph: bound encrypted snapshot suffix formatting Pengpeng Hou
2026-04-06 18:52 ` Viacheslav Dubeyko
2026-04-07 1:57 ` [PATCH v2] " Pengpeng Hou
2026-04-07 19:42 ` Viacheslav Dubeyko
2026-04-08 0:57 ` [PATCH v3] " Pengpeng Hou
2026-04-08 18:34 ` Viacheslav Dubeyko
2026-04-09 2:39 ` [PATCH v4] " Pengpeng Hou
2026-04-09 18:09 ` Viacheslav Dubeyko
2026-04-10 20:40 ` Viacheslav Dubeyko
2026-04-10 20:46 ` Viacheslav Dubeyko
2026-04-22 9:53 ` Ilya Dryomov
2026-04-23 18:04 ` Viacheslav Dubeyko
2026-04-24 9:27 ` Ilya Dryomov
2026-04-24 18:31 ` Viacheslav Dubeyko
2026-04-24 19:20 ` Ilya Dryomov
2026-04-27 8:12 ` Luis Henriques
2026-04-28 11:40 ` Ilya Dryomov
2026-04-28 18:17 ` Viacheslav Dubeyko
2026-04-24 8:15 ` Luis Henriques [this message]
2026-04-07 3:30 ` [PATCH] " Pengpeng Hou
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=87eck4oju4.fsf@igalia.com \
--to=luis@igalia.com \
--cc=Slava.Dubeyko@ibm.com \
--cc=amarkuze@redhat.com \
--cc=ceph-devel@vger.kernel.org \
--cc=idryomov@gmail.com \
--cc=linux-kernel@vger.kernel.org \
--cc=pengpeng@iscas.ac.cn \
--cc=slava@dubeyko.com \
--cc=xiubli@redhat.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.