MINOR: quic: Amplification limit handling sanitization.

Add a BUG_ON() to quic_peer_validated_addr() to check the amplification limit
is respected when it return false(0), i.e. when the connection is not validated.

Implement quic_may_send_bytes() which returns the number of bytes which may be
sent when the connection has not already been validated and call this functions
at several places when this is the case (after having called
quic_peer_validated_addr()).

Furthermore, this patch improves the code maintainability. Some patches to
come will have to rename ->[rt]x.bytes quic_conn struct members.
This commit is contained in:
Frédéric Lécaille 2023-08-04 15:10:56 +02:00
parent 1f40b6c9fe
commit a45f90dd4e
3 changed files with 18 additions and 5 deletions

View File

@ -467,6 +467,16 @@ static inline size_t quic_path_prep_data(struct quic_path *path)
return path->cwnd - path->prep_in_flight;
}
/* Return the number of bytes which may be sent from <qc> connection when
* it has not already been validated. Note that this is the responsability
* of the caller to check that the case with quic_peer_validated_addr().
* This latter BUG_ON() if 3 * qc->rx.bytes < qc->tx.prep_bytes.
*/
static inline size_t quic_may_send_bytes(struct quic_conn *qc)
{
return 3 * qc->rx.bytes - qc->tx.prep_bytes;
}
/* CRYPTO data buffer handling functions. */
static inline unsigned char *c_buf_getpos(struct quic_enc_level *qel, uint64_t offset)
{

View File

@ -149,6 +149,8 @@ int quic_peer_validated_addr(struct quic_conn *qc)
qc->state >= QUIC_HS_ST_COMPLETE)
return 1;
BUG_ON(qc->tx.prep_bytes > 3 * qc->rx.bytes);
return 0;
}

View File

@ -233,7 +233,7 @@ static void qc_prep_fast_retrans(struct quic_conn *qc,
* packet size is the packet number. And the maximum increase is 4 bytes.
*/
if (!quic_peer_validated_addr(qc) && qc_is_listener(qc) &&
pkt->len + 4 > 3 * qc->rx.bytes - qc->tx.prep_bytes) {
pkt->len + 4 > quic_may_send_bytes(qc)) {
qc->flags |= QUIC_FL_CONN_ANTI_AMPLIFICATION_REACHED;
TRACE_PROTO("anti-amplification limit would be reached", QUIC_EV_CONN_SPPKTS, qc, pkt);
goto leave;
@ -298,8 +298,9 @@ void qc_prep_hdshk_fast_retrans(struct quic_conn *qc,
*/
if (!quic_peer_validated_addr(qc) && qc_is_listener(qc)) {
size_t dglen = pkt->len + 4;
size_t may_send = 3 * qc->rx.bytes - qc->tx.prep_bytes;
size_t may_send;
may_send = quic_may_send_bytes(qc);
dglen += pkt->next ? pkt->next->len + 4 : 0;
if (dglen > may_send) {
qc->flags |= QUIC_FL_CONN_ANTI_AMPLIFICATION_REACHED;
@ -468,7 +469,7 @@ static int qc_prep_app_pkts(struct quic_conn *qc, struct buffer *buf,
/* Leave room for the datagram header */
pos += dg_headlen;
if (!quic_peer_validated_addr(qc) && qc_is_listener(qc)) {
end = pos + QUIC_MIN((uint64_t)qc->path->mtu, 3 * qc->rx.bytes - qc->tx.prep_bytes);
end = pos + QUIC_MIN((uint64_t)qc->path->mtu, quic_may_send_bytes(qc));
}
else {
end = pos + qc->path->mtu;
@ -1043,7 +1044,7 @@ int qc_prep_hpkts(struct quic_conn *qc, struct buffer *buf, struct list *qels)
/* Leave room for the datagram header */
pos += dg_headlen;
if (!quic_peer_validated_addr(qc) && qc_is_listener(qc)) {
end = pos + QUIC_MIN((uint64_t)qc->path->mtu, 3 * qc->rx.bytes - qc->tx.prep_bytes);
end = pos + QUIC_MIN((uint64_t)qc->path->mtu, quic_may_send_bytes(qc));
}
else {
end = pos + qc->path->mtu;
@ -1357,7 +1358,7 @@ int qc_need_sending(struct quic_conn *qc, struct quic_enc_level *qel)
int qc_may_probe_ipktns(struct quic_conn *qc)
{
return quic_peer_validated_addr(qc) ||
(int)(3 * qc->rx.bytes - qc->tx.prep_bytes) >= QUIC_INITIAL_PACKET_MINLEN;
quic_may_send_bytes(qc) >= QUIC_INITIAL_PACKET_MINLEN;
}
/*