mirror of
https://github.com/haproxy/haproxy.git
synced 2026-06-08 16:23:24 -04:00
BUG/MEDIUM: xprt_qmux: implement ->get_ssl_sock_ctx() to get the SSL laye
conn_get_ssl_sock_ctx() retrieves the ssl_sock_ctx of a connection by calling conn->xprt->get_ssl_sock_ctx(). Only ssl_sock implements this method, and it returns conn->xprt_ctx. This works because for every existing XPRT combination the SSL layer is the topmost one: even xprt_handshake (SOCKS4, PROXY, NetScaler CIP) is installed *below* ssl_sock, so conn->xprt keeps pointing to ssl_sock. Qmux changes this assumption: xprt_qmux is stacked *on top of* ssl_sock and keeps the SSL layer as its lower layer to exchange the QUIC transport parameters over the established TLS stream. During the qmux handshake, conn->xprt therefore points to xprt_qmux, which does not implement get_ssl_sock_ctx(), making conn_get_ssl_sock_ctx() return NULL for the whole connection, affecting every caller that inspects the SSL layer (sample fetches, logging, ssl_sock_infocbk(), ...). The visible consequence was a crash: when the peer sends a TLS alert during the qmux handshake, the SSL library calls ssl_sock_infocbk(), which recovers a valid connection but a NULL ctx, rightfully triggering the "BUG_ON(!ctx)" early in the function. This patch implements xprt_qmux_get_ssl_sock_ctx() so that it returns the ssl_sock_ctx of the lower layer when it is the SSL layer, just like ssl_sock_get_ctx() does. conn_get_ssl_sock_ctx() then works again for all callers while the qmux handshake is in progress. After the handshake, conn->xprt is restored to the SSL layer so nothing else changes. This should be backported to 3.4.
This commit is contained in:
parent
45a64123d6
commit
e51ae5ce66
1 changed files with 17 additions and 0 deletions
|
|
@ -350,6 +350,22 @@ static void xprt_qmux_close(struct connection *conn, void *xprt_ctx)
|
|||
pool_free(xprt_qmux_ctx_pool, ctx);
|
||||
}
|
||||
|
||||
/* Retrieve the ssl_sock_ctx of the lower layer. Contrary to most XPRTs, QMux
|
||||
* is stacked on top of the SSL layer (and not the other way around), so during
|
||||
* the QMux handshake conn->xprt points to xprt_qmux. Without this delegation,
|
||||
* conn_get_ssl_sock_ctx() would return NULL for any code inspecting the SSL
|
||||
* layer of the connection (sample fetches, logging, info callback, ...) while
|
||||
* the QMux handshake is in progress.
|
||||
*/
|
||||
static struct ssl_sock_ctx *xprt_qmux_get_ssl_sock_ctx(struct connection *conn)
|
||||
{
|
||||
struct xprt_qmux_ctx *ctx = conn->xprt_ctx;
|
||||
|
||||
if (ctx && ctx->ops_lower == xprt_get(XPRT_SSL))
|
||||
return ctx->ctx_lower;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int xprt_qmux_get_alpn(const struct connection *conn, void *xprt_ctx,
|
||||
const char **str, int *len)
|
||||
{
|
||||
|
|
@ -371,6 +387,7 @@ struct xprt_ops xprt_qmux = {
|
|||
.start = xprt_qmux_start,
|
||||
.close = xprt_qmux_close,
|
||||
.get_alpn = xprt_qmux_get_alpn,
|
||||
.get_ssl_sock_ctx = xprt_qmux_get_ssl_sock_ctx,
|
||||
.name = "qmux",
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue