From a0618e0eda69d31d090f776a9217a6a3cf76e5da Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 21 Oct 2021 16:37:27 -0700 Subject: [PATCH 1/7] s3: smbd: Add two tests showing the ability to delete a directory containing a dangling symlink over SMB2 depends on "delete veto files" setting. Add knownfail. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14879 Signed-off-by: Jeremy Allison Reviewed-by: Ralph Boehme (cherry picked from commit 942123b95923f35a32df4196a072a3ed3468396a) (cherry picked from commit 359517877d6462ff4398401748f921c8b79357a6) --- selftest/knownfail.d/rmdir_dangle_symlink | 1 + selftest/target/Samba3.pm | 4 + .../test_delete_veto_files_only_rmdir.sh | 183 ++++++++++++++++++ source3/selftest/tests.py | 3 + 4 files changed, 191 insertions(+) create mode 100644 selftest/knownfail.d/rmdir_dangle_symlink create mode 100755 source3/script/tests/test_delete_veto_files_only_rmdir.sh diff --git a/selftest/knownfail.d/rmdir_dangle_symlink b/selftest/knownfail.d/rmdir_dangle_symlink new file mode 100644 index 00000000000..c775dc5fe15 --- /dev/null +++ b/selftest/knownfail.d/rmdir_dangle_symlink @@ -0,0 +1 @@ +^samba3.blackbox.test_dangle_rmdir.rmdir can delete directory containing dangling symlink\(fileserver\) diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm index bbff9d74817..588d7779dd4 100755 --- a/selftest/target/Samba3.pm +++ b/selftest/target/Samba3.pm @@ -1584,6 +1584,10 @@ sub setup_fileserver veto files = /veto_name*/ delete veto files = yes +[delete_veto_files_only] + path = $veto_sharedir + delete veto files = yes + [homes] comment = Home directories browseable = No diff --git a/source3/script/tests/test_delete_veto_files_only_rmdir.sh b/source3/script/tests/test_delete_veto_files_only_rmdir.sh new file mode 100755 index 00000000000..d2c3b2198f7 --- /dev/null +++ b/source3/script/tests/test_delete_veto_files_only_rmdir.sh @@ -0,0 +1,183 @@ +#!/bin/sh +# +# Check smbclient can (or cannot) delete a directory containing dangling symlinks. +# BUG: https://bugzilla.samba.org/show_bug.cgi?id=14879 +# + +if [ $# -lt 6 ]; then +cat < "$tmpfile" < "$tmpfile" < "$tmpfile" < "$tmpfile" < Date: Mon, 25 Oct 2021 12:01:58 -0700 Subject: [PATCH 2/7] s3: VFS: streams_depot. Allow unlinkat to cope with dangling symlinks. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14879 Signed-off-by: Jeremy Allison Reviewed-by: Ralph Boehme (cherry picked from commit 295d7d026babe3cd5123d0f53adcb16868907f05) (backported from commit 7a4173809a87350bc3580240232978042ec2ceca) [pfilipen@redhat.com: code in 4.15 uses different variable name] --- source3/modules/vfs_streams_depot.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/source3/modules/vfs_streams_depot.c b/source3/modules/vfs_streams_depot.c index a5e02d5a069..dd6376e5fd0 100644 --- a/source3/modules/vfs_streams_depot.c +++ b/source3/modules/vfs_streams_depot.c @@ -739,6 +739,16 @@ static int streams_depot_unlink_internal(vfs_handle_struct *handle, ret = SMB_VFS_NEXT_LSTAT(handle, smb_fname_base); } else { ret = SMB_VFS_NEXT_STAT(handle, smb_fname_base); + if (ret == -1 && (errno == ENOENT || errno == ELOOP)) { + if (VALID_STAT(smb_fname->st) && + S_ISLNK(smb_fname->st.st_ex_mode)) { + /* + * Original name was a link - Could be + * trying to remove a dangling symlink. + */ + ret = SMB_VFS_NEXT_LSTAT(handle, smb_fname_base); + } + } } if (ret == -1) { -- 2.33.1 From 474a91d03527a15f7655be3866a9e5eaa405118f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 25 Oct 2021 12:02:43 -0700 Subject: [PATCH 3/7] s3: VFS: xattr_tdb. Allow unlinkat to cope with dangling symlinks. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14879 Signed-off-by: Jeremy Allison Reviewed-by: Ralph Boehme (cherry picked from commit f254be19d6501a4f573843af97963e350a9ee2ed) (backported from commit 0dba0917fd97e975d1daab5b0828644d026c2bc5) [pfilipen@redhat.com: code in 4.15 uses different variable name] --- source3/modules/vfs_xattr_tdb.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/source3/modules/vfs_xattr_tdb.c b/source3/modules/vfs_xattr_tdb.c index d89a1dd0d7d..e06ff9639f1 100644 --- a/source3/modules/vfs_xattr_tdb.c +++ b/source3/modules/vfs_xattr_tdb.c @@ -639,6 +639,16 @@ static int xattr_tdb_unlinkat(vfs_handle_struct *handle, ret = SMB_VFS_NEXT_LSTAT(handle, smb_fname_tmp); } else { ret = SMB_VFS_NEXT_STAT(handle, smb_fname_tmp); + if (ret == -1 && (errno == ENOENT || errno == ELOOP)) { + if (VALID_STAT(smb_fname->st) && + S_ISLNK(smb_fname->st.st_ex_mode)) { + /* + * Original name was a link - Could be + * trying to remove a dangling symlink. + */ + ret = SMB_VFS_NEXT_LSTAT(handle, smb_fname_tmp); + } + } } if (ret == -1) { goto out; -- 2.33.1 From 298a8dac1160ebba56cd84b7e25908e160b88f85 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 25 Oct 2021 12:21:37 -0700 Subject: [PATCH 4/7] s3: smbd: Fix rmdir_internals() to do an early return if lp_delete_veto_files() is not set. Fix the comments to match what the code actually does. The exit at the end of the scan directory loop if we find a client visible filename is a change in behavior, but the previous behavior (not exist on visible filename, but delete it) was a bug and in non-tested code. Now it's testd. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14879 Signed-off-by: Jeremy Allison Reviewed-by: Ralph Boehme (cherry picked from commit a37d16e7c55f85e3f2c9c8614755ea6307092d5f) (backported from commit e00fe095e8cf7ab54bc82870b913762d2fdddbad) [pfilipen@redhat.com: rmdir_internals() got refactored in 4.15] --- source3/smbd/close.c | 247 ++++++++++++++++++++++--------------------- 1 file changed, 128 insertions(+), 119 deletions(-) diff --git a/source3/smbd/close.c b/source3/smbd/close.c index f05619d1886..0c102b9533b 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -938,8 +938,11 @@ static NTSTATUS rmdir_internals(TALLOC_CTX *ctx, files_struct *fsp) { connection_struct *conn = fsp->conn; struct smb_filename *smb_dname = fsp->fsp_name; - const struct loadparm_substitution *lp_sub = - loadparm_s3_global_substitution(); + SMB_STRUCT_STAT st; + const char *dname = NULL; + char *talloced = NULL; + long dirpos = 0; + struct smb_Dir *dir_hnd = NULL; int ret; SMB_ASSERT(!is_ntfs_stream_smb_fname(smb_dname)); @@ -974,143 +977,149 @@ static NTSTATUS rmdir_internals(TALLOC_CTX *ctx, files_struct *fsp) return NT_STATUS_OK; } - if(((errno == ENOTEMPTY)||(errno == EEXIST)) && *lp_veto_files(talloc_tos(), lp_sub, SNUM(conn))) { - /* - * Check to see if the only thing in this directory are - * vetoed files/directories. If so then delete them and - * retry. If we fail to delete any of them (and we *don't* - * do a recursive delete) then fail the rmdir. - */ - SMB_STRUCT_STAT st; - const char *dname = NULL; - char *talloced = NULL; - long dirpos = 0; - struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn, - smb_dname, NULL, - 0); - - if(dir_hnd == NULL) { + if (!((errno == ENOTEMPTY) || (errno == EEXIST))) { + DEBUG(3,("rmdir_internals: couldn't remove directory %s : " + "%s\n", smb_fname_str_dbg(smb_dname), + strerror(errno))); + return map_nt_error_from_unix(errno); + } + + /* + * Here we know the initial directory unlink failed with + * ENOTEMPTY or EEXIST so we know there are objects within. + * If we don't have permission to delete files non + * visible to the client just fail the directory delete. + */ + + if (!lp_delete_veto_files(SNUM(conn))) { + errno = ENOTEMPTY; + goto err; + } + + /* + * Check to see if the only thing in this directory are + * files non-visible to the client. If not, fail the delete. + */ + + dir_hnd = OpenDir(talloc_tos(), conn, smb_dname, NULL, 0); + if (dir_hnd == NULL) { + errno = ENOTEMPTY; + goto err; + } + + while ((dname = ReadDirName(dir_hnd, &dirpos, &st, &talloced)) != NULL) { + if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0)) { + TALLOC_FREE(talloced); + continue; + } + if (!is_visible_file(conn, + dir_hnd, + dname, + &st, + false)) { + TALLOC_FREE(talloced); + continue; + } + if(!IS_VETO_PATH(conn, dname)) { + /* + * We found a client visible name. + * We cannot delete this directory. + */ + DBG_DEBUG("got name %s - " + "can't delete directory %s\n", + dname, + fsp_str_dbg(fsp)); + TALLOC_FREE(dir_hnd); + TALLOC_FREE(talloced); errno = ENOTEMPTY; goto err; } + TALLOC_FREE(talloced); + } - while ((dname = ReadDirName(dir_hnd, &dirpos, &st, - &talloced)) != NULL) { - if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0)) { - TALLOC_FREE(talloced); - continue; - } - if (!is_visible_file(conn, - dir_hnd, - dname, - &st, - false)) { - TALLOC_FREE(talloced); - continue; - } - if(!IS_VETO_PATH(conn, dname)) { - TALLOC_FREE(dir_hnd); - TALLOC_FREE(talloced); - errno = ENOTEMPTY; - goto err; - } + /* Do a recursive delete. */ + RewindDir(dir_hnd,&dirpos); + while ((dname = ReadDirName(dir_hnd, &dirpos, &st, &talloced)) != NULL) { + struct smb_filename *smb_dname_full = NULL; + char *fullname = NULL; + bool do_break = true; + + if (ISDOT(dname) || ISDOTDOT(dname)) { + TALLOC_FREE(talloced); + continue; + } + if (!is_visible_file(conn, + dir_hnd, + dname, + &st, + false)) { TALLOC_FREE(talloced); + continue; } - /* We only have veto files/directories. - * Are we allowed to delete them ? */ + fullname = talloc_asprintf(ctx, + "%s/%s", + smb_dname->base_name, + dname); - if(!lp_delete_veto_files(SNUM(conn))) { - TALLOC_FREE(dir_hnd); - errno = ENOTEMPTY; - goto err; + if (fullname == NULL) { + errno = ENOMEM; + goto err_break; } - /* Do a recursive delete. */ - RewindDir(dir_hnd,&dirpos); - while ((dname = ReadDirName(dir_hnd, &dirpos, &st, - &talloced)) != NULL) { - struct smb_filename *smb_dname_full = NULL; - char *fullname = NULL; - bool do_break = true; - - if (ISDOT(dname) || ISDOTDOT(dname)) { - TALLOC_FREE(talloced); - continue; - } - if (!is_visible_file(conn, - dir_hnd, - dname, - &st, - false)) { - TALLOC_FREE(talloced); - continue; - } - - fullname = talloc_asprintf(ctx, - "%s/%s", - smb_dname->base_name, - dname); + smb_dname_full = synthetic_smb_fname(talloc_tos(), + fullname, + NULL, + NULL, + smb_dname->twrp, + smb_dname->flags); + if (smb_dname_full == NULL) { + errno = ENOMEM; + goto err_break; + } - if(!fullname) { - errno = ENOMEM; + if(SMB_VFS_LSTAT(conn, smb_dname_full) != 0) { + goto err_break; + } + if(smb_dname_full->st.st_ex_mode & S_IFDIR) { + int retval; + if(!recursive_rmdir(ctx, conn, + smb_dname_full)) { goto err_break; } - - smb_dname_full = synthetic_smb_fname(talloc_tos(), - fullname, - NULL, - NULL, - smb_dname->twrp, - smb_dname->flags); - if (smb_dname_full == NULL) { - errno = ENOMEM; + retval = SMB_VFS_UNLINKAT(conn, + conn->cwd_fsp, + smb_dname_full, + AT_REMOVEDIR); + if(retval != 0) { goto err_break; } - - if(SMB_VFS_LSTAT(conn, smb_dname_full) != 0) { + } else { + int retval = SMB_VFS_UNLINKAT(conn, + conn->cwd_fsp, + smb_dname_full, + 0); + if(retval != 0) { goto err_break; } - if(smb_dname_full->st.st_ex_mode & S_IFDIR) { - int retval; - if(!recursive_rmdir(ctx, conn, - smb_dname_full)) { - goto err_break; - } - retval = SMB_VFS_UNLINKAT(conn, - conn->cwd_fsp, - smb_dname_full, - AT_REMOVEDIR); - if(retval != 0) { - goto err_break; - } - } else { - int retval = SMB_VFS_UNLINKAT(conn, - conn->cwd_fsp, - smb_dname_full, - 0); - if(retval != 0) { - goto err_break; - } - } + } - /* Successful iteration. */ - do_break = false; + /* Successful iteration. */ + do_break = false; - err_break: - TALLOC_FREE(fullname); - TALLOC_FREE(smb_dname_full); - TALLOC_FREE(talloced); - if (do_break) - break; - } - TALLOC_FREE(dir_hnd); - /* Retry the rmdir */ - ret = SMB_VFS_UNLINKAT(conn, - conn->cwd_fsp, - smb_dname, - AT_REMOVEDIR); + err_break: + TALLOC_FREE(fullname); + TALLOC_FREE(smb_dname_full); + TALLOC_FREE(talloced); + if (do_break) + break; } + TALLOC_FREE(dir_hnd); + /* Retry the rmdir */ + ret = SMB_VFS_UNLINKAT(conn, + conn->cwd_fsp, + smb_dname, + AT_REMOVEDIR); err: -- 2.33.1 From a7075aeedd078c68b57556678fa40907cd66cd08 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 25 Oct 2021 12:32:29 -0700 Subject: [PATCH 5/7] s3: smbd: Fix logic in rmdir_internals() to cope with dangling symlinks. Still need to add the same logic in can_delete_directory_fsp() before we can delete the knownfail. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14879 Signed-off-by: Jeremy Allison Reviewed-by: Ralph Boehme (cherry picked from commit 26fecad2e66e91a3913d88ee2e0889f266e91d89) (backported from commit 4793c4d5307472f0eb72f70f7dbf7324744e3f91) [pfilipen@redhat.com: rmdir_internals() got refactored in 4.15] --- source3/smbd/close.c | 103 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 101 insertions(+), 2 deletions(-) diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 0c102b9533b..81811f703b0 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -1008,10 +1008,14 @@ static NTSTATUS rmdir_internals(TALLOC_CTX *ctx, files_struct *fsp) } while ((dname = ReadDirName(dir_hnd, &dirpos, &st, &talloced)) != NULL) { + struct smb_filename *smb_dname_full = NULL; + char *fullname = NULL; + if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0)) { TALLOC_FREE(talloced); continue; } + if (!is_visible_file(conn, dir_hnd, dname, @@ -1020,6 +1024,98 @@ static NTSTATUS rmdir_internals(TALLOC_CTX *ctx, files_struct *fsp) TALLOC_FREE(talloced); continue; } + + fullname = talloc_asprintf(talloc_tos(), + "%s/%s", + smb_dname->base_name, + dname); + + if (fullname == NULL) { + TALLOC_FREE(talloced); + errno = ENOMEM; + goto err; + } + + smb_dname_full = synthetic_smb_fname(talloc_tos(), + fullname, + NULL, + NULL, + smb_dname->twrp, + smb_dname->flags); + if (smb_dname_full == NULL) { + TALLOC_FREE(talloced); + TALLOC_FREE(fullname); + errno = ENOMEM; + goto err; + } + + ret = SMB_VFS_LSTAT(conn, smb_dname_full); + if (ret != 0) { + int saved_errno = errno; + TALLOC_FREE(talloced); + TALLOC_FREE(fullname); + TALLOC_FREE(smb_dname_full); + errno = saved_errno; + goto err; + } + + if (S_ISLNK(smb_dname_full->st.st_ex_mode)) { + /* Could it be an msdfs link ? */ + if (lp_host_msdfs() && + lp_msdfs_root(SNUM(conn))) { + struct smb_filename *smb_atname; + smb_atname = synthetic_smb_fname(talloc_tos(), + dname, + NULL, + &smb_dname_full->st, + fsp->fsp_name->twrp, + fsp->fsp_name->flags); + if (smb_atname == NULL) { + TALLOC_FREE(talloced); + TALLOC_FREE(fullname); + TALLOC_FREE(smb_dname_full); + errno = ENOMEM; + goto err; + } + if (is_msdfs_link(conn, smb_atname)) { + TALLOC_FREE(talloced); + TALLOC_FREE(fullname); + TALLOC_FREE(smb_dname_full); + TALLOC_FREE(smb_atname); + DBG_DEBUG("got msdfs link name %s " + "- can't delete directory %s\n", + dname, + fsp_str_dbg(fsp)); + errno = ENOTEMPTY; + goto err; + } + TALLOC_FREE(smb_atname); + } + + /* Not a DFS link - could it be a dangling symlink ? */ + ret = SMB_VFS_STAT(conn, smb_dname_full); + if (ret == -1 && (errno == ENOENT || errno == ELOOP)) { + /* + * Dangling symlink. + * Allow delete as "delete veto files = yes" + */ + TALLOC_FREE(talloced); + TALLOC_FREE(fullname); + TALLOC_FREE(smb_dname_full); + continue; + } + + DBG_DEBUG("got symlink name %s - " + "can't delete directory %s\n", + dname, + fsp_str_dbg(fsp)); + TALLOC_FREE(talloced); + TALLOC_FREE(fullname); + TALLOC_FREE(smb_dname_full); + errno = ENOTEMPTY; + goto err; + } + if(!IS_VETO_PATH(conn, dname)) { /* * We found a client visible name. @@ -1029,12 +1125,15 @@ static NTSTATUS rmdir_internals(TALLOC_CTX *ctx, files_struct *fsp) "can't delete directory %s\n", dname, fsp_str_dbg(fsp)); - TALLOC_FREE(dir_hnd); TALLOC_FREE(talloced); + TALLOC_FREE(fullname); + TALLOC_FREE(smb_dname_full); errno = ENOTEMPTY; goto err; } TALLOC_FREE(talloced); + TALLOC_FREE(fullname); + TALLOC_FREE(smb_dname_full); } /* Do a recursive delete. */ @@ -1114,7 +1213,6 @@ static NTSTATUS rmdir_internals(TALLOC_CTX *ctx, files_struct *fsp) if (do_break) break; } - TALLOC_FREE(dir_hnd); /* Retry the rmdir */ ret = SMB_VFS_UNLINKAT(conn, conn->cwd_fsp, @@ -1123,6 +1221,7 @@ static NTSTATUS rmdir_internals(TALLOC_CTX *ctx, files_struct *fsp) err: + TALLOC_FREE(dir_hnd); if (ret != 0) { DEBUG(3,("rmdir_internals: couldn't remove directory %s : " "%s\n", smb_fname_str_dbg(smb_dname), -- 2.33.1 From 843fc3b857cdfd6c7e902acef933d17690815e7e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 25 Oct 2021 12:36:57 -0700 Subject: [PATCH 6/7] s3: smbd: Fix logic in can_delete_directory_fsp() to cope with dangling symlinks. Remove knownfail. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14879 Signed-off-by: Jeremy Allison Reviewed-by: Ralph Boehme (cherry picked from commit e9ef970eee5eca8ab3720279c54098e91d2dfda9) (backported from commit 5023dbc04bfad7cc39e8c4de96f40c82e7a0288e) [pfilipen@redhat.com: can_delete_directory_fsp() got refactored in 4.15] --- selftest/knownfail.d/rmdir_dangle_symlink | 1 - source3/smbd/dir.c | 97 +++++++++++++++++++++++ 2 files changed, 97 insertions(+), 1 deletion(-) delete mode 100644 selftest/knownfail.d/rmdir_dangle_symlink diff --git a/selftest/knownfail.d/rmdir_dangle_symlink b/selftest/knownfail.d/rmdir_dangle_symlink deleted file mode 100644 index c775dc5fe15..00000000000 --- a/selftest/knownfail.d/rmdir_dangle_symlink +++ /dev/null @@ -1 +0,0 @@ -^samba3.blackbox.test_dangle_rmdir.rmdir can delete directory containing dangling symlink\(fileserver\) diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 545c7499f28..96edc8678e5 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -1876,6 +1876,8 @@ NTSTATUS can_delete_directory_fsp(files_struct *fsp) char *talloced = NULL; SMB_STRUCT_STAT st; struct connection_struct *conn = fsp->conn; + struct smb_filename *smb_dname = fsp->fsp_name; + int ret; struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn, fsp->fsp_name, @@ -1887,6 +1889,9 @@ NTSTATUS can_delete_directory_fsp(files_struct *fsp) } while ((dname = ReadDirName(dir_hnd, &dirpos, &st, &talloced))) { + struct smb_filename *smb_dname_full = NULL; + char *fullname = NULL; + if (ISDOT(dname) || (ISDOTDOT(dname))) { TALLOC_FREE(talloced); continue; @@ -1901,6 +1906,98 @@ NTSTATUS can_delete_directory_fsp(files_struct *fsp) continue; } + fullname = talloc_asprintf(talloc_tos(), + "%s/%s", + smb_dname->base_name, + dname); + + if (fullname == NULL) { + TALLOC_FREE(dir_hnd); + TALLOC_FREE(talloced); + return NT_STATUS_NO_MEMORY; + } + + smb_dname_full = synthetic_smb_fname(talloc_tos(), + fullname, + NULL, + NULL, + smb_dname->twrp, + smb_dname->flags); + if (smb_dname_full == NULL) { + TALLOC_FREE(dir_hnd); + TALLOC_FREE(talloced); + TALLOC_FREE(fullname); + return NT_STATUS_NO_MEMORY; + } + + ret = SMB_VFS_LSTAT(conn, smb_dname_full); + if (ret != 0) { + TALLOC_FREE(dir_hnd); + TALLOC_FREE(talloced); + TALLOC_FREE(fullname); + TALLOC_FREE(smb_dname_full); + return map_nt_error_from_unix(errno); + } + + if (S_ISLNK(smb_dname_full->st.st_ex_mode)) { + /* Could it be an msdfs link ? */ + if (lp_host_msdfs() && + lp_msdfs_root(SNUM(conn))) { + struct smb_filename *smb_atname; + smb_atname = synthetic_smb_fname(talloc_tos(), + dname, + NULL, + &smb_dname_full->st, + fsp->fsp_name->twrp, + fsp->fsp_name->flags); + if (smb_atname == NULL) { + TALLOC_FREE(dir_hnd); + TALLOC_FREE(talloced); + TALLOC_FREE(fullname); + TALLOC_FREE(smb_dname_full); + return NT_STATUS_NO_MEMORY; + } + if (is_msdfs_link(conn, smb_atname)) { + TALLOC_FREE(dir_hnd); + TALLOC_FREE(talloced); + TALLOC_FREE(fullname); + TALLOC_FREE(smb_dname_full); + TALLOC_FREE(smb_atname); + DBG_DEBUG("got msdfs link name %s " + "- can't delete directory %s\n", + dname, + fsp_str_dbg(fsp)); + return NT_STATUS_DIRECTORY_NOT_EMPTY; + } + TALLOC_FREE(smb_atname); + } + + /* Not a DFS link - could it be a dangling symlink ? */ + ret = SMB_VFS_STAT(conn, smb_dname_full); + if (ret == -1 && (errno == ENOENT || errno == ELOOP)) { + /* + * Dangling symlink. + * Allow if "delete veto files = yes" + */ + if (lp_delete_veto_files(SNUM(conn))) { + TALLOC_FREE(talloced); + TALLOC_FREE(fullname); + TALLOC_FREE(smb_dname_full); + continue; + } + } + + DBG_DEBUG("got symlink name %s - " + "can't delete directory %s\n", + dname, + fsp_str_dbg(fsp)); + TALLOC_FREE(dir_hnd); + TALLOC_FREE(talloced); + TALLOC_FREE(fullname); + TALLOC_FREE(smb_dname_full); + return NT_STATUS_DIRECTORY_NOT_EMPTY; + } + DEBUG(10,("got name %s - can't delete\n", dname )); status = NT_STATUS_DIRECTORY_NOT_EMPTY; -- 2.33.1 From 7189ea825d8c9e4777dba737227ead602ad9b651 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 25 Oct 2021 12:42:02 -0700 Subject: [PATCH 7/7] s3: docs-xml: Clarify the "delete veto files" paramter. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BUG: https://bugzilla.samba.org/show_bug.cgi?id=14879 Signed-off-by: Jeremy Allison Reviewed-by: Ralph Boehme Autobuild-User(master): Ralph Böhme Autobuild-Date(master): Fri Oct 29 14:57:14 UTC 2021 on sn-devel-184 (cherry picked from commit 0b818c6b77e972626d0b071bebcf4ce55619fb84) (cherry picked from commit a549dc219cba5bd61969e4919ae4142f52c133ea) --- docs-xml/smbdotconf/filename/deletevetofiles.xml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/docs-xml/smbdotconf/filename/deletevetofiles.xml b/docs-xml/smbdotconf/filename/deletevetofiles.xml index 581dc05396d..570d4ac60a0 100644 --- a/docs-xml/smbdotconf/filename/deletevetofiles.xml +++ b/docs-xml/smbdotconf/filename/deletevetofiles.xml @@ -4,9 +4,12 @@ xmlns:samba="http://www.samba.org/samba/DTD/samba-doc"> This option is used when Samba is attempting to - delete a directory that contains one or more vetoed directories - (see the - option). If this option is set to no (the default) then if a vetoed + delete a directory that contains one or more vetoed files + or directories or non-visible files or directories (such + as dangling symlinks that point nowhere). + (see the , , + , + options). If this option is set to no (the default) then if a vetoed directory contains any non-vetoed files or directories then the directory delete will fail. This is usually what you want. -- 2.33.1