]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MINOR: quic_tp: fix preferred_address decoding
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Thu, 30 Nov 2023 13:01:51 +0000 (14:01 +0100)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Thu, 30 Nov 2023 14:49:10 +0000 (15:49 +0100)
quic_transport_param_dec_pref_addr() is responsible to decode
preferred_address from received transport parameter. There was two
issues with this function :
* address and port location as defined in RFC were inverted for both
  IPv4 and IPv6 during decoding
* an invalid check was done to ensure decoded CID length corresponds to
  remaining buffer size. It did not take into account the final field
  for stateless reset token.

These issues were never encountered as only server can emit
preferred_address transport parameter, so the impact of this bug is
invisible.

This should be backported up to 2.6.

src/quic_tp.c

index 5ae4f826b30d98da3935461a1159f877f1f401ab..eea8a31ddc649d31c380acd46d5b3c3109b70923 100644 (file)
@@ -130,27 +130,30 @@ static int quic_transport_param_dec_pref_addr(struct tp_preferred_address *addr,
        if (end - *buf < addr_len)
                return 0;
 
-       addr->ipv4_port = read_n16(*buf);
-       *buf += sizeof addr->ipv4_port;
-
        memcpy(addr->ipv4_addr, *buf, sizeof addr->ipv4_addr);
        *buf += sizeof addr->ipv4_addr;
 
-       addr->ipv6_port = read_n16(*buf);
-       *buf += sizeof addr->ipv6_port;
+       addr->ipv4_port = read_n16(*buf);
+       *buf += sizeof addr->ipv4_port;
 
        memcpy(addr->ipv6_addr, *buf, sizeof addr->ipv6_addr);
        *buf += sizeof addr->ipv6_addr;
 
+       addr->ipv6_port = read_n16(*buf);
+       *buf += sizeof addr->ipv6_port;
+
        addr->cid.len = *(*buf)++;
        if (addr->cid.len) {
-               if (end - *buf > addr->cid.len || addr->cid.len > sizeof addr->cid.data)
+               if (end - sizeof(addr->stateless_reset_token) - *buf > addr->cid.len ||
+                   addr->cid.len > sizeof(addr->cid.data)) {
                        return 0;
+               }
+
                memcpy(addr->cid.data, *buf, addr->cid.len);
                *buf += addr->cid.len;
        }
 
-       if (end - *buf != sizeof addr->stateless_reset_token)
+       if (end - *buf != sizeof(addr->stateless_reset_token))
                return 0;
 
        memcpy(addr->stateless_reset_token, *buf, end - *buf);