]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
vfs_ceph_snapshots: Fix panic on snapshot access with a "/"-rooted share
authorMatthias Grandl <matthias.grandl@croit.io>
Fri, 10 Jul 2026 05:58:42 +0000 (07:58 +0200)
committerAnoop C S <anoopcs@samba.org>
Tue, 21 Jul 2026 16:12:17 +0000 (16:12 +0000)
ceph_snap_gmt_convert_dir() builds an absolute snapshot path by joining
the share's connectpath, the request-relative name and the snapshot
subdir with '/' separators, then hands it to OpenDir(). OpenDir() ->
fd_openat() -> filename_convert_dirfsp_rel() splits the path on '/' and
openat_pathref_fsp_nosymlink() asserts that no component is empty:

    SMB_ASSERT(rel_fname.base_name[0] != '\0')   source3/smbd/files.c:1212

connectpath is a bare "/" when the share is mounted at the file system
root, so the join yields a leading "//" (e.g. "//.snap" or
"//dir/.snap"). That empty first component trips the assert and panics
smbd as soon as a snapshot is accessed.

Whether the malformed path actually reaches the assert also depends on
the Ceph client accepting a non-canonical "//" path in the preceding
stat(), so the panic is libcephfs-version dependent.

Canonicalize the .snap directory path with canonicalize_absolute_path()
after building it, so the path handed to OpenDir() is always canonical
and the empty leading component can no longer occur.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=16176

Signed-off-by: Matthias Grandl <matthias.grandl@croit.io>
Reviewed-by: Anoop C S <anoopcs@samba.org>
Reviewed-by: David Disseldorp ddiss@samba.org
Autobuild-User(master): Anoop C S <anoopcs@samba.org>
Autobuild-Date(master): Tue Jul 21 16:12:18 UTC 2026 on atb-devel-224

source3/modules/vfs_ceph_snapshots.c

index cf2dfdc2d5d629944e2bc1670f17e536a1cc48a8..203b907b90bbf483421fb3a960aa58a53fe79e01 100644 (file)
@@ -29,6 +29,7 @@
 #include "lib/util/tevent_ntstatus.h"
 #include "lib/util/smb_strtox.h"
 #include "source3/smbd/dir.h"
+#include "lib/util_path.h"
 
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_VFS
@@ -505,6 +506,7 @@ static int ceph_snap_gmt_convert_dir(struct vfs_handle_struct *handle,
                                     size_t buflen)
 {
        int ret;
+       char *canon = NULL;
        NTSTATUS status;
        struct smb_Dir *dir_hnd = NULL;
        struct files_struct *dirfsp = NULL;
@@ -537,6 +539,19 @@ static int ceph_snap_gmt_convert_dir(struct vfs_handle_struct *handle,
                goto err_out;
        }
 
+       /*
+        * Canonicalize to collapse any "//" run when connectpath
+        * is a bare "/", which would trip the SMB_ASSERT in
+        * openat_pathref_fsp_nosymlink().
+        */
+       canon = canonicalize_absolute_path(tmp_ctx, _converted_buf);
+       if (canon == NULL) {
+               ret = -ENOMEM;
+               goto err_out;
+       }
+       strlcpy(_converted_buf, canon, buflen);
+       TALLOC_FREE(canon);
+
        snaps_dname = synthetic_smb_fname(tmp_ctx,
                                _converted_buf,
                                NULL,