mirror of
https://github.com/samba-team/samba.git
synced 2024-12-22 13:34:15 +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 *was_free,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
const struct server_id *dead_server_id,
|
||||
struct smbXsrv_client_global0 **_g,
|
||||
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;
|
||||
enum ndr_err_code ndr_err;
|
||||
struct smbXsrv_client_global0 *global = NULL;
|
||||
bool dead = false;
|
||||
bool exists;
|
||||
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;
|
||||
|
||||
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);
|
||||
if (!exists) {
|
||||
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;
|
||||
NTSTATUS status;
|
||||
uint32_t seqnum = 0;
|
||||
struct server_id last_server_id = { .pid = 0, };
|
||||
|
||||
TALLOC_FREE(state->filter_subreq);
|
||||
SMB_ASSERT(state->db_rec == NULL);
|
||||
@ -545,10 +564,14 @@ static void smb2srv_client_mc_negprot_next(struct tevent_req *req)
|
||||
return;
|
||||
}
|
||||
|
||||
verify_again:
|
||||
TALLOC_FREE(global);
|
||||
|
||||
smbXsrv_client_global_verify_record(state->db_rec,
|
||||
&is_free,
|
||||
NULL,
|
||||
state,
|
||||
&last_server_id,
|
||||
&global,
|
||||
&seqnum);
|
||||
if (is_free) {
|
||||
@ -602,6 +625,16 @@ static void smb2srv_client_mc_negprot_next(struct tevent_req *req)
|
||||
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)) {
|
||||
subreq = messaging_filtered_read_send(state,
|
||||
state->ev,
|
||||
@ -618,12 +651,28 @@ static void smb2srv_client_mc_negprot_next(struct tevent_req *req)
|
||||
if (procid_is_local(&global->server_id)) {
|
||||
status = smb2srv_client_connection_pass(state->smb2req,
|
||||
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)) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
status = smb2srv_client_connection_drop(state->smb2req,
|
||||
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)) {
|
||||
return;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user