diff options
| -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;  }  | 
