smbd: use real dirfsp for SMB_VFS_UNLINKAT() in recursive_rmdir()
authorRalph Boehme <slow@samba.org>
Fri, 22 Jan 2021 11:49:56 +0000 (12:49 +0100)
committerJeremy Allison <jra@samba.org>
Thu, 28 Jan 2021 08:11:49 +0000 (08:11 +0000)
Also use synthetic_pathref() to ensure atname->fsp has a valid pathref as some
backends may make use of it.

Signed-off-by: Ralph Boehme <slow@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
source3/smbd/close.c

index a1081334cb23d7619118d1513689468d6d5fe18b..8d7f7980fcf0e50ddd2a122d0e22ccfb0363361d 100644 (file)
@@ -854,7 +854,9 @@ bool recursive_rmdir(TALLOC_CTX *ctx,
        long offset = 0;
        SMB_STRUCT_STAT st;
        struct smb_Dir *dir_hnd;
+       struct files_struct *dirfsp = NULL;
        int retval;
+       NTSTATUS status;
 
        SMB_ASSERT(!is_ntfs_stream_smb_fname(smb_dname));
 
@@ -862,7 +864,10 @@ bool recursive_rmdir(TALLOC_CTX *ctx,
        if (dir_hnd == NULL)
                return False;
 
+       dirfsp = dir_hnd_fetch_fsp(dir_hnd);
+
        while ((dname = ReadDirName(dir_hnd, &offset, &st, &talloced))) {
+               struct smb_filename *atname = NULL;
                struct smb_filename *smb_dname_full = NULL;
                char *fullname = NULL;
                bool do_break = true;
@@ -913,9 +918,23 @@ bool recursive_rmdir(TALLOC_CTX *ctx,
                        }
                        unlink_flags = AT_REMOVEDIR;
                }
+
+               status = synthetic_pathref(talloc_tos(),
+                                          dirfsp,
+                                          dname,
+                                          NULL,
+                                          NULL,
+                                          smb_dname_full->twrp,
+                                          smb_dname_full->flags,
+                                          &atname);
+               if (!NT_STATUS_IS_OK(status)) {
+                       errno = map_errno_from_nt_status(status);
+                       goto err_break;
+               }
+
                retval = SMB_VFS_UNLINKAT(conn,
-                                         conn->cwd_fsp,
-                                         smb_dname_full,
+                                         dirfsp,
+                                         atname,
                                          unlink_flags);
                if (retval != 0) {
                        goto err_break;
@@ -928,6 +947,7 @@ bool recursive_rmdir(TALLOC_CTX *ctx,
                TALLOC_FREE(smb_dname_full);
                TALLOC_FREE(fullname);
                TALLOC_FREE(talloced);
+               TALLOC_FREE(atname);
                if (do_break) {
                        ret = false;
                        break;