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
#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
size_t buflen)
{
int ret;
+ char *canon = NULL;
NTSTATUS status;
struct smb_Dir *dir_hnd = NULL;
struct files_struct *dirfsp = NULL;
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,