[SCM] Samba Shared Repository - branch master updated

Stefan Metzmacher metze at samba.org
Thu Jan 14 12:41:01 UTC 2021


The branch, master has been updated
       via  da052dde8a9 s3:smbd: simplify the error handling in create_file_unixpath()
       via  9c277b27dec s3:smbd: allow close_file() with a non-fsa fsp for {SHUTDOWN,ERROR}_CLOSE
       via  20187c6f54c s3:smbd: make sure a SHUTDOWN_CLOSE applies to a stream fsp before its base fsp
       via  930b6bb3b87 s3:smbd: make use of fsp_set_base_fsp() when changing fsp->base_fsp
       via  928382f2700 s3:smbd: add fsp_set_base_fsp() helper
       via  42c60703f2e s3:smbd: remove duplicate assignment of base_fsp in create_file_unixpath()
       via  87b4a8f35a8 s3:smbd: fix the error cleanup in create_file_unixpath()
       via  22bebaf8589 s3:smbd: split out create_internal_fsp() from create_internal_dirfsp()
       via  7dc9a84bb5c s3:smbd: make fsp_free() static, it should only ever be called by file_free()
       via  81b6931be0c s3:smbd: let vfs_default_durable_reconnect() use file_free()
       via  bcac1dab694 s3:smbd: close pathref fsp in call_trans2findfirst()
       via  eae7ce8a2e0 s3:smbd: turn assignment into assert check in call_trans2findfirst()
       via  e1a10b58171 s3:smbd: let call_trans2findfirst() use file_free() instead of fsp_free()
       via  9b1dc2a4ca6 s3:smbd: make sure openat_pathref_fsp() calls fd_close(fsp->base_fsp);
       via  8d79764ad3e s3:smbd: introduce a reopen_from_fsp() helper function
       via  38ae1599a0c s3:smbd: don't pass an unused smb_fname to reopen_from_procfd()
       via  d6949f0f93f s3:smbd: let open_directory() also use fd_open_atomic() as reopen_from_procfd() fallback
       via  30134630988 s3:smbd: let open_pathref_base_fsp() make use of smb_fname_fsp_unlink()
       via  c2e7256b1e0 s3:smbd: let openat_pathref_fsp() make use of fsp_attach_smb_fname()
       via  cff29e58ffa s3:smbd: let openat_pathref_fsp() allocate fsp->fsp_name directly on fsp
       via  347edf7ee00 s3:smbd: split out a fsp_attach_smb_fname() helper function
       via  1ab038b77a8 s3:smbd: let fsp_set_smb_fname() always link fsp to fsp->fsp_name->fsp
       via  932c27e290e s3:smbd: let fsp_smb_fname_link() set both sides of the link
       via  3fdfb79a12b s3:smbd: rearrange move_smb_fname_fsp_link a bit
      from  4e624478dcd s4 auth ntlm: Fix integer overflow in authsam_password_check_and_record

https://git.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit da052dde8a9801063e74d036d15f516d079d3720
Author: Stefan Metzmacher <metze at samba.org>
Date:   Mon Dec 21 16:49:03 2020 +0100

    s3:smbd: simplify the error handling in create_file_unixpath()
    
    We can just call close_file(req, fsp, ERROR_CLOSE), as it handles
    non-fsa fsp's and base_fsp's just fine.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>
    
    Autobuild-User(master): Stefan Metzmacher <metze at samba.org>
    Autobuild-Date(master): Thu Jan 14 12:40:56 UTC 2021 on sn-devel-184

commit 9c277b27dec568677c0b407497da6eb95ae7cb8d
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Dec 23 12:10:37 2020 +0100

    s3:smbd: allow close_file() with a non-fsa fsp for {SHUTDOWN,ERROR}_CLOSE
    
    Such an fsp was typically created via create_internal_fsp() and
    opened via fd_openat() without going through SMB_VFS_CREATE_FILE(),
    so they should be closed via fd_close().
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit 20187c6f54c85131bcdc7979a649d1a575d3a8e0
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Dec 23 11:50:34 2020 +0100

    s3:smbd: make sure a SHUTDOWN_CLOSE applies to a stream fsp before its base fsp
    
    Before we had open_pathref_fsp() we had the stream fsp before the base
    fsp in the linked list we traverse for SHUTDOWN_CLOSE.
    
    Now the order has changed. I could have used some DLIST_PROMOTE()
    hacks, but that's still fragile.
    
    Now we reference both fsp's via ->base_fsp and ->stream_fsp.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit 930b6bb3b87f600757266b34a9bb1ca3764177fd
Author: Stefan Metzmacher <metze at samba.org>
Date:   Mon Dec 21 16:35:11 2020 +0100

    s3:smbd: make use of fsp_set_base_fsp() when changing fsp->base_fsp
    
    This allows us to add some more logic for bi-directional linking between
    base and stream fsp in the next commits.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit 928382f27000ce93aa29080f06cb7445b0b8c281
Author: Stefan Metzmacher <metze at samba.org>
Date:   Mon Dec 21 15:44:22 2020 +0100

    s3:smbd: add fsp_set_base_fsp() helper
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit 42c60703f2e7417168774f7b5a0ff25299e3b6a2
Author: Stefan Metzmacher <metze at samba.org>
Date:   Mon Jan 4 16:33:09 2021 +0100

    s3:smbd: remove duplicate assignment of base_fsp in create_file_unixpath()
    
    This has already been set a few lines above. The duplicate was the result of
    restructuring create_file_unixpath() a few months ago, allocating fsp in
    create_file_unixpath() instead of in the callees open_file_ntcreate() or
    open_directory() respectively.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit 87b4a8f35a8ab993eec806022986fdf860c8bbc7
Author: Stefan Metzmacher <metze at samba.org>
Date:   Mon Dec 21 16:40:01 2020 +0100

    s3:smbd: fix the error cleanup in create_file_unixpath()
    
    We always need to cleanup the base_fsp!
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>

commit 22bebaf8589ff6ff95fe59f14f632b3b90471920
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Dec 23 11:50:34 2020 +0100

    s3:smbd: split out create_internal_fsp() from create_internal_dirfsp()
    
    That will be useful in other places as well.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit 7dc9a84bb5c78235c4e77fde2b8297e9c8206862
Author: Stefan Metzmacher <metze at samba.org>
Date:   Mon Dec 21 12:41:06 2020 +0100

    s3:smbd: make fsp_free() static, it should only ever be called by file_free()
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit 81b6931be0cd4adfcb233e1c03fb9ca898fee9b0
Author: Stefan Metzmacher <metze at samba.org>
Date:   Mon Dec 21 12:18:44 2020 +0100

    s3:smbd: let vfs_default_durable_reconnect() use file_free()
    
    We should always go through file_free(), which calls fsp_free() at the end.
    
    Most things in file_free() may not apply to all
    vfs_default_durable_reconnect() cases, but we want fsp_free() to become
    static to files.c
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit bcac1dab694be832c3f993356daacaee35c49f71
Author: Ralph Boehme <slow at samba.org>
Date:   Tue Jan 12 12:50:43 2021 +0100

    s3:smbd: close pathref fsp in call_trans2findfirst()
    
    Before freeing the fsp we have to close the handle.
    
    Signed-off-by: Ralph Boehme <slow at samba.org>
    Reviewed-by: Stefan Metzmacher <metze at samba.org>

commit eae7ce8a2e0e0982bba70fbd36f444954339abe3
Author: Ralph Boehme <slow at samba.org>
Date:   Mon Jan 4 16:09:43 2021 +0100

    s3:smbd: turn assignment into assert check in call_trans2findfirst()
    
    The pathref fsp link destructor will set smb_dname->fsp to NULL. Turning this
    into an assert to give a hint at readers of the code trying to understand the
    mechanics.
    
    Signed-off-by: Ralph Boehme <slow at samba.org>
    Reviewed-by: Stefan Metzmacher <metze at samba.org>

commit e1a10b58171ec5a1b41ab99962bc6eebb3b427e3
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Dec 23 13:28:40 2020 +0100

    s3:smbd: let call_trans2findfirst() use file_free() instead of fsp_free()
    
    This makes sure we call vfs_remove_all_fsp_extensions() before
    fsp_free() is called from within file_free(). And allows us to
    make 'fsp_free()' static in the next commits.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit 9b1dc2a4ca61aaa96c3e731a7a59da2a21aa522d
Author: Stefan Metzmacher <metze at samba.org>
Date:   Mon Dec 21 15:31:25 2020 +0100

    s3:smbd: make sure openat_pathref_fsp() calls fd_close(fsp->base_fsp);
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit 8d79764ad3ed75cddec1568d74cbfd3d41e018be
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Dec 23 15:48:36 2020 +0100

    s3:smbd: introduce a reopen_from_fsp() helper function
    
    In future we may move the reopen logic to the VFS,
    but for now we just keep it in one place.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit 38ae1599a0c7408a8a6abf9856ad2979c4c3aa81
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Dec 23 16:03:37 2020 +0100

    s3:smbd: don't pass an unused smb_fname to reopen_from_procfd()
    
    Both callers pass in a helper variable that points to
    fsp->fsp_name and it was only used for a debug message,
    so we can simply use fsp_str_dgb() instead.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit d6949f0f93ff0a1f6292395fbbd9c07b12fe9336
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Dec 23 15:38:03 2020 +0100

    s3:smbd: let open_directory() also use fd_open_atomic() as reopen_from_procfd() fallback
    
    Calling fd_open_atomic() without O_CREAT is the same as calling
    fd_openat() directly, so we can also use it to open an existing
    directory.
    
    In the next step we'll move the reopen_from_procfd() fallback logic to
    a single helper function.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit 30134630988ca76545a8aee8516d44a0dc64bc8d
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Dec 16 15:12:46 2020 +0100

    s3:smbd: let open_pathref_base_fsp() make use of smb_fname_fsp_unlink()
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit c2e7256b1e092acc20daf58059c0e749e3a756e4
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Dec 16 15:02:11 2020 +0100

    s3:smbd: let openat_pathref_fsp() make use of fsp_attach_smb_fname()
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit cff29e58ffaa81785e89f240808af84d6db836c8
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Dec 16 14:50:08 2020 +0100

    s3:smbd: let openat_pathref_fsp() allocate fsp->fsp_name directly on fsp
    
    Otherwise we'll always keep the current talloc_stackframe arround.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit 347edf7ee00609782d6a5d1f4b0995424c831a00
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Dec 16 15:01:38 2020 +0100

    s3:smbd: split out a fsp_attach_smb_fname() helper function
    
    It's useful to watch this using: git show --histogram
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit 1ab038b77a89a7960fbd4cdb55565af6b2333574
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Dec 16 14:15:11 2020 +0100

    s3:smbd: let fsp_set_smb_fname() always link fsp to fsp->fsp_name->fsp
    
    This was only done if fsp->fsp_name already existed, but not the first time.
    
    This also makes sure we modify fsp->fsp_name and fsp->name_hash only on success.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit 932c27e290ead0c2a98c57f2a9649aaf51d7233b
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Dec 16 14:03:36 2020 +0100

    s3:smbd: let fsp_smb_fname_link() set both sides of the link
    
    We also need to be sure both sides were not linked before.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit 3fdfb79a12bf21eb661a8dea00f46bf944ea9df0
Author: Stefan Metzmacher <metze at samba.org>
Date:   Thu Dec 17 11:05:21 2020 +0100

    s3:smbd: rearrange move_smb_fname_fsp_link a bit
    
    We only modify smb_fname_src on success.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

-----------------------------------------------------------------------

Summary of changes:
 source3/include/vfs.h  |   1 +
 source3/smbd/close.c   |  65 +++++++++++++++--
 source3/smbd/durable.c |  35 ++++++----
 source3/smbd/files.c   | 184 ++++++++++++++++++++++++++++++++++---------------
 source3/smbd/open.c    | 128 +++++++++++++++++-----------------
 source3/smbd/proto.h   |   5 +-
 source3/smbd/trans2.c  |  14 +++-
 7 files changed, 289 insertions(+), 143 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source3/include/vfs.h b/source3/include/vfs.h
index 04c8c3e4c76..49726618c5c 100644
--- a/source3/include/vfs.h
+++ b/source3/include/vfs.h
@@ -446,6 +446,7 @@ typedef struct files_struct {
 	struct notify_change_buf *notify;
 
 	struct files_struct *base_fsp; /* placeholder for delete on close */
+	struct files_struct *stream_fsp; /* backlink from base_fsp */
 
 	/*
 	 * Cache of share_mode_data->flags
diff --git a/source3/smbd/close.c b/source3/smbd/close.c
index 20f2ed8a172..97d13473082 100644
--- a/source3/smbd/close.c
+++ b/source3/smbd/close.c
@@ -1290,6 +1290,7 @@ NTSTATUS close_file(struct smb_request *req, files_struct *fsp,
 {
 	NTSTATUS status;
 	struct files_struct *base_fsp = fsp->base_fsp;
+	bool close_base_fsp = false;
 
 	/*
 	 * This fsp can never be an internal dirfsp. They must
@@ -1297,31 +1298,83 @@ NTSTATUS close_file(struct smb_request *req, files_struct *fsp,
 	 */
 	SMB_ASSERT(!fsp->fsp_flags.is_dirfsp);
 
-	if (fsp->fsp_flags.is_directory) {
-		status = close_directory(req, fsp, close_type);
-	} else if (fsp->fake_file_handle != NULL) {
+	if (fsp->stream_fsp != NULL) {
+		/*
+		 * fsp is the base for a stream.
+		 *
+		 * We're called with SHUTDOWN_CLOSE from files.c which walks the
+		 * complete list of files.
+		 *
+		 * We need to wait until the stream is closed.
+		 */
+		SMB_ASSERT(close_type == SHUTDOWN_CLOSE);
+		return NT_STATUS_OK;
+	}
+
+	if (base_fsp != NULL) {
+		/*
+		 * We need to remove the link in order to
+		 * recurse for the base fsp below.
+		 */
+		SMB_ASSERT(base_fsp->base_fsp == NULL);
+		SMB_ASSERT(base_fsp->stream_fsp == fsp);
+		base_fsp->stream_fsp = NULL;
+
+		if (close_type == SHUTDOWN_CLOSE) {
+			/*
+			 * We're called with SHUTDOWN_CLOSE from files.c
+			 * which walks the complete list of files.
+			 *
+			 * We may need to defer the SHUTDOWN_CLOSE
+			 * if it's the next in the linked list.
+			 *
+			 * So we only close if the base is *not* the
+			 * next in the list.
+			 */
+			close_base_fsp = (fsp->next != base_fsp);
+		} else {
+			close_base_fsp = true;
+		}
+	}
+
+	if (fsp->fake_file_handle != NULL) {
 		status = close_fake_file(req, fsp);
 	} else if (fsp->print_file != NULL) {
 		/* FIXME: return spool errors */
 		print_spool_end(fsp, close_type);
 		file_free(req, fsp);
 		status = NT_STATUS_OK;
+	} else if (!fsp->fsp_flags.is_fsa) {
+		if (close_type == NORMAL_CLOSE) {
+			DBG_ERR("unexpected NORMAL_CLOSE for [%s] "
+				"is_fsa[%u] is_pathref[%u] is_directory[%u]\n",
+				fsp_str_dbg(fsp),
+				fsp->fsp_flags.is_fsa,
+				fsp->fsp_flags.is_pathref,
+				fsp->fsp_flags.is_directory);
+		}
+		SMB_ASSERT(close_type != NORMAL_CLOSE);
+		fd_close(fsp);
+		file_free(req, fsp);
+		status = NT_STATUS_OK;
+	} else if (fsp->fsp_flags.is_directory) {
+		status = close_directory(req, fsp, close_type);
 	} else {
 		status = close_normal_file(req, fsp, close_type);
 	}
 
-	if ((base_fsp != NULL) && (close_type != SHUTDOWN_CLOSE)) {
+	if (close_base_fsp) {
 
 		/*
 		 * fsp was a stream, the base fsp can't be a stream as well
 		 *
-		 * For SHUTDOWN_CLOSE this is not possible here, because
+		 * For SHUTDOWN_CLOSE this is not possible here
+		 * (if the base_fsp was the next in the linked list), because
 		 * SHUTDOWN_CLOSE only happens from files.c which walks the
 		 * complete list of files. If we mess with more than one fsp
 		 * those loops will become confused.
 		 */
 
-		SMB_ASSERT(base_fsp->base_fsp == NULL);
 		close_file(req, base_fsp, close_type);
 	}
 
diff --git a/source3/smbd/durable.c b/source3/smbd/durable.c
index 0580ae4adbf..c3f55d1bdff 100644
--- a/source3/smbd/durable.c
+++ b/source3/smbd/durable.c
@@ -719,7 +719,7 @@ NTSTATUS vfs_default_durable_reconnect(struct connection_struct *conn,
 		if (!GUID_equal(fsp_client_guid(fsp),
 				&e.client_guid)) {
 			TALLOC_FREE(lck);
-			fsp_free(fsp);
+			file_free(smb1req, fsp);
 			return NT_STATUS_OBJECT_NAME_NOT_FOUND;
 		}
 
@@ -735,7 +735,7 @@ NTSTATUS vfs_default_durable_reconnect(struct connection_struct *conn,
 			&epoch); /* epoch */
 		if (!NT_STATUS_IS_OK(status)) {
 			TALLOC_FREE(lck);
-			fsp_free(fsp);
+			file_free(smb1req, fsp);
 			return status;
 		}
 
@@ -747,7 +747,7 @@ NTSTATUS vfs_default_durable_reconnect(struct connection_struct *conn,
 			epoch);
 		if (fsp->lease == NULL) {
 			TALLOC_FREE(lck);
-			fsp_free(fsp);
+			file_free(smb1req, fsp);
 			return NT_STATUS_NO_MEMORY;
 		}
 	}
@@ -765,7 +765,7 @@ NTSTATUS vfs_default_durable_reconnect(struct connection_struct *conn,
 	status = fsp_set_smb_fname(fsp, smb_fname);
 	if (!NT_STATUS_IS_OK(status)) {
 		TALLOC_FREE(lck);
-		fsp_free(fsp);
+		file_free(smb1req, fsp);
 		DEBUG(0, ("vfs_default_durable_reconnect: "
 			  "fsp_set_smb_fname failed: %s\n",
 			  nt_errstr(status)));
@@ -786,7 +786,8 @@ NTSTATUS vfs_default_durable_reconnect(struct connection_struct *conn,
 		DBG_DEBUG("Could not set new share_mode_entry values\n");
 		TALLOC_FREE(lck);
 		op->compat = NULL;
-		fsp_free(fsp);
+		fsp->op = NULL;
+		file_free(smb1req, fsp);
 		return NT_STATUS_INTERNAL_ERROR;
 	}
 
@@ -798,7 +799,8 @@ NTSTATUS vfs_default_durable_reconnect(struct connection_struct *conn,
 			  nt_errstr(status)));
 		TALLOC_FREE(lck);
 		op->compat = NULL;
-		fsp_free(fsp);
+		fsp->op = NULL;
+		file_free(smb1req, fsp);
 		return status;
 	}
 
@@ -819,7 +821,8 @@ NTSTATUS vfs_default_durable_reconnect(struct connection_struct *conn,
 		DEBUG(1, ("vfs_default_durable_reconnect: failed to open "
 			  "file: %s\n", nt_errstr(status)));
 		op->compat = NULL;
-		fsp_free(fsp);
+		fsp->op = NULL;
+		file_free(smb1req, fsp);
 		return status;
 	}
 
@@ -846,7 +849,8 @@ NTSTATUS vfs_default_durable_reconnect(struct connection_struct *conn,
 		}
 		TALLOC_FREE(lck);
 		op->compat = NULL;
-		fsp_free(fsp);
+		fsp->op = NULL;
+		file_free(smb1req, fsp);
 		return status;
 	}
 
@@ -859,7 +863,8 @@ NTSTATUS vfs_default_durable_reconnect(struct connection_struct *conn,
 		}
 		TALLOC_FREE(lck);
 		op->compat = NULL;
-		fsp_free(fsp);
+		fsp->op = NULL;
+		file_free(smb1req, fsp);
 		return NT_STATUS_OBJECT_NAME_NOT_FOUND;
 	}
 
@@ -873,7 +878,8 @@ NTSTATUS vfs_default_durable_reconnect(struct connection_struct *conn,
 		}
 		TALLOC_FREE(lck);
 		op->compat = NULL;
-		fsp_free(fsp);
+		fsp->op = NULL;
+		file_free(smb1req, fsp);
 		return NT_STATUS_OBJECT_NAME_NOT_FOUND;
 	}
 
@@ -891,7 +897,8 @@ NTSTATUS vfs_default_durable_reconnect(struct connection_struct *conn,
 		}
 		TALLOC_FREE(lck);
 		op->compat = NULL;
-		fsp_free(fsp);
+		fsp->op = NULL;
+		file_free(smb1req, fsp);
 		return NT_STATUS_OBJECT_NAME_NOT_FOUND;
 	}
 
@@ -907,7 +914,8 @@ NTSTATUS vfs_default_durable_reconnect(struct connection_struct *conn,
 		}
 		TALLOC_FREE(lck);
 		op->compat = NULL;
-		fsp_free(fsp);
+		fsp->op = NULL;
+		file_free(smb1req, fsp);
 		return status;
 	}
 
@@ -918,7 +926,8 @@ NTSTATUS vfs_default_durable_reconnect(struct connection_struct *conn,
 			  "vfs_default_durable_cookie - %s\n",
 			  nt_errstr(status)));
 		op->compat = NULL;
-		fsp_free(fsp);
+		fsp->op = NULL;
+		file_free(smb1req, fsp);
 		return status;
 	}
 
diff --git a/source3/smbd/files.c b/source3/smbd/files.c
index e19c11883eb..f60d5979f53 100644
--- a/source3/smbd/files.c
+++ b/source3/smbd/files.c
@@ -26,6 +26,9 @@
 
 #define FILE_HANDLE_OFFSET 0x1000
 
+static NTSTATUS fsp_attach_smb_fname(struct files_struct *fsp,
+				     struct smb_filename **_smb_fname);
+
 /**
  * create new fsp to be used for file_new or a durable handle reconnect
  */
@@ -183,6 +186,28 @@ NTSTATUS file_new(struct smb_request *req, connection_struct *conn,
 	return NT_STATUS_OK;
 }
 
+NTSTATUS create_internal_fsp(connection_struct *conn,
+			     const struct smb_filename *smb_fname,
+			     struct files_struct **_fsp)
+{
+	struct files_struct *fsp = NULL;
+	NTSTATUS status;
+
+	status = file_new(NULL, conn, &fsp);
+	if (!NT_STATUS_IS_OK(status)) {
+		return status;
+	}
+
+	status = fsp_set_smb_fname(fsp, smb_fname);
+	if (!NT_STATUS_IS_OK(status)) {
+		file_free(NULL, fsp);
+		return status;
+	}
+
+	*_fsp = fsp;
+	return NT_STATUS_OK;
+}
+
 /*
  * Create an internal fsp for an *existing* directory.
  *
@@ -196,17 +221,11 @@ NTSTATUS create_internal_dirfsp(connection_struct *conn,
 	struct files_struct *fsp = NULL;
 	NTSTATUS status;
 
-	status = file_new(NULL, conn, &fsp);
+	status = create_internal_fsp(conn, smb_dname, &fsp);
 	if (!NT_STATUS_IS_OK(status)) {
 		return status;
 	}
 
-	status = fsp_set_smb_fname(fsp, smb_dname);
-	if (!NT_STATUS_IS_OK(status)) {
-		file_free(NULL, fsp);
-		return status;
-	}
-
 	fsp->access_mask = FILE_LIST_DIRECTORY;
 	fsp->fsp_flags.is_directory = true;
 	fsp->fsp_flags.is_dirfsp = true;
@@ -299,6 +318,9 @@ static NTSTATUS fsp_smb_fname_link(struct files_struct *fsp,
 {
 	struct fsp_smb_fname_link *link = NULL;
 
+	SMB_ASSERT(*smb_fname_link == NULL);
+	SMB_ASSERT(*smb_fname_fsp == NULL);
+
 	link = talloc_zero(fsp, struct fsp_smb_fname_link);
 	if (link == NULL) {
 		return NT_STATUS_NO_MEMORY;
@@ -307,6 +329,7 @@ static NTSTATUS fsp_smb_fname_link(struct files_struct *fsp,
 	link->smb_fname_link = smb_fname_link;
 	link->smb_fname_fsp = smb_fname_fsp;
 	*smb_fname_link = link;
+	*smb_fname_fsp = fsp;
 
 	talloc_set_destructor(link, fsp_smb_fname_link_destructor);
 	return NT_STATUS_OK;
@@ -343,10 +366,13 @@ static int smb_fname_fsp_destructor(struct smb_filename *smb_fname)
 	}
 
 	if (fsp->base_fsp != NULL) {
-		status = fd_close(fsp->base_fsp);
+		struct files_struct *tmp_base_fsp = fsp->base_fsp;
+
+		fsp_set_base_fsp(fsp, NULL);
+
+		status = fd_close(tmp_base_fsp);
 		SMB_ASSERT(NT_STATUS_IS_OK(status));
-		file_free(NULL, fsp->base_fsp);
-		fsp->base_fsp = NULL;
+		file_free(NULL, tmp_base_fsp);
 	}
 
 	status = fd_close(fsp);
@@ -388,10 +414,8 @@ static NTSTATUS open_pathref_base_fsp(const struct files_struct *dirfsp,
 		return NT_STATUS_OBJECT_NAME_NOT_FOUND;
 	}
 
-	fsp->base_fsp = smb_fname_base->fsp;
-	smb_fname_base->fsp = NULL;
-	talloc_set_destructor(smb_fname_base->fsp_link, NULL);
-	talloc_set_destructor(smb_fname_base, NULL);
+	fsp_set_base_fsp(fsp, smb_fname_base->fsp);
+	smb_fname_fsp_unlink(smb_fname_base);
 	TALLOC_FREE(smb_fname_base);
 
 	return NT_STATUS_OK;
@@ -441,7 +465,7 @@ NTSTATUS openat_pathref_fsp(const struct files_struct *dirfsp,
 		open_flags |= O_DIRECTORY;
 	}
 
-	full_fname = full_path_from_dirfsp_atname(talloc_tos(),
+	full_fname = full_path_from_dirfsp_atname(fsp,
 						  dirfsp,
 						  smb_fname);
 	if (full_fname == NULL) {
@@ -449,15 +473,11 @@ NTSTATUS openat_pathref_fsp(const struct files_struct *dirfsp,
 		goto fail;
 	}
 
-	fsp->fsp_name = talloc_move(fsp, &full_fname);
-
-	if (is_ntfs_default_stream_smb_fname(fsp->fsp_name)) {
-		fsp->fsp_name->stream_name = NULL;
+	if (is_ntfs_default_stream_smb_fname(full_fname)) {
+		full_fname->stream_name = NULL;
 	}
 
-	status = file_name_hash(fsp->conn,
-				smb_fname_str_dbg(fsp->fsp_name),
-				&fsp->name_hash);
+	status = fsp_attach_smb_fname(fsp, &full_fname);
 	if (!NT_STATUS_IS_OK(status)) {
 		goto fail;
 	}
@@ -478,10 +498,13 @@ NTSTATUS openat_pathref_fsp(const struct files_struct *dirfsp,
 			  nt_errstr(status));
 
 		if (fsp->base_fsp != NULL) {
-			file_free(NULL, fsp->base_fsp);
-			fsp->base_fsp = NULL;
+			struct files_struct *tmp_base_fsp = fsp->base_fsp;
+
+			fsp_set_base_fsp(fsp, NULL);
+
+			fd_close(tmp_base_fsp);
+			file_free(NULL, tmp_base_fsp);
 		}
-		fd_close(fsp);
 		file_free(NULL, fsp);
 		fsp = NULL;
 
@@ -525,9 +548,6 @@ NTSTATUS openat_pathref_fsp(const struct files_struct *dirfsp,
 
 	fsp->file_id = vfs_file_id_from_sbuf(conn, &fsp->fsp_name->st);
 
-	fsp->fsp_name->fsp = fsp;
-	smb_fname->fsp = fsp;
-
 	status = fsp_smb_fname_link(fsp,
 				    &smb_fname->fsp_link,
 				    &smb_fname->fsp);
@@ -535,13 +555,6 @@ NTSTATUS openat_pathref_fsp(const struct files_struct *dirfsp,
 		goto fail;
 	}
 
-	status = fsp_smb_fname_link(fsp,
-				    &fsp->fsp_name->fsp_link,
-				    &fsp->fsp_name->fsp);
-	if (!NT_STATUS_IS_OK(status)) {
-		goto fail;
-	}
-
 	DBG_DEBUG("fsp [%s]: OK\n", fsp_str_dbg(fsp));
 
 	talloc_set_destructor(smb_fname, smb_fname_fsp_destructor);
@@ -556,8 +569,12 @@ fail:
 		return status;
 	}
 	if (fsp->base_fsp != NULL) {
-		file_free(NULL, fsp->base_fsp);
-		fsp->base_fsp = NULL;
+		struct files_struct *tmp_base_fsp = fsp->base_fsp;
+
+		fsp_set_base_fsp(fsp, NULL);
+
+		fd_close(tmp_base_fsp);
+		file_free(NULL, tmp_base_fsp);
 	}
 	fd_close(fsp);
 	file_free(NULL, fsp);
@@ -581,22 +598,27 @@ NTSTATUS move_smb_fname_fsp_link(struct smb_filename *smb_fname_dst,
 {
 	NTSTATUS status;
 
+	/*
+	 * The target should always not be linked yet!
+	 */
+	SMB_ASSERT(smb_fname_dst->fsp == NULL);
+	SMB_ASSERT(smb_fname_dst->fsp_link == NULL);
+
 	if (smb_fname_src->fsp == NULL) {
 		return NT_STATUS_OK;
 	}
 
-	smb_fname_dst->fsp = smb_fname_src->fsp;
-	talloc_set_destructor(smb_fname_dst, smb_fname_fsp_destructor);
-
-	smb_fname_fsp_unlink(smb_fname_src);
-
-	status = fsp_smb_fname_link(smb_fname_dst->fsp,
+	status = fsp_smb_fname_link(smb_fname_src->fsp,
 				    &smb_fname_dst->fsp_link,
 				    &smb_fname_dst->fsp);
 	if (!NT_STATUS_IS_OK(status)) {
 		return status;
 	}
 
+	talloc_set_destructor(smb_fname_dst, smb_fname_fsp_destructor);
+
+	smb_fname_fsp_unlink(smb_fname_src);
+
 	return NT_STATUS_OK;
 }
 
@@ -918,7 +940,7 @@ bool file_find_subpath(files_struct *dir_fsp)
  Free up a fsp.
 ****************************************************************************/
 
-void fsp_free(files_struct *fsp)
+static void fsp_free(files_struct *fsp)
 {
 	struct smbd_server_connection *sconn = fsp->conn->sconn;
 
@@ -1223,13 +1245,47 @@ NTSTATUS file_name_hash(connection_struct *conn,
 	return NT_STATUS_OK;
 }
 
+static NTSTATUS fsp_attach_smb_fname(struct files_struct *fsp,
+				     struct smb_filename **_smb_fname)
+{
+	struct smb_filename *smb_fname_new = *_smb_fname;
+	const char *name_str = NULL;
+	uint32_t name_hash = 0;
+	NTSTATUS status;
+
+	name_str = smb_fname_str_dbg(smb_fname_new);
+	if (name_str == NULL) {
+		return NT_STATUS_NO_MEMORY;
+	}
+
+	status = file_name_hash(fsp->conn,
+				name_str,


-- 
Samba Shared Repository



More information about the samba-cvs mailing list