diff options
Diffstat (limited to 'source3')
-rw-r--r-- | source3/smbd/smb2_sesssetup.c | 41 |
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; } |