BUG/MINOR: quic: fix race condition in qc_check_dcid()
qc_check_dcid() is a function which check that a DCID is associated to
the expected quic_conn instance. This is used for quic_conn socket
receive handler as there is a tiny risk that a datagram to another
connection was received on this socket.
As other operations on global CID tree, a lock must be used to protect
against race condition. However, as previous commit, lock was not held
long enough as CID tree node is accessed outside of the lock region. To
fix this, increase critical section until CID dereferencement is done.
The impact of this bug should be similar to the previous one. However,
risk of crash are even less reduced as it should be extremely rare to
receive datagram for other connections on a quic_conn socket. As such,
most of the time first check condition of qc_check_dcid() is enough.
This may fix first crash of issue github #2607.
This must be backported up to 2.8.
(cherry picked from commit 05f59a51ac5ba193ef37447ac88f74d3019c3399)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 177bcf3b4c5b387157a78836379ae877ec96ffe9)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit dd1eaf5a1f037b160dfd3b3ad0acf19bbbb23e95)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
diff --git a/src/quic_conn.c b/src/quic_conn.c
index dbeeb74..5c748a4 100644
--- a/src/quic_conn.c
+++ b/src/quic_conn.c
@@ -8639,13 +8639,12 @@
*/
HA_RWLOCK_RDLOCK(QC_CID_LOCK, &tree->lock);
node = ebmb_lookup(&tree->root, dcid, dcid_len);
- HA_RWLOCK_RDUNLOCK(QC_CID_LOCK, &tree->lock);
-
if (node) {
conn_id = ebmb_entry(node, struct quic_connection_id, node);
if (qc == conn_id->qc)
return 1;
}
+ HA_RWLOCK_RDUNLOCK(QC_CID_LOCK, &tree->lock);
return 0;
}