]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MINOR: quic: upgrade rdlock to wrlock for ODCID removal
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Wed, 22 Dec 2021 10:29:05 +0000 (11:29 +0100)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Thu, 23 Dec 2021 14:51:00 +0000 (15:51 +0100)
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

index 624cb35510ed6677660c30ba241b72a460a01873..500814fd1f76067ebccd2a36580a61af4b4ee59f 100644 (file)
@@ -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,14 +3894,21 @@ 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;
+       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.
         */
-       ebmb_delete(&qc->odcid_node);
-
- end:
-       HA_RWLOCK_RDUNLOCK(QUIC_LOCK, &l->rx.cids_lock);
+       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;
 }