Re: [PATCH v3] ceph: Fix multifs mds auth caps issue

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Sorry, couldn't get to this after my PTO. Comments inline.

On Tue, Aug 26, 2025 at 12:02 AM Viacheslav Dubeyko
<Slava.Dubeyko@xxxxxxx> wrote:
>
> On Mon, 2025-08-25 at 00:18 +0530, khiremat@xxxxxxxxxx wrote:
> > From: Kotresh HR <khiremat@xxxxxxxxxx>
> >
> > The mds auth caps check should also validate the
> > fsname along with the associated caps. Not doing
> > so would result in applying the mds auth caps of
> > one fs on to the other fs in a multifs ceph cluster.
> > The bug causes multiple issues w.r.t user
> > authentication, following is one such example.
> >
> > Steps to Reproduce (on vstart cluster):
> > 1. Create two file systems in a cluster, say 'fsname1' and 'fsname2'
> > 2. Authorize read only permission to the user 'client.usr' on fs 'fsname1'
> >     $ceph fs authorize fsname1 client.usr / r
> > 3. Authorize read and write permission to the same user 'client.usr' on fs 'fsname2'
> >     $ceph fs authorize fsname2 client.usr / rw
> > 4. Update the keyring
> >     $ceph auth get client.usr >> ./keyring
> >
> > With above permssions for the user 'client.usr', following is the
> > expectation.
> >   a. The 'client.usr' should be able to only read the contents
> >      and not allowed to create or delete files on file system 'fsname1'.
> >   b. The 'client.usr' should be able to read/write on file system 'fsname2'.
> >
> > But, with this bug, the 'client.usr' is allowed to read/write on file
> > system 'fsname1'. See below.
> >
> > 5. Mount the file system 'fsname1' with the user 'client.usr'
> >      $sudo bin/mount.ceph usr@.fsname1=/ /kmnt_fsname1_usr/
> > 6. Try creating a file on file system 'fsname1' with user 'client.usr'. This
> >    should fail but passes with this bug.
> >      $touch /kmnt_fsname1_usr/file1
> > 7. Mount the file system 'fsname1' with the user 'client.admin' and create a
> >    file.
> >      $sudo bin/mount.ceph admin@.fsname1=/ /kmnt_fsname1_admin
> >      $echo "data" > /kmnt_fsname1_admin/admin_file1
> > 8. Try removing an existing file on file system 'fsname1' with the user
> >    'client.usr'. This shoudn't succeed but succeeds with the bug.
> >      $rm -f /kmnt_fsname1_usr/admin_file1
> >
> > For more information, please take a look at the corresponding mds/fuse patch
> > and tests added by looking into the tracker mentioned below.
> >
> > v2: Fix a possible null dereference in doutc
> > v3: Don't store fsname from mdsmap, validate against
> >     ceph_mount_options's fsname and use it
> >
> > URL: https://tracker.ceph.com/issues/72167
> > Signed-off-by: Kotresh HR <khiremat@xxxxxxxxxx>
> > ---
> >  fs/ceph/mds_client.c | 10 ++++++++++
> >  fs/ceph/mdsmap.c     | 14 +++++++++++++-
> >  2 files changed, 23 insertions(+), 1 deletion(-)
> >
> > diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c
> > index ce0c129f4651..638a12626432 100644
> > --- a/fs/ceph/mds_client.c
> > +++ b/fs/ceph/mds_client.c
> > @@ -5680,11 +5680,21 @@ static int ceph_mds_auth_match(struct ceph_mds_client *mdsc,
> >       u32 caller_uid = from_kuid(&init_user_ns, cred->fsuid);
> >       u32 caller_gid = from_kgid(&init_user_ns, cred->fsgid);
> >       struct ceph_client *cl = mdsc->fsc->client;
> > +     const char *fs_name = mdsc->fsc->mount_options->mds_namespace;
> >       const char *spath = mdsc->fsc->mount_options->server_path;
> >       bool gid_matched = false;
> >       u32 gid, tlen, len;
> >       int i, j;
> >
>
> The doutc is debug output and it will never be shown without enabling it. So, it
> will be completely enough to place the doutc one time for both cases here.
>
ok. makes sense. I will get this done in the next patch version.

> > +     if (auth->match.fs_name && strcmp(auth->match.fs_name, fs_name)) {
> > +             doutc(cl, "fsname check failed fs_name=%s  match.fs_name=%s\n",
> > +                   fs_name, auth->match.fs_name);
> > +             return 0;
>
> If the check is failed, then it sounds to me that we need to show an error
> message here and return error code:
>
> pr_err_client(<error message>);
> return -EINVAL; ????
>
> Am I correct here?
No. The code should continue to validate the next fsname in the mds
cap and see if it matches.

>
> > +     } else {
> > +             doutc(cl, "fsname check passed fs_name=%s  match.fs_name=%s\n",
> > +                   fs_name, auth->match.fs_name ? auth->match.fs_name : "");
> > +     }
> > +
> >       doutc(cl, "match.uid %lld\n", auth->match.uid);
> >       if (auth->match.uid != MDS_AUTH_UID_ANY) {
> >               if (auth->match.uid != caller_uid)
> > diff --git a/fs/ceph/mdsmap.c b/fs/ceph/mdsmap.c
> > index 8109aba66e02..44f435351daa 100644
> > --- a/fs/ceph/mdsmap.c
> > +++ b/fs/ceph/mdsmap.c
> > @@ -356,7 +356,19 @@ struct ceph_mdsmap *ceph_mdsmap_decode(struct ceph_mds_client *mdsc, void **p,
> >               /* enabled */
> >               ceph_decode_8_safe(p, end, m->m_enabled, bad_ext);
> >               /* fs_name */
> > -             ceph_decode_skip_string(p, end, bad_ext);
> > +             const char *mds_namespace = mdsc->fsc->mount_options->mds_namespace;
> > +             u32 fsname_len;
>
> I am afraid we could have compiler warnings for such C declarations. Let's have
> all declarations in the beginning of scope:
>
> if (mdsmap_ev >= 8) {
>      const char *mds_namespace = mdsc->fsc->mount_options->mds_namespace;
>      u32 fsname_len;
>
>      /* enabled */
>     ceph_decode_8_safe(p, end, m->m_enabled, bad_ext);
>     /* fs_name */
>     <rest logic>
> }
>
Sure, I will fix this up in the next patch version.

> > +             ceph_decode_32_safe(p, end, fsname_len, bad_ext);
> > +
> > +             void *sp = *p;
>
> What the point to introduce sp variable but not to use p pointer directly? Any
> particular reason?
>
No. It was overlooked. I will address this in the next patch version.

> > +             if (!(mds_namespace &&
> > +                   strlen(mds_namespace) == fsname_len &&
> > +                   !strncmp(mds_namespace, (char *)sp, fsname_len))) {
>
> Frankly speaking, I think to introduce a static inline function for this check
> could make the code cleaner. I mean something like this:
>
> if (fsname_mismatch()) {
>    <complain>
>    goto bad;
> }
Makes sense. I will address this in the next patch version.

>
> > +                     pr_warn_client(cl, "fsname doesn't match\n");
>
> What's about sharing the mismatched names?
>
> pr_warn_client(cl, "fsname %s doesn't match to mds_namespace %s\n");
>
I was doubtful initially that this code can get executed before the
mds_namespace is initialized and
also if fsname can be null. I think this can be done as pr_warn_client
handles NULL gracefully?

> Thanks,
> Slava.
>
> > +                     goto bad;
> > +             }
> > +             // skip fsname after validation
> > +             ceph_decode_skip_n(p, end, fsname_len, bad);
> >       }
> >       /* damaged */
> >       if (mdsmap_ev >= 9) {
>






[Index of Archives]     [CEPH Users]     [Ceph Large]     [Ceph Dev]     [Information on CEPH]     [Linux BTRFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux