From ecd9b751f17bb0f73201989bb9116547fe7fc0da Mon Sep 17 00:00:00 2001 From: Noel Power Date: Mon, 8 Feb 2021 10:42:22 +0000 Subject: [PATCH] s3/modules: Ensure vfs_streaminfo gets passed valid pathref smb_filename the smb_filename/smb_filename->fsp passed to vfs_streaminfo eventually is passed to SMB_VFS_FLISTXATTR, we need to ensure this is properly setup and not NULL Signed-off-by: Noel Power Reviewed-by: Jeremy Allison --- source3/modules/vfs_catia.c | 12 +++++++----- source3/smbd/filename.c | 31 +++++++++++++++++++++++++++++-- source3/smbd/open.c | 29 ++++++++++++++++++++++++++++- 3 files changed, 64 insertions(+), 8 deletions(-) diff --git a/source3/modules/vfs_catia.c b/source3/modules/vfs_catia.c index d7e53e4fa12..81c24a8cfd1 100644 --- a/source3/modules/vfs_catia.c +++ b/source3/modules/vfs_catia.c @@ -982,19 +982,21 @@ catia_streaminfo(struct vfs_handle_struct *handle, &mapped_name, vfs_translate_to_unix); if (!NT_STATUS_IS_OK(status)) { - errno = map_errno_from_nt_status(status); return status; } - catia_smb_fname = synthetic_smb_fname(talloc_tos(), + status = synthetic_pathref(talloc_tos(), + handle->conn->cwd_fsp, mapped_name, NULL, &smb_fname->st, smb_fname->twrp, - smb_fname->flags); - if (catia_smb_fname == NULL) { + smb_fname->flags, + &catia_smb_fname); + + if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(mapped_name); - return NT_STATUS_NO_MEMORY; + return status; } status = SMB_VFS_NEXT_STREAMINFO(handle, fsp, catia_smb_fname, diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 9035c7e82c7..3560837ad1e 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -1720,6 +1720,7 @@ static NTSTATUS build_stream_path(TALLOC_CTX *mem_ctx, NTSTATUS status; unsigned int i, num_streams = 0; struct stream_struct *streams = NULL; + struct smb_filename *pathref = NULL; if (SMB_VFS_STAT(conn, smb_fname) == 0) { DEBUG(10, ("'%s' exists\n", smb_fname_str_dbg(smb_fname))); @@ -1732,12 +1733,36 @@ static NTSTATUS build_stream_path(TALLOC_CTX *mem_ctx, goto fail; } + if (smb_fname->fsp == NULL) { + status = synthetic_pathref(mem_ctx, + conn->cwd_fsp, + smb_fname->base_name, + NULL, + NULL, + smb_fname->twrp, + smb_fname->flags, + &pathref); + if (!NT_STATUS_IS_OK(status)) { + if (NT_STATUS_EQUAL(status, + NT_STATUS_OBJECT_NAME_NOT_FOUND)) { + TALLOC_FREE(pathref); + SET_STAT_INVALID(smb_fname->st); + return NT_STATUS_OK; + } + DBG_DEBUG("synthetic_pathref failed: %s\n", + nt_errstr(status)); + goto fail; + } + } else { + pathref = smb_fname; + } + /* Fall back to a case-insensitive scan of all streams on the file. */ - status = vfs_streaminfo(conn, NULL, smb_fname, mem_ctx, + status = vfs_streaminfo(conn, NULL, pathref, mem_ctx, &num_streams, &streams); - if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) { SET_STAT_INVALID(smb_fname->st); + TALLOC_FREE(pathref); return NT_STATUS_OK; } @@ -1760,6 +1785,7 @@ static NTSTATUS build_stream_path(TALLOC_CTX *mem_ctx, /* Couldn't find the stream. */ if (i == num_streams) { SET_STAT_INVALID(smb_fname->st); + TALLOC_FREE(pathref); TALLOC_FREE(streams); return NT_STATUS_OK; } @@ -1782,6 +1808,7 @@ static NTSTATUS build_stream_path(TALLOC_CTX *mem_ctx, } status = NT_STATUS_OK; fail: + TALLOC_FREE(pathref); TALLOC_FREE(streams); return status; } diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 92b0a507760..5b3dc246e8a 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -4919,9 +4919,36 @@ static NTSTATUS open_streams_for_delete(connection_struct *conn, int j; unsigned int i, num_streams = 0; TALLOC_CTX *frame = talloc_stackframe(); + const struct smb_filename *pathref = NULL; NTSTATUS status; - status = vfs_streaminfo(conn, NULL, smb_fname, talloc_tos(), + if (smb_fname->fsp == NULL) { + struct smb_filename *tmp = NULL; + status = synthetic_pathref(frame, + conn->cwd_fsp, + smb_fname->base_name, + NULL, + NULL, + smb_fname->twrp, + smb_fname->flags, + &tmp); + if (!NT_STATUS_IS_OK(status)) { + if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED) + || NT_STATUS_EQUAL(status, + NT_STATUS_OBJECT_NAME_NOT_FOUND)) { + DBG_DEBUG("no streams around\n"); + TALLOC_FREE(frame); + return NT_STATUS_OK; + } + DBG_DEBUG("synthetic_pathref failed: %s\n", + nt_errstr(status)); + goto fail; + } + pathref = tmp; + } else { + pathref = smb_fname; + } + status = vfs_streaminfo(conn, NULL, pathref, talloc_tos(), &num_streams, &stream_info); if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED) -- 2.34.1