summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/smbd/smb2_sesssetup.c41
1 files changed, 36 insertions, 5 deletions
diff --git a/source3/smbd/smb2_sesssetup.c b/source3/smbd/smb2_sesssetup.c
index a03abf73aa..61b5519d97 100644
--- a/source3/smbd/smb2_sesssetup.c
+++ b/source3/smbd/smb2_sesssetup.c
@@ -439,8 +439,16 @@ struct smbd_smb2_session_setup_state {
uint16_t out_session_flags;
DATA_BLOB out_security_buffer;
uint64_t out_session_id;
+ /* The following pointer is owned by state->session. */
+ struct smbd_smb2_session_setup_state **pp_self_ref;
};
+static int pp_self_ref_destructor(struct smbd_smb2_session_setup_state **pp_state)
+{
+ (*pp_state)->session = NULL;
+ return 0;
+}
+
static int smbd_smb2_session_setup_state_destructor(struct smbd_smb2_session_setup_state *state)
{
/*
@@ -454,6 +462,24 @@ static int smbd_smb2_session_setup_state_destructor(struct smbd_smb2_session_set
static void smbd_smb2_session_setup_gensec_done(struct tevent_req *subreq);
static void smbd_smb2_session_setup_previous_done(struct tevent_req *subreq);
+/************************************************************************
+ We have to tag the state->session pointer with memory talloc'ed
+ on it to ensure it gets NULL'ed out if the underlying struct smbXsrv_session
+ is deleted by shutdown whilst this request is in flight.
+************************************************************************/
+
+static NTSTATUS tag_state_session_ptr(struct smbd_smb2_session_setup_state *state)
+{
+ state->pp_self_ref = talloc_zero(state->session,
+ struct smbd_smb2_session_setup_state *);
+ if (state->pp_self_ref == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ *state->pp_self_ref = state;
+ talloc_set_destructor(state->pp_self_ref, pp_self_ref_destructor);
+ return NT_STATUS_OK;
+}
+
static struct tevent_req *smbd_smb2_session_setup_send(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
struct smbd_smb2_request *smb2req,
@@ -522,6 +548,11 @@ static struct tevent_req *smbd_smb2_session_setup_send(TALLOC_CTX *mem_ctx,
}
}
+ status = tag_state_session_ptr(state);
+ if (tevent_req_nterror(req, status)) {
+ return tevent_req_post(req, ev);
+ }
+
if (state->session->gensec == NULL) {
status = auth_generic_prepare(state->session,
state->session->connection->remote_address,
@@ -577,7 +608,7 @@ static void smbd_smb2_session_setup_gensec_done(struct tevent_req *subreq)
if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
state->out_session_id = state->session->global->session_wire_id;
/* we want to keep the session */
- state->session = NULL;
+ TALLOC_FREE(state->pp_self_ref);
tevent_req_nterror(req, status);
return;
}
@@ -617,7 +648,7 @@ static void smbd_smb2_session_setup_gensec_done(struct tevent_req *subreq)
return;
}
/* we want to keep the session */
- state->session = NULL;
+ TALLOC_FREE(state->pp_self_ref);
tevent_req_done(req);
return;
}
@@ -633,7 +664,7 @@ static void smbd_smb2_session_setup_gensec_done(struct tevent_req *subreq)
}
/* we want to keep the session */
- state->session = NULL;
+ TALLOC_FREE(state->pp_self_ref);
tevent_req_done(req);
return;
}
@@ -664,7 +695,7 @@ static void smbd_smb2_session_setup_previous_done(struct tevent_req *subreq)
return;
}
/* we want to keep the session */
- state->session = NULL;
+ TALLOC_FREE(state->pp_self_ref);
tevent_req_done(req);
return;
}
@@ -680,7 +711,7 @@ static void smbd_smb2_session_setup_previous_done(struct tevent_req *subreq)
}
/* we want to keep the session */
- state->session = NULL;
+ TALLOC_FREE(state->pp_self_ref);
tevent_req_done(req);
return;
}