From: Stefan Metzmacher Date: Thu, 12 Feb 2026 12:21:06 +0000 (+0100) Subject: s3:smb2_server: failing lease/oplock breaks should call smbd_server_connection_termin... X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=734481e2aa9c9bb20fc9bc8734eba85d2f61be72;p=thirdparty%2Fsamba.git s3:smb2_server: failing lease/oplock breaks should call smbd_server_connection_terminate() If there's a problem sending a lease break we need to call smbd_server_connection_terminate(xconn). Currently we only called smbXsrv_connection_disconnect_transport(), which only closes the low level socket, but it doesn't cleanup smbXsrv_connection and in case of the last connection for the smbXsrv_client, so we leave the stale structures and the stale process behind. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15995 Signed-off-by: Stefan Metzmacher Reviewed-by: Ralph Boehme --- diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c index c5e910204a0..1aaebd92c82 100644 --- a/source3/smbd/smb2_server.c +++ b/source3/smbd/smb2_server.c @@ -4284,7 +4284,15 @@ static struct tevent_req *smbd_smb2_break_send(TALLOC_CTX *mem_ctx, xconn->smb2.send_queue_len++; status = smbd_smb2_flush_send_queue(xconn); - if (tevent_req_nterror(req, status)) { + if (!NT_STATUS_IS_OK(status)) { + if (tevent_req_is_in_progress(req)) { + /* + * most likely tevent_req_nterror() + * was already called on + * state->queue_entry.ack.req + */ + tevent_req_nterror(req, status); + } return tevent_req_post(req, ev); } @@ -4482,6 +4490,33 @@ static void smbXsrv_pending_break_done(struct tevent_req *subreq) status = smbd_smb2_break_recv(subreq); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { + struct smbXsrv_connection *xconn = NULL; + + /* + * smbXsrv_connection_disconnect_transport() + * was already called, but in order to + * avoid stale xconn structures and in + * case of only one xconn a stale process + * we need to call smbd_server_connection_terminate() + * + * So we search if the xconn related to the + * last_channel_id is still there and + * start the cleanup, which most likely + * happens in an async fashion + */ + for (xconn = client->connections; + xconn != NULL; + xconn = xconn->next) + { + if (xconn->channel_id != pb->last_channel_id) { + continue; + } + + smbd_server_connection_terminate(xconn, + nt_errstr(status)); + break; + } + status = smbXsrv_pending_break_submit(pb); if (NT_STATUS_EQUAL(status, NT_STATUS_ABANDONED)) { /*