BUG/MINOR: mux-quic: fix crash on aborting uni remote stream

A remote unidirectional stream can be aborted prematurely if application
layers cannot identify its type. In this case, a STOP_SENDING frame is
emitted.

Since QUIC MUX refactoring, a crash would occur in this scenario due to
2 specific characteristics of remote uni streams :
* qcs.tx.fctl was not initialized completely. This cause a crash due to
  BUG_ON() statement inside qcs_destroy().
* qcs.stream is never allocated. This caused qcs_prep_bytes() to crash
  inside qcc_io_send().

This bug is considered minor as it happens only on very specific QUIC
clients. It was detected when using s2n-quic over interop.

This does not need to be backported.
This commit is contained in:
Amaury Denoyelle 2024-03-05 15:14:08 +01:00
parent d8f1ff8648
commit b0dd4810e7

View File

@ -127,7 +127,7 @@ static struct qcs *qcs_new(struct qcc *qcc, uint64_t id, enum qcs_type type)
qfctl_init(&qcs->tx.fc, qcc->rfctl.msd_uni_l); qfctl_init(&qcs->tx.fc, qcc->rfctl.msd_uni_l);
} }
else { else {
qcs->tx.fc.off_real = 0; qfctl_init(&qcs->tx.fc, 0);
} }
qcs->rx.ncbuf = NCBUF_NULL; qcs->rx.ncbuf = NCBUF_NULL;
@ -2115,7 +2115,7 @@ static int qcc_io_send(struct qcc *qcc)
/* Stream must not be present in send_list if it has nothing to send. */ /* Stream must not be present in send_list if it has nothing to send. */
BUG_ON(!(qcs->flags & (QC_SF_FIN_STREAM|QC_SF_TO_STOP_SENDING|QC_SF_TO_RESET)) && BUG_ON(!(qcs->flags & (QC_SF_FIN_STREAM|QC_SF_TO_STOP_SENDING|QC_SF_TO_RESET)) &&
!qcs_prep_bytes(qcs)); (!qcs->stream || !qcs_prep_bytes(qcs)));
/* Each STOP_SENDING/RESET_STREAM frame is sent individually to /* Each STOP_SENDING/RESET_STREAM frame is sent individually to
* guarantee its emission. * guarantee its emission.
@ -2130,7 +2130,7 @@ static int qcc_io_send(struct qcc *qcc)
* to send. * to send.
*/ */
if (!(qcs->flags & (QC_SF_FIN_STREAM|QC_SF_TO_RESET)) && if (!(qcs->flags & (QC_SF_FIN_STREAM|QC_SF_TO_RESET)) &&
!qcs_prep_bytes(qcs)) { (!qcs->stream || !qcs_prep_bytes(qcs))) {
LIST_DEL_INIT(&qcs->el_send); LIST_DEL_INIT(&qcs->el_send);
continue; continue;
} }