Skip to content

Commit

Permalink
BUG/MEDIUM: quic: fix transient send error with listener socket
Browse files Browse the repository at this point in the history
Transient send errors is handled differentely if using connection or
listener socket for QUIC transfers. In the first case, proper poller
subscription is used via fd_cant_send()/fd_want_send(). For the listener
socket case, error is ignored by qc_snd_buf() caller and retransmission
mechanism will allow to reemit the data.

For listener socket, transient error code handling is buggy. It blindly
uses fd_cand_send() with <qc.fd> member which is set to -1 for listener
socket usage. This results in an invalid fdtab access, with a possible
crash or a modification of a totally unrelated FD.

This bug is simply fixed by using qc_test_fd() before using
fd_cant_send()/fd_want_send(). This ensures <qc.fd> is used only if
initialized which is only the case when using connection socket.

No crash was reported yet for this bug. However, it is reproducible by
using ASAN compilation and the following strace sendmsg() errno command
injection :

 # strace -qq -yy -p $(pgrep haproxy) -f -e trace=%network \
     -e inject=sendto,sendmsg:error=EAGAIN:when=20+20

This must be backported up to 2.7.
  • Loading branch information
a-denoyelle committed Feb 19, 2024
1 parent 56e73df commit 5b31989
Showing 1 changed file with 5 additions and 3 deletions.
8 changes: 5 additions & 3 deletions src/quic_sock.c
Original file line number Diff line number Diff line change
Expand Up @@ -686,14 +686,16 @@ int qc_snd_buf(struct quic_conn *qc, const struct buffer *buf, size_t sz,
if (ret < 0) {
if (errno == EAGAIN || errno == EWOULDBLOCK ||
errno == ENOTCONN || errno == EINPROGRESS) {
/* transient error */
if (errno == EAGAIN || errno == EWOULDBLOCK)
qc->cntrs.socket_full++;
else
qc->cntrs.sendto_err++;

/* transient error */
fd_want_send(qc->fd);
fd_cant_send(qc->fd);
if (qc_test_fd(qc)) {
fd_want_send(qc->fd);
fd_cant_send(qc->fd);
}
TRACE_PRINTF(TRACE_LEVEL_USER, QUIC_EV_CONN_SPPKTS, qc, 0, 0, 0,
"UDP send failure errno=%d (%s)", errno, strerror(errno));
return 0;
Expand Down

0 comments on commit 5b31989

Please sign in to comment.