diff options
author | Jeremy Allison <jra@samba.org> | 2012-09-06 17:14:52 -0700 |
---|---|---|
committer | Jeremy Allison <jra@samba.org> | 2012-09-10 23:34:06 +0200 |
commit | ba5f557b5db9fbc9a59d742d2612b397b5525266 (patch) | |
tree | a569ca9f73e39700f99a5b830fe43546f40a6e01 /source3 | |
parent | cfeac09fc0796ecf77593244e9e72c1521fd251c (diff) | |
download | samba-ba5f557b5db9fbc9a59d742d2612b397b5525266.tar.gz samba-ba5f557b5db9fbc9a59d742d2612b397b5525266.tar.bz2 samba-ba5f557b5db9fbc9a59d742d2612b397b5525266.zip |
Fix talloc memory heirarchy bug. If there's an SMB2 sessionsetup in flight when we're shut down, we end up freeing the struct smbXsrv_session *session pointer twice.
Autobuild-User(master): Jeremy Allison <jra@samba.org>
Autobuild-Date(master): Mon Sep 10 23:34:06 CEST 2012 on sn-devel-104
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; } |