From: Amaury Denoyelle Date: Tue, 18 Oct 2022 09:05:02 +0000 (+0200) Subject: BUG/MINOR: quic: fix buffer overflow on retry token generation X-Git-Tag: v2.7-dev9~163 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=6c940569f607a2311861358fc607a4a08ce028c3;p=thirdparty%2Fhaproxy.git BUG/MINOR: quic: fix buffer overflow on retry token generation When generating a Retry token, client CID is used as encryption input. The client must reuse the same CID when emitting the token in a new Initial packet. A memory overflow can occur on quic_generate_retry_token() depending on the size of client CID. This is because space reserved for only accounted for QUIC_HAP_CID_LEN (size of haproxy owned generated CID). However, the client CID size only depends on client parameter and is instead limited to QUIC_CID_MAXLEN as specified in RFC9000. This was reproduced with ngtcp2 and haproxy built with ASAN. Here is the error log : ==14964==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7fffee228cee at pc 0x7ffff785f427 bp 0x7fffee2289e0 sp 0x7fffee228188 WRITE of size 17 at 0x7fffee228cee thread T5 #0 0x7ffff785f426 in __interceptor_memcpy /usr/src/debug/gcc/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:827 #1 0x555555906ea7 in quic_generate_retry_token_aad src/quic_conn.c:5452 #2 0x555555907e72 in quic_retry_token_check src/quic_conn.c:5577 #3 0x55555590d01e in qc_lstnr_pkt_rcv src/quic_conn.c:6103 #4 0x5555559190fa in quic_lstnr_dghdlr src/quic_conn.c:7179 #5 0x555555eb0abf in run_tasks_from_lists src/task.c:590 #6 0x555555eb285f in process_runnable_tasks src/task.c:855 #7 0x555555d9118f in run_poll_loop src/haproxy.c:2853 #8 0x555555d91f88 in run_thread_poll_loop src/haproxy.c:3042 #9 0x7ffff709f8fc (/usr/lib/libc.so.6+0x868fc) #10 0x7ffff7121a5f (/usr/lib/libc.so.6+0x108a5f) This must be backported up to 2.6. --- diff --git a/src/quic_conn.c b/src/quic_conn.c index 88993dc16e..44c944c014 100644 --- a/src/quic_conn.c +++ b/src/quic_conn.c @@ -5471,7 +5471,7 @@ static int quic_generate_retry_token(unsigned char *buf, size_t len, int ret = 0; unsigned char *p; unsigned char aad[sizeof(uint32_t) + sizeof(in_port_t) + - sizeof(struct in6_addr) + QUIC_HAP_CID_LEN]; + sizeof(struct in6_addr) + QUIC_CID_MAXLEN]; size_t aadlen; unsigned char salt[QUIC_RETRY_TOKEN_SALTLEN]; unsigned char key[QUIC_TLS_KEY_LEN]; @@ -5557,7 +5557,7 @@ static int quic_retry_token_check(unsigned char *token, size_t tokenlen, int ret = 0; unsigned char buf[128]; unsigned char aad[sizeof(uint32_t) + sizeof(in_port_t) + - sizeof(struct in6_addr) + QUIC_HAP_CID_LEN]; + sizeof(struct in6_addr) + QUIC_CID_MAXLEN]; size_t aadlen; const unsigned char *salt; unsigned char key[QUIC_TLS_KEY_LEN];