From 250ac42754547ac86b9e947cc772e92aa5f3e22e Mon Sep 17 00:00:00 2001 From: Amaury Denoyelle Date: Wed, 22 Dec 2021 11:29:05 +0100 Subject: [PATCH] BUG/MINOR: quic: upgrade rdlock to wrlock for ODCID removal When a quic_conn is found in the DCID tree, it can be removed from the first ODCID tree. However, this operation must absolutely be run under a write-lock to avoid race condition. To avoid to use the lock too frequently, node.leaf_p is checked. This value is set to NULL after ebmb_delete. --- src/xprt_quic.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/xprt_quic.c b/src/xprt_quic.c index 624cb35510..500814fd1f 100644 --- a/src/xprt_quic.c +++ b/src/xprt_quic.c @@ -3863,6 +3863,8 @@ static struct quic_conn *retrieve_qc_conn_from_cid(struct quic_rx_packet *pkt, struct quic_conn *qc = NULL; struct ebmb_node *node; struct quic_connection_id *id; + /* set if the quic_conn is found in the second DCID tree */ + int found_in_dcid = 0; HA_RWLOCK_RDLOCK(QUIC_LOCK, &l->rx.cids_lock); @@ -3892,15 +3894,22 @@ static struct quic_conn *retrieve_qc_conn_from_cid(struct quic_rx_packet *pkt, id = ebmb_entry(node, struct quic_connection_id, node); qc = id->qc; - - /* If found in DCIDs tree, remove the quic_conn from the ODCIDs tree. - * If already done, this is a noop. - */ - ebmb_delete(&qc->odcid_node); + found_in_dcid = 1; end: HA_RWLOCK_RDUNLOCK(QUIC_LOCK, &l->rx.cids_lock); + /* If found in DCIDs tree, remove the quic_conn from the ODCIDs tree. + * If already done, this is a noop. + * + * node.leaf_p is first checked to avoid unnecessary locking. + */ + if (found_in_dcid && qc->odcid_node.node.leaf_p) { + HA_RWLOCK_WRLOCK(QUIC_LOCK, &l->rx.cids_lock); + ebmb_delete(&qc->odcid_node); + HA_RWLOCK_WRUNLOCK(QUIC_LOCK, &l->rx.cids_lock); + } + return qc; }