Skip to content

Commit 175aaf7

Browse files
committed
BUG/MINOR: quic: fix buffer overflow with sockaddr_in46
New type sockaddr_in46 has been recently introduced. It serves as a union which can store either an IPv4 or IPv6 address. The objective is to reduce the storage size for QUIC datagrams which previously uses a sockaddr_storage field. On qc_new_conn(), source and destination addresses from the datagram are passed to the function as sockaddr_storage so that they are copied into the newly built quic_conn instance. However, the involved memcpy() is producing a buffer overflow as sockaddr_in46 is smaller than sockaddr_storage type. This patch fixes this by defining a new helper function in46union_to_addr(). This allows to convert safely sockaddr_in46 to a plain sockaddr type. The function is now used before invoking qc_new_conn(). No need to backport.
1 parent 9b72252 commit 175aaf7

2 files changed

Lines changed: 35 additions & 2 deletions

File tree

include/haproxy/quic_sock.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,36 @@ static inline int quic_increment_curr_handshake(struct listener *l)
109109
return next;
110110
}
111111

112+
/* Initializes <dst> sockaddr_storage from <src> union sockaddr_in46 type.
113+
* Only IP version 4 and 6 addresses are supported.
114+
*/
115+
static inline void in46union_to_addr(const union sockaddr_in46 *src,
116+
struct sockaddr_storage *dst)
117+
{
118+
struct sockaddr_in *in;
119+
struct sockaddr_in6 *in6;
120+
121+
switch (((struct sockaddr_storage *)src)->ss_family) {
122+
case AF_INET:
123+
in = (struct sockaddr_in *)dst;
124+
in->sin_family = AF_INET;
125+
in->sin_addr = src->in4.sin_addr;
126+
in->sin_port = src->in4.sin_port;
127+
break;
128+
129+
case AF_INET6:
130+
in6 = (struct sockaddr_in6 *)dst;
131+
in6->sin6_family = AF_INET6;
132+
in6->sin6_addr = src->in6.sin6_addr;
133+
in6->sin6_port = src->in6.sin6_port;
134+
break;
135+
136+
default:
137+
ABORT_NOW();
138+
break;
139+
}
140+
}
141+
112142
#endif /* USE_QUIC */
113143
#endif /* _HAPROXY_QUIC_SOCK_H */
114144

src/quic_rx.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1868,9 +1868,12 @@ static struct quic_conn *quic_rx_pkt_retrieve_conn(struct quic_rx_packet *pkt,
18681868
pool_free(pool_head_quic_connection_id, conn_id);
18691869
}
18701870
else {
1871+
struct sockaddr_storage saddr, daddr;
1872+
in46union_to_addr(&pkt->saddr, &saddr);
1873+
in46union_to_addr(&dgram->daddr, &daddr);
1874+
18711875
qc = qc_new_conn(l, pkt, &token_odcid, NULL, conn_id,
1872-
(struct sockaddr_storage *)&dgram->daddr,
1873-
(struct sockaddr_storage *)&pkt->saddr);
1876+
&daddr, &saddr);
18741877
if (qc == NULL) {
18751878
quic_cid_delete(conn_id); /* Removes CID from global tree as it points to a NULL qc. */
18761879
pool_free(pool_head_quic_connection_id, conn_id);

0 commit comments

Comments
 (0)