From 6dc59035aee721fb14bf38ecd0e00acba9adab05 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 31 Jul 2019 14:17:02 +0200 Subject: [PATCH] smbd: Fix use-after-free from exit_server_common() We need to keep the smbXsrv_connection structures around until all pending requests have had their chance to clean up behind them. If you look at srv_send_smb(), it's exactly prepared already to just drop anything on the floor when the transport has been declared dead: if (!NT_STATUS_IS_OK(xconn->transport.status)) { /* * we're not supposed to do any io */ return true; } Bug: https://bugzilla.samba.org/show_bug.cgi?id=14064 Signed-off-by: Volker Lendecke Reviewed-by: Stefan Metzmacher Autobuild-User(master): Stefan Metzmacher Autobuild-Date(master): Thu Aug 1 15:39:13 UTC 2019 on sn-devel-184 (cherry picked from commit c226dc6e8a18343031829c35552e557903593daf) --- source3/smbd/server_exit.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/source3/smbd/server_exit.c b/source3/smbd/server_exit.c index 2378c0c15ca..b21501a7a23 100644 --- a/source3/smbd/server_exit.c +++ b/source3/smbd/server_exit.c @@ -91,7 +91,6 @@ static void exit_server_common(enum server_exit_reason how, { struct smbXsrv_client *client = global_smbXsrv_client; struct smbXsrv_connection *xconn = NULL; - struct smbXsrv_connection *xconn_next = NULL; struct smbd_server_connection *sconn = NULL; struct messaging_context *msg_ctx = global_messaging_context(); @@ -110,10 +109,7 @@ static void exit_server_common(enum server_exit_reason how, /* * Here we typically have just one connection */ - for (; xconn != NULL; xconn = xconn_next) { - xconn_next = xconn->next; - DLIST_REMOVE(client->connections, xconn); - + for (; xconn != NULL; xconn = xconn->next) { /* * This is typically the disconnect for the only * (or with multi-channel last) connection of the client @@ -128,8 +124,6 @@ static void exit_server_common(enum server_exit_reason how, break; } } - - TALLOC_FREE(xconn); DO_PROFILE_INC(disconnect); } @@ -172,6 +166,20 @@ static void exit_server_common(enum server_exit_reason how, change_to_root_user(); + if (client != NULL) { + struct smbXsrv_connection *xconn_next = NULL; + + for (xconn = client->connections; + xconn != NULL; + xconn = xconn_next) { + xconn_next = xconn->next; + DLIST_REMOVE(client->connections, xconn); + TALLOC_FREE(xconn); + } + } + + change_to_root_user(); + /* 3 second timeout. */ print_notify_send_messages(msg_ctx, 3); -- 2.11.0