mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-08-08 08:07:10 +02:00
BUG/MEDIUM: quic: fix sslconns on quic_conn alloc failure
QUIC connections are accounted inside global sslconns. As with QUIC actconn, it suffered from a similar issue if an intermediary allocation failed inside qc_new_conn(). Fix this similarly by moving increment operation inside qc_new_conn(). Increment and error path are now centralized and much easier to validate. The consequences are similar to the actconn fix : on memory allocation global sslconns may wrap, this time blocking any future QUIC or SSL connections on the process. This must be backported up to 2.6.
This commit is contained in:
parent
a7ba679fe7
commit
6f9b65f952
@ -43,8 +43,6 @@ static inline void qc_free_ssl_sock_ctx(struct ssl_sock_ctx **ctx)
|
|||||||
SSL_free((*ctx)->ssl);
|
SSL_free((*ctx)->ssl);
|
||||||
pool_free(pool_head_quic_ssl_sock_ctx, *ctx);
|
pool_free(pool_head_quic_ssl_sock_ctx, *ctx);
|
||||||
*ctx = NULL;
|
*ctx = NULL;
|
||||||
|
|
||||||
_HA_ATOMIC_DEC(&global.sslconns);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* _HAPROXY_QUIC_SSL_H */
|
#endif /* _HAPROXY_QUIC_SSL_H */
|
||||||
|
@ -1162,7 +1162,7 @@ struct quic_conn *qc_new_conn(const struct quic_version *qv, int ipv4,
|
|||||||
struct quic_conn *qc = NULL;
|
struct quic_conn *qc = NULL;
|
||||||
struct listener *l = NULL;
|
struct listener *l = NULL;
|
||||||
struct quic_cc_algo *cc_algo = NULL;
|
struct quic_cc_algo *cc_algo = NULL;
|
||||||
unsigned int next_actconn = 0;
|
unsigned int next_actconn = 0, next_sslconn = 0;
|
||||||
|
|
||||||
TRACE_ENTER(QUIC_EV_CONN_INIT);
|
TRACE_ENTER(QUIC_EV_CONN_INIT);
|
||||||
|
|
||||||
@ -1173,6 +1173,12 @@ struct quic_conn *qc_new_conn(const struct quic_version *qv, int ipv4,
|
|||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
next_sslconn = increment_sslconn();
|
||||||
|
if (!next_sslconn) {
|
||||||
|
TRACE_STATE("sslconn reached", QUIC_EV_CONN_INIT);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
qc = pool_alloc(pool_head_quic_conn);
|
qc = pool_alloc(pool_head_quic_conn);
|
||||||
if (!qc) {
|
if (!qc) {
|
||||||
TRACE_ERROR("Could not allocate a new connection", QUIC_EV_CONN_INIT);
|
TRACE_ERROR("Could not allocate a new connection", QUIC_EV_CONN_INIT);
|
||||||
@ -1182,7 +1188,7 @@ struct quic_conn *qc_new_conn(const struct quic_version *qv, int ipv4,
|
|||||||
/* Now that quic_conn instance is allocated, quic_conn_release() will
|
/* Now that quic_conn instance is allocated, quic_conn_release() will
|
||||||
* ensure global accounting is decremented.
|
* ensure global accounting is decremented.
|
||||||
*/
|
*/
|
||||||
next_actconn = 0;
|
next_sslconn = next_actconn = 0;
|
||||||
|
|
||||||
/* Initialize in priority qc members required for a safe dealloc. */
|
/* Initialize in priority qc members required for a safe dealloc. */
|
||||||
qc->nictx = NULL;
|
qc->nictx = NULL;
|
||||||
@ -1382,6 +1388,8 @@ struct quic_conn *qc_new_conn(const struct quic_version *qv, int ipv4,
|
|||||||
*/
|
*/
|
||||||
if (next_actconn)
|
if (next_actconn)
|
||||||
_HA_ATOMIC_DEC(&actconn);
|
_HA_ATOMIC_DEC(&actconn);
|
||||||
|
if (next_sslconn)
|
||||||
|
_HA_ATOMIC_DEC(&global.sslconns);
|
||||||
|
|
||||||
TRACE_LEAVE(QUIC_EV_CONN_INIT);
|
TRACE_LEAVE(QUIC_EV_CONN_INIT);
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -1519,6 +1527,7 @@ void quic_conn_release(struct quic_conn *qc)
|
|||||||
* time with limited ressources.
|
* time with limited ressources.
|
||||||
*/
|
*/
|
||||||
_HA_ATOMIC_DEC(&actconn);
|
_HA_ATOMIC_DEC(&actconn);
|
||||||
|
_HA_ATOMIC_DEC(&global.sslconns);
|
||||||
|
|
||||||
TRACE_PROTO("QUIC conn. freed", QUIC_EV_CONN_FREED, qc);
|
TRACE_PROTO("QUIC conn. freed", QUIC_EV_CONN_FREED, qc);
|
||||||
leave:
|
leave:
|
||||||
|
@ -1902,7 +1902,6 @@ static struct quic_conn *quic_rx_pkt_retrieve_conn(struct quic_rx_packet *pkt,
|
|||||||
struct quic_conn *qc = NULL;
|
struct quic_conn *qc = NULL;
|
||||||
struct proxy *prx;
|
struct proxy *prx;
|
||||||
struct quic_counters *prx_counters;
|
struct quic_counters *prx_counters;
|
||||||
unsigned int next_sslconn = 0;
|
|
||||||
|
|
||||||
TRACE_ENTER(QUIC_EV_CONN_LPKT);
|
TRACE_ENTER(QUIC_EV_CONN_LPKT);
|
||||||
|
|
||||||
@ -1960,13 +1959,6 @@ static struct quic_conn *quic_rx_pkt_retrieve_conn(struct quic_rx_packet *pkt,
|
|||||||
pkt->saddr = dgram->saddr;
|
pkt->saddr = dgram->saddr;
|
||||||
ipv4 = dgram->saddr.ss_family == AF_INET;
|
ipv4 = dgram->saddr.ss_family == AF_INET;
|
||||||
|
|
||||||
next_sslconn = increment_sslconn();
|
|
||||||
if (!next_sslconn) {
|
|
||||||
TRACE_STATE("drop packet on sslconn reached",
|
|
||||||
QUIC_EV_CONN_LPKT, NULL, NULL, NULL, pkt->version);
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Generate the first connection CID. This is derived from the client
|
/* Generate the first connection CID. This is derived from the client
|
||||||
* ODCID and address. This allows to retrieve the connection from the
|
* ODCID and address. This allows to retrieve the connection from the
|
||||||
* ODCID without storing it in the CID tree. This is an interesting
|
* ODCID without storing it in the CID tree. This is an interesting
|
||||||
@ -1985,7 +1977,6 @@ static struct quic_conn *quic_rx_pkt_retrieve_conn(struct quic_rx_packet *pkt,
|
|||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
next_sslconn = 0;
|
|
||||||
/* Compute and store into the quic_conn the hash used to compute extra CIDs */
|
/* Compute and store into the quic_conn the hash used to compute extra CIDs */
|
||||||
if (quic_hash64_from_cid)
|
if (quic_hash64_from_cid)
|
||||||
qc->hash64 = quic_hash64_from_cid(conn_id->cid.data, conn_id->cid.len,
|
qc->hash64 = quic_hash64_from_cid(conn_id->cid.data, conn_id->cid.len,
|
||||||
@ -2036,9 +2027,6 @@ static struct quic_conn *quic_rx_pkt_retrieve_conn(struct quic_rx_packet *pkt,
|
|||||||
else
|
else
|
||||||
HA_ATOMIC_INC(&prx_counters->dropped_pkt);
|
HA_ATOMIC_INC(&prx_counters->dropped_pkt);
|
||||||
|
|
||||||
if (next_sslconn)
|
|
||||||
_HA_ATOMIC_DEC(&global.sslconns);
|
|
||||||
|
|
||||||
TRACE_LEAVE(QUIC_EV_CONN_LPKT);
|
TRACE_LEAVE(QUIC_EV_CONN_LPKT);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user