mirror of
https://github.com/samba-team/samba.git
synced 2025-01-11 05:18:09 +03:00
smbXsrv_client: handle NAME_NOT_FOUND from smb2srv_client_connection_{pass,drop}()
If we get NT_STATUS_OBJECT_NOT_FOUND from smb2srv_client_connection_{pass,drop}() we should just keep the connection and overwrite the stale record in smbXsrv_client_global.tdb. It's basically a race with serverid_exists() and a process that doesn't cleanly teardown. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15200 Signed-off-by: Stefan Metzmacher <metze@samba.org> Reviewed-by: Ralph Boehme <slow@samba.org>
This commit is contained in:
parent
8c8d8cf01e
commit
5d66d5b84f
@ -189,6 +189,7 @@ static void smbXsrv_client_global_verify_record(struct db_record *db_rec,
|
|||||||
bool *is_free,
|
bool *is_free,
|
||||||
bool *was_free,
|
bool *was_free,
|
||||||
TALLOC_CTX *mem_ctx,
|
TALLOC_CTX *mem_ctx,
|
||||||
|
const struct server_id *dead_server_id,
|
||||||
struct smbXsrv_client_global0 **_g,
|
struct smbXsrv_client_global0 **_g,
|
||||||
uint32_t *pseqnum)
|
uint32_t *pseqnum)
|
||||||
{
|
{
|
||||||
@ -198,6 +199,7 @@ static void smbXsrv_client_global_verify_record(struct db_record *db_rec,
|
|||||||
struct smbXsrv_client_globalB global_blob;
|
struct smbXsrv_client_globalB global_blob;
|
||||||
enum ndr_err_code ndr_err;
|
enum ndr_err_code ndr_err;
|
||||||
struct smbXsrv_client_global0 *global = NULL;
|
struct smbXsrv_client_global0 *global = NULL;
|
||||||
|
bool dead = false;
|
||||||
bool exists;
|
bool exists;
|
||||||
TALLOC_CTX *frame = talloc_stackframe();
|
TALLOC_CTX *frame = talloc_stackframe();
|
||||||
|
|
||||||
@ -254,6 +256,22 @@ static void smbXsrv_client_global_verify_record(struct db_record *db_rec,
|
|||||||
|
|
||||||
global = global_blob.info.info0;
|
global = global_blob.info.info0;
|
||||||
|
|
||||||
|
dead = server_id_equal(dead_server_id, &global->server_id);
|
||||||
|
if (dead) {
|
||||||
|
struct server_id_buf tmp;
|
||||||
|
|
||||||
|
DBG_NOTICE("key '%s' server_id %s is already dead.\n",
|
||||||
|
hex_encode_talloc(frame, key.dptr, key.dsize),
|
||||||
|
server_id_str_buf(global->server_id, &tmp));
|
||||||
|
if (DEBUGLVL(DBGLVL_NOTICE)) {
|
||||||
|
NDR_PRINT_DEBUG(smbXsrv_client_globalB, &global_blob);
|
||||||
|
}
|
||||||
|
TALLOC_FREE(frame);
|
||||||
|
dbwrap_record_delete(db_rec);
|
||||||
|
*is_free = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
exists = serverid_exists(&global->server_id);
|
exists = serverid_exists(&global->server_id);
|
||||||
if (!exists) {
|
if (!exists) {
|
||||||
struct server_id_buf tmp;
|
struct server_id_buf tmp;
|
||||||
@ -534,6 +552,7 @@ static void smb2srv_client_mc_negprot_next(struct tevent_req *req)
|
|||||||
struct tevent_req *subreq = NULL;
|
struct tevent_req *subreq = NULL;
|
||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
uint32_t seqnum = 0;
|
uint32_t seqnum = 0;
|
||||||
|
struct server_id last_server_id = { .pid = 0, };
|
||||||
|
|
||||||
TALLOC_FREE(state->filter_subreq);
|
TALLOC_FREE(state->filter_subreq);
|
||||||
SMB_ASSERT(state->db_rec == NULL);
|
SMB_ASSERT(state->db_rec == NULL);
|
||||||
@ -545,10 +564,14 @@ static void smb2srv_client_mc_negprot_next(struct tevent_req *req)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
verify_again:
|
||||||
|
TALLOC_FREE(global);
|
||||||
|
|
||||||
smbXsrv_client_global_verify_record(state->db_rec,
|
smbXsrv_client_global_verify_record(state->db_rec,
|
||||||
&is_free,
|
&is_free,
|
||||||
NULL,
|
NULL,
|
||||||
state,
|
state,
|
||||||
|
&last_server_id,
|
||||||
&global,
|
&global,
|
||||||
&seqnum);
|
&seqnum);
|
||||||
if (is_free) {
|
if (is_free) {
|
||||||
@ -602,6 +625,16 @@ static void smb2srv_client_mc_negprot_next(struct tevent_req *req)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If last_server_id is set, we expect
|
||||||
|
* smbXsrv_client_global_verify_record()
|
||||||
|
* to detect the already dead global->server_id
|
||||||
|
* as state->db_rec is still locked and its
|
||||||
|
* value didn't change.
|
||||||
|
*/
|
||||||
|
SMB_ASSERT(last_server_id.pid == 0);
|
||||||
|
last_server_id = global->server_id;
|
||||||
|
|
||||||
if (procid_is_local(&global->server_id)) {
|
if (procid_is_local(&global->server_id)) {
|
||||||
subreq = messaging_filtered_read_send(state,
|
subreq = messaging_filtered_read_send(state,
|
||||||
state->ev,
|
state->ev,
|
||||||
@ -618,12 +651,28 @@ static void smb2srv_client_mc_negprot_next(struct tevent_req *req)
|
|||||||
if (procid_is_local(&global->server_id)) {
|
if (procid_is_local(&global->server_id)) {
|
||||||
status = smb2srv_client_connection_pass(state->smb2req,
|
status = smb2srv_client_connection_pass(state->smb2req,
|
||||||
global);
|
global);
|
||||||
|
if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
|
||||||
|
/*
|
||||||
|
* We remembered last_server_id = global->server_id
|
||||||
|
* above, so we'll treat it as dead in the
|
||||||
|
* next round to smbXsrv_client_global_verify_record().
|
||||||
|
*/
|
||||||
|
goto verify_again;
|
||||||
|
}
|
||||||
if (tevent_req_nterror(req, status)) {
|
if (tevent_req_nterror(req, status)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
status = smb2srv_client_connection_drop(state->smb2req,
|
status = smb2srv_client_connection_drop(state->smb2req,
|
||||||
global);
|
global);
|
||||||
|
if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
|
||||||
|
/*
|
||||||
|
* We remembered last_server_id = global->server_id
|
||||||
|
* above, so we'll treat it as dead in the
|
||||||
|
* next round to smbXsrv_client_global_verify_record().
|
||||||
|
*/
|
||||||
|
goto verify_again;
|
||||||
|
}
|
||||||
if (tevent_req_nterror(req, status)) {
|
if (tevent_req_nterror(req, status)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user