1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-08 21:18:16 +03:00

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 <jra@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
(cherry picked from commit 26fecad2e6)
(backported from commit 4793c4d530)
[pfilipen@redhat.com: rmdir_internals() got refactored in 4.15]
This commit is contained in:
Jeremy Allison 2021-10-25 12:32:29 -07:00 committed by Jule Anger
parent 66d688cea2
commit 7034f9b765

View File

@ -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),