From 05cbf6e66f6989e383904ac582dae9515ac3a838 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) --- 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 2fdab781fda..8ecfc1aaf82 100755 --- a/selftest/target/Samba3.pm +++ b/selftest/target/Samba3.pm @@ -1738,6 +1738,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) --- 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 973edeeda24..ae73ba965a5 100644 --- a/source3/modules/vfs_streams_depot.c +++ b/source3/modules/vfs_streams_depot.c @@ -823,6 +823,16 @@ static int streams_depot_unlink_internal(vfs_handle_struct *handle, ret = SMB_VFS_NEXT_LSTAT(handle, full_fname); } else { ret = SMB_VFS_NEXT_STAT(handle, full_fname); + 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, full_fname); + } + } } if (ret == -1) { TALLOC_FREE(full_fname); -- 2.30.2 From 9938ef02b42f1578e758010b9c4b7a149a9d39c8 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) --- 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 daa99b2cc3e..42c570b54b3 100644 --- a/source3/modules/vfs_xattr_tdb.c +++ b/source3/modules/vfs_xattr_tdb.c @@ -520,6 +520,16 @@ static int xattr_tdb_unlinkat(vfs_handle_struct *handle, ret = SMB_VFS_NEXT_LSTAT(handle, full_fname); } else { ret = SMB_VFS_NEXT_STAT(handle, full_fname); + 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, full_fname); + } + } } if (ret == -1) { goto out; -- 2.30.2 From 38ca6d51a07b2ff26e6447846d62c72aabee3606 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) --- source3/smbd/close.c | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 470ca7f1b6d..484442ddc17 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -965,8 +965,6 @@ static NTSTATUS rmdir_internals(TALLOC_CTX *ctx, struct files_struct *fsp) struct smb_filename *smb_dname = fsp->fsp_name; struct smb_filename *parent_fname = NULL; struct smb_filename *at_fname = NULL; - const struct loadparm_substitution *lp_sub = - loadparm_s3_global_substitution(); SMB_STRUCT_STAT st; const char *dname = NULL; char *talloced = NULL; @@ -1026,9 +1024,7 @@ static NTSTATUS rmdir_internals(TALLOC_CTX *ctx, struct files_struct *fsp) return NT_STATUS_OK; } - if (!((errno == ENOTEMPTY) || (errno == EEXIST)) || - !*lp_veto_files(talloc_tos(), lp_sub, SNUM(conn))) - { + if (!((errno == ENOTEMPTY) || (errno == EEXIST))) { DEBUG(3,("rmdir_internals: couldn't remove directory %s : " "%s\n", smb_fname_str_dbg(smb_dname), strerror(errno))); @@ -1036,11 +1032,21 @@ static NTSTATUS rmdir_internals(TALLOC_CTX *ctx, struct files_struct *fsp) 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 - * 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. + * files non-visible to the client. If not, fail the delete. */ dir_hnd = OpenDir(talloc_tos(), conn, smb_dname, NULL, 0); @@ -1133,16 +1139,18 @@ static NTSTATUS rmdir_internals(TALLOC_CTX *ctx, struct files_struct *fsp) continue; } + /* + * 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(talloced); TALLOC_FREE(fullname); TALLOC_FREE(smb_dname_full); TALLOC_FREE(direntry_fname); - } - - /* We only have veto files/directories. - * Are we allowed to delete them ? */ - - if (!lp_delete_veto_files(SNUM(conn))) { errno = ENOTEMPTY; goto err; } -- 2.30.2 From a8bc5af4ded62d80dca97622f5c90b0ebab5c130 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) --- source3/smbd/close.c | 56 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 51 insertions(+), 5 deletions(-) diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 484442ddc17..7178257efcc 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -1103,15 +1103,61 @@ static NTSTATUS rmdir_internals(TALLOC_CTX *ctx, struct files_struct *fsp) goto err; } - /* - * is_visible_fsp() always returns true - * for the symlink/MSDFS case. - */ 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(fsp, 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); - continue; + errno = ENOTEMPTY; + goto err; } /* Not a symlink, get a pathref. */ -- 2.30.2 From a1fb0d7bcf0791066b23e909c4f3a7a89bab6034 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) --- selftest/knownfail.d/rmdir_dangle_symlink | 1 - source3/smbd/dir.c | 55 ++++++++++++++++++++--- 2 files changed, 49 insertions(+), 7 deletions(-) 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 174f07b1159..4d61bb0d56d 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -1922,16 +1922,59 @@ NTSTATUS can_delete_directory_fsp(files_struct *fsp) break; } - /* - * is_visible_fsp() always returns true - * for the symlink/MSDFS case. - */ - 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_dname; + smb_dname = synthetic_smb_fname(talloc_tos(), + dname, + NULL, + &smb_dname_full->st, + fsp->fsp_name->twrp, + fsp->fsp_name->flags); + if (smb_dname == NULL) { + TALLOC_FREE(talloced); + TALLOC_FREE(fullname); + TALLOC_FREE(smb_dname_full); + status = NT_STATUS_NO_MEMORY; + break; + } + if (is_msdfs_link(fsp, smb_dname)) { + TALLOC_FREE(talloced); + TALLOC_FREE(fullname); + TALLOC_FREE(smb_dname_full); + TALLOC_FREE(smb_dname); + DBG_DEBUG("got msdfs link name %s " + "- can't delete directory %s\n", + dname, + fsp_str_dbg(fsp)); + status = NT_STATUS_DIRECTORY_NOT_EMPTY; + break; + } + TALLOC_FREE(smb_dname); + } + /* 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(talloced); TALLOC_FREE(fullname); TALLOC_FREE(smb_dname_full); - DBG_DEBUG("got name %s - can't delete\n", dname); status = NT_STATUS_DIRECTORY_NOT_EMPTY; break; } -- 2.30.2 From 2a6f19df3f1588dbf60b86b520798b88861d2179 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) --- 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.30.2