The Samba-Bugzilla – Attachment 16284 Details for
Bug 14533
A multichannel disconnect with a pending open may lead to a panic
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
Work in progress patches for master
tmp.diff.txt (text/plain), 10.11 KB, created by
Stefan Metzmacher
on 2020-10-14 12:53:15 UTC
(
hide
)
Description:
Work in progress patches for master
Filename:
MIME Type:
Creator:
Stefan Metzmacher
Created:
2020-10-14 12:53:15 UTC
Size:
10.11 KB
patch
obsolete
>From d3c876b2d70a7b0032980e7091be6d17ad7fc443 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Wed, 23 Sep 2020 04:58:22 +0200 >Subject: [PATCH 1/3] source4/torture/smb2/lease.c > test_lease_timeout_disconnect > >--- > source4/torture/smb2/lease.c | 153 +++++++++++++++++++++++++++++++++++ > 1 file changed, 153 insertions(+) > >diff --git a/source4/torture/smb2/lease.c b/source4/torture/smb2/lease.c >index d3b8daea3105..ca65c53c8f7c 100644 >--- a/source4/torture/smb2/lease.c >+++ b/source4/torture/smb2/lease.c >@@ -4151,6 +4151,158 @@ done: > return ret; > } > >+static bool test_lease_timeout_disconnect(struct torture_context *tctx, >+ struct smb2_tree *tree1) >+{ >+ TALLOC_CTX *mem_ctx = talloc_new(tctx); >+ NTSTATUS status; >+ bool ret = true; >+ struct smbcli_options transport2_options; >+ struct smbcli_options transport3_options; >+ struct smb2_tree *tree2 = NULL; >+ //struct smb2_session *session2 = NULL; >+ struct smb2_tree *tree3 = NULL; >+ //struct smb2_session *session3 = NULL; >+ //struct smb2_session *session1 = tree1->session; >+ struct smb2_transport *transport1 = tree1->session->transport; >+ struct smb2_transport *transport2; >+ struct smb2_transport *transport3; >+ //struct smb2_handle h1 = {{ 0 }}; >+ const char *fname = "lease_timeout_logoff.dat" ; >+ uint32_t caps; >+ struct smb2_create io1; >+ struct smb2_create io2; >+ struct smb2_request *req2 = NULL; >+ struct smb2_lease ls1; >+ >+ caps = smb2cli_conn_server_capabilities( >+ tree1->session->transport->conn); >+ if (!(caps & SMB2_CAP_LEASING)) { >+ torture_skip(tctx, "leases are not supported"); >+ } >+ >+ smb2_util_unlink(tree1, fname); >+ >+ /* Connect 2nd connection */ >+ torture_comment(tctx, "connect tree2 with the same client_guid\n"); >+ transport2_options = transport1->options; >+ if (!torture_smb2_connection_ext(tctx, 0, &transport2_options, &tree2)) { >+ torture_warning(tctx, "couldn't reconnect, bailing\n"); >+ return false; >+ } >+ transport2 = tree2->session->transport; >+ //session2 = tree2->session; >+ >+ /* Connect 3rd connection */ >+ torture_comment(tctx, "connect tree3 with the same client_guid\n"); >+ transport3_options = transport1->options; >+ if (!torture_smb2_connection_ext(tctx, 0, &transport3_options, &tree3)) { >+ torture_warning(tctx, "couldn't reconnect, bailing\n"); >+ return false; >+ } >+ transport3 = tree3->session->transport; >+ //session3 = tree3->session; >+ >+ /* Set lease handlers */ >+ transport1->lease.handler = torture_lease_handler; >+ transport1->lease.private_data = tree1; >+ transport2->lease.handler = torture_lease_handler; >+ transport2->lease.private_data = tree2; >+ transport3->lease.handler = torture_lease_handler; >+ transport3->lease.private_data = tree3; >+ >+ smb2_lease_create_share(&io1, &ls1, false, fname, >+ smb2_util_share_access(""), >+ LEASE1, >+ smb2_util_lease_state("RH")); >+ io1.in.durable_open = true; >+ smb2_generic_create(&io2, NULL, false, fname, >+ NTCREATEX_DISP_OPEN_IF, >+ SMB2_OPLOCK_LEVEL_NONE, 0, 0); >+ >+ torture_comment(tctx, "tree1: create file[%s] with durable RH lease (SHARE NONE)\n", fname); >+ torture_reset_lease_break_info(tctx, &lease_break_info); >+ lease_break_info.lease_skip_ack = true; >+ status = smb2_create(tree1, mem_ctx, &io1); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ //h1 = io1.out.file.handle; >+ CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE); >+ CHECK_LEASE(&io1, "RH", true, LEASE1, 0); >+ CHECK_VAL(lease_break_info.count, 0); >+ >+ torture_comment(tctx, "tree1: skip lease acks\n"); >+ torture_reset_lease_break_info(tctx, &lease_break_info); >+ lease_break_info.lease_skip_ack = true; >+ torture_comment(tctx, "tree2: open file[%s] without lease (SHARE RWD)\n", fname); >+ req2 = smb2_create_send(tree2, &io2); >+ torture_assert(tctx, req2 != NULL, "req2 started"); >+ >+ torture_comment(tctx, "tree1: wait for lease break\n"); >+ torture_wait_for_lease_break(tctx); >+ CHECK_VAL(lease_break_info.count, 1); >+ CHECK_BREAK_INFO("RH", "R", LEASE1); >+ >+ torture_comment(tctx, "tree1: reset lease handler\n"); >+ torture_reset_lease_break_info(tctx, &lease_break_info); >+ lease_break_info.lease_skip_ack = true; >+ CHECK_VAL(lease_break_info.count, 0); >+ >+ torture_comment(tctx, "tree2: check for SMB2_REQUEST_RECV\n"); >+ torture_assert_int_equal(tctx, req2->state, >+ SMB2_REQUEST_RECV, >+ "SMB2_REQUEST_RECV"); >+ >+ torture_comment(tctx, "sleep 1\n"); >+ smb_msleep(1); >+ >+ torture_comment(tctx, "transport1: keepalive\n"); >+ status = smb2_keepalive(transport1); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ >+ torture_comment(tctx, "transport2: keepalive\n"); >+ status = smb2_keepalive(transport2); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ >+ torture_comment(tctx, "transport3: keepalive\n"); >+ status = smb2_keepalive(transport3); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ >+ torture_comment(tctx, "tree2: check for SMB2_REQUEST_RECV\n"); >+ torture_assert_int_equal(tctx, req2->state, >+ SMB2_REQUEST_RECV, >+ "SMB2_REQUEST_RECV"); >+ torture_comment(tctx, "tree2: check for STATUS_PENDING\n"); >+ torture_assert(tctx, req2->cancel.can_cancel, "STATUS_PENDING"); >+ >+ torture_comment(tctx, "sleep 1\n"); >+ smb_msleep(1000); >+ torture_comment(tctx, "transport1: keepalive\n"); >+ status = smb2_keepalive(transport1); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ torture_comment(tctx, "transport2: disconnect\n"); >+ TALLOC_FREE(tree2); >+ >+ torture_comment(tctx, "sleep 1\n"); >+ smb_msleep(1000); >+ torture_comment(tctx, "transport1: keepalive\n"); >+ status = smb2_keepalive(transport1); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ torture_comment(tctx, "transport1: disconnect\n"); >+ TALLOC_FREE(tree1); >+ >+ torture_comment(tctx, "sleep 1\n"); >+ smb_msleep(1000); >+ torture_comment(tctx, "transport3: keepalive\n"); >+ status = smb2_keepalive(transport3); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ torture_comment(tctx, "transport3: disconnect\n"); >+ TALLOC_FREE(tree3); >+ >+done: >+ >+ return ret; >+} >+ > struct torture_suite *torture_smb2_lease_init(TALLOC_CTX *ctx) > { > struct torture_suite *suite = >@@ -4192,6 +4344,7 @@ struct torture_suite *torture_smb2_lease_init(TALLOC_CTX *ctx) > torture_suite_add_1smb2_test(suite, "dynamic_share", test_lease_dynamic_share); > torture_suite_add_1smb2_test(suite, "timeout", test_lease_timeout); > torture_suite_add_1smb2_test(suite, "unlink", test_lease_unlink); >+ torture_suite_add_1smb2_test(suite, "timeout-disconnect", test_lease_timeout_disconnect); > > suite->description = talloc_strdup(suite, "SMB2-LEASE tests"); > >-- >2.17.1 > > >From e00e92146986ac084b96f59c8875f7fd42ecc0e0 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Wed, 23 Sep 2020 13:07:20 +0200 >Subject: [PATCH 2/3] xconn->transport.terminating = true > >--- > source3/smbd/globals.h | 1 + > source3/smbd/smb2_server.c | 8 ++++++++ > 2 files changed, 9 insertions(+) > >diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h >index fcf33a699c68..43d329caa8a1 100644 >--- a/source3/smbd/globals.h >+++ b/source3/smbd/globals.h >@@ -367,6 +367,7 @@ struct smbXsrv_connection { > > struct { > NTSTATUS status; >+ bool terminating; > int sock; > struct tevent_fd *fde; > >diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c >index cf9de185c1f4..ca839c3cfc67 100644 >--- a/source3/smbd/smb2_server.c >+++ b/source3/smbd/smb2_server.c >@@ -1631,6 +1631,14 @@ void smbd_server_connection_terminate_ex(struct smbXsrv_connection *xconn, > > num_ok = smbXsrv_client_valid_connections(client); > >+ if (xconn->transport.terminating) { >+ DBG_DEBUG("skip recursion conn[%s] num_ok[%zu] reason[%s] at %s\n", >+ smbXsrv_connection_dbg(xconn), num_ok, >+ reason, location); >+ return; >+ } >+ xconn->transport.terminating = true; >+ > DBG_DEBUG("conn[%s] num_ok[%zu] reason[%s] at %s\n", > smbXsrv_connection_dbg(xconn), num_ok, > reason, location); >-- >2.17.1 > > >From ec14e831cd4e79207290107045216c37cec0f3d8 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Wed, 23 Sep 2020 13:19:49 +0200 >Subject: [PATCH 3/3] assert that xconn is alive for the lifetime of > smbXsrv_connection_shutdown_send/recv > >--- > source3/smbd/smb2_server.c | 23 +++++++++++++++++++++++ > 1 file changed, 23 insertions(+) > >diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c >index ca839c3cfc67..3f99c86ce253 100644 >--- a/source3/smbd/smb2_server.c >+++ b/source3/smbd/smb2_server.c >@@ -1494,6 +1494,7 @@ size_t smbXsrv_client_valid_connections(struct smbXsrv_client *client) > > struct smbXsrv_connection_shutdown_state { > struct tevent_queue *wait_queue; >+ struct smbXsrv_connection *xconn; > }; > > static void smbXsrv_connection_shutdown_wait_done(struct tevent_req *subreq); >@@ -1514,6 +1515,7 @@ static struct tevent_req *smbXsrv_connection_shutdown_send(TALLOC_CTX *mem_ctx, > * smbXsrv_connection_disconnect_transport() before. > */ > SMB_ASSERT(!NT_STATUS_IS_OK(xconn->transport.status)); >+ SMB_ASSERT(xconn->transport.terminating); > > req = tevent_req_create(mem_ctx, &state, > struct smbXsrv_connection_shutdown_state); >@@ -1521,6 +1523,9 @@ static struct tevent_req *smbXsrv_connection_shutdown_send(TALLOC_CTX *mem_ctx, > return NULL; > } > >+ state->xconn = xconn; >+ tevent_req_defer_callback(req, ev); >+ > status = smbXsrv_session_disconnect_xconn(xconn); > if (tevent_req_nterror(req, status)) { > return tevent_req_post(req, ev); >@@ -1584,15 +1589,33 @@ static void smbXsrv_connection_shutdown_wait_done(struct tevent_req *subreq) > struct tevent_req *req = > tevent_req_callback_data(subreq, > struct tevent_req); >+ struct smbXsrv_connection_shutdown_state *state = >+ tevent_req_data(req, >+ struct smbXsrv_connection_shutdown_state); >+ struct smbXsrv_connection *xconn = state->xconn; > > tevent_queue_wait_recv(subreq); > TALLOC_FREE(subreq); > > tevent_req_done(req); >+ /* >+ * make sure the xconn pointer is still valid, >+ * it should as we used tevent_req_defer_callback() >+ */ >+ SMB_ASSERT(xconn->transport.terminating); > } > > static NTSTATUS smbXsrv_connection_shutdown_recv(struct tevent_req *req) > { >+ struct smbXsrv_connection_shutdown_state *state = >+ tevent_req_data(req, >+ struct smbXsrv_connection_shutdown_state); >+ struct smbXsrv_connection *xconn = state->xconn; >+ /* >+ * make sure the xconn pointer is still valid, >+ * it should as we used tevent_req_defer_callback() >+ */ >+ SMB_ASSERT(xconn->transport.terminating); > return tevent_req_simple_recv_ntstatus(req); > } > >-- >2.17.1 >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Actions:
View
Attachments on
bug 14533
: 16284