From cde2c0b27a35c3083d2e9ef7c26c5e57b92a5e8f Mon Sep 17 00:00:00 2001 From: Dorin Hogea Date: Tue, 11 Aug 2026 16:57:51 -0400 Subject: [PATCH] Fix fdb push crash from stale identity blob and dtran teardown races Signed-off-by: Dorin Hogea --- db/fdb_fend.c | 40 +++++++++++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/db/fdb_fend.c b/db/fdb_fend.c index f4db7983a0..5b4d9aa3fa 100644 --- a/db/fdb_fend.c +++ b/db/fdb_fend.c @@ -4135,10 +4135,14 @@ static void _free_fdb_tran(fdb_distributed_tran_t *dtran, fdb_tran_t *tran) */ void fdb_free_tran(sqlclntstate *clnt, fdb_tran_t *tran) { - fdb_distributed_tran_t *dtran = clnt->dbtran.dtran; + fdb_distributed_tran_t *dtran; uuidstr_t us; + Pthread_mutex_lock(&clnt->dtran_mtx); + + dtran = clnt->dbtran.dtran; if (!dtran) { + Pthread_mutex_unlock(&clnt->dtran_mtx); logmsg(LOGMSG_ERROR, "%s no dtran\n", __func__); return; } @@ -4156,6 +4160,8 @@ void fdb_free_tran(sqlclntstate *clnt, fdb_tran_t *tran) free(dtran); clnt->dbtran.dtran = 0; } + + Pthread_mutex_unlock(&clnt->dtran_mtx); } extern char gbl_dbname[]; @@ -4168,12 +4174,18 @@ void fdb_client_set_identityBlob(sqlclntstate *clnt, cdb2_hndl_tp *hndl) cdb2_setIdentityBlob(hndl, externalComdb2getAuthIdBlob(clnt->authdata)); } else if (clnt->use_db_identity) { cdb2_setDbIdentityBlob(hndl); + } else { + /* No fresh identity for this call (eg. teardown/rollback after the + * triggering query's protobuf buffer was already freed). Clear any + * blob left over from an earlier statement on this handle instead of + * leaving a dangling pointer into freed memory. */ + cdb2_setIdentityBlob(hndl, NULL); } } int fdb_trans_commit(sqlclntstate *clnt, enum trans_clntcomm sideeffects, int *is_distributed) { - fdb_distributed_tran_t *dtran = clnt->dbtran.dtran; + fdb_distributed_tran_t *dtran; fdb_tran_t *tran, *tmp; fdb_msg_t *msg; int rc = 0; @@ -4181,8 +4193,13 @@ int fdb_trans_commit(sqlclntstate *clnt, enum trans_clntcomm sideeffects, int *i *is_distributed = 0; - if (!dtran) + Pthread_mutex_lock(&clnt->dtran_mtx); + + dtran = clnt->dbtran.dtran; + if (!dtran) { + Pthread_mutex_unlock(&clnt->dtran_mtx); return 0; + } /* nop, this is the remote part that reuses the same dbtran data structure */ @@ -4190,17 +4207,17 @@ int fdb_trans_commit(sqlclntstate *clnt, enum trans_clntcomm sideeffects, int *i /* this is on remote side, the structure is different, see * fdb_bend_sql.c */ fdb_svc_trans_destroy(clnt); + Pthread_mutex_unlock(&clnt->dtran_mtx); return 0; } msg = (fdb_msg_t *)calloc(1, fdb_msg_size()); if (!msg) { + Pthread_mutex_unlock(&clnt->dtran_mtx); logmsg(LOGMSG_ERROR, "%s malloc\n", __func__); return FDB_ERR_MALLOC; } - Pthread_mutex_lock(&clnt->dtran_mtx); - if (clnt->use_2pc && listc_size(&dtran->fdb_trans) > 0) { clnt->is_coordinator = 1; } @@ -4337,13 +4354,18 @@ int fdb_trans_commit(sqlclntstate *clnt, enum trans_clntcomm sideeffects, int *i int fdb_trans_rollback(sqlclntstate *clnt) { - fdb_distributed_tran_t *dtran = clnt->dbtran.dtran; + fdb_distributed_tran_t *dtran; fdb_tran_t *tran, *tmp; fdb_msg_t *msg; int rc = 0; - if (!dtran) + Pthread_mutex_lock(&clnt->dtran_mtx); + + dtran = clnt->dbtran.dtran; + if (!dtran) { + Pthread_mutex_unlock(&clnt->dtran_mtx); return 0; + } /* nop, this is the remote part that reuses the same dbtran data structure */ @@ -4351,17 +4373,17 @@ int fdb_trans_rollback(sqlclntstate *clnt) /* this is on remote side, the structure is different, see * fdb_bend_sql.c */ fdb_svc_trans_destroy(clnt); + Pthread_mutex_unlock(&clnt->dtran_mtx); return 0; } msg = (fdb_msg_t *)calloc(1, fdb_msg_size()); if (!msg) { + Pthread_mutex_unlock(&clnt->dtran_mtx); logmsg(LOGMSG_ERROR, "%s malloc\n", __func__); return FDB_ERR_MALLOC; } - Pthread_mutex_lock(&clnt->dtran_mtx); - LISTC_FOR_EACH(&dtran->fdb_trans, tran, lnk) { if (tran->is_cdb2api) {