From: W.C.A. Wijngaards Date: Wed, 3 Jun 2026 12:37:37 +0000 (+0200) Subject: - Fix PROXYv2 header read and consume, it checks the header X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=8bc074043a836778b37202f6d8413ebb3eac28f6;p=thirdparty%2Funbound.git - Fix PROXYv2 header read and consume, it checks the header size. Thanks to Qifan Zhang, Palo Alto Networks for the report. --- diff --git a/doc/Changelog b/doc/Changelog index bd1812165..2dce57cac 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -17,6 +17,9 @@ - Fix ipset module to use larger domain name buffers, and check buffer lengths. Thanks to Qifan Zhang, Palo Alto Networks for the report. + - Fix PROXYv2 header read and consume, it checks the header + size. Thanks to Qifan Zhang, Palo Alto Networks for + the report. 3 June 2026: Yorgos - Fix const as reported by newest compiler warnings. diff --git a/util/netevent.c b/util/netevent.c index 8e4228edc..3c395ad18 100644 --- a/util/netevent.c +++ b/util/netevent.c @@ -951,6 +951,10 @@ static int consume_pp2_header(struct sldns_buffer* buf, struct comm_reply* rep, { struct sockaddr_in* addr = (struct sockaddr_in*)&rep->client_addr; + if(ntohs(header->len) < PP2_HEADER_LEN_INET) { + verbose(VERB_OPS, "proxy_protocol: header too short for IPv4 address"); + return 0; + } addr->sin_family = AF_INET; addr->sin_addr.s_addr = header->addr.addr4.src_addr; addr->sin_port = header->addr.addr4.src_port; @@ -963,6 +967,10 @@ static int consume_pp2_header(struct sldns_buffer* buf, struct comm_reply* rep, { struct sockaddr_in6* addr = (struct sockaddr_in6*)&rep->client_addr; + if(ntohs(header->len) < PP2_HEADER_LEN_INET6) { + verbose(VERB_OPS, "proxy_protocol: header too short for IPv6 address"); + return 0; + } memset(addr, 0, sizeof(*addr)); addr->sin6_family = AF_INET6; memcpy(&addr->sin6_addr, diff --git a/util/proxy_protocol.c b/util/proxy_protocol.c index 235538b62..689745ee9 100644 --- a/util/proxy_protocol.c +++ b/util/proxy_protocol.c @@ -185,14 +185,23 @@ pp2_read_header(uint8_t* buf, size_t buflen) (header->ver_cmd & 0xF) != PP2_CMD_PROXY) { return PP_PARSE_UNKNOWN_CMD; } - /* Check for supported family and protocol */ - if(header->fam_prot != PP2_UNSPEC_UNSPEC && - header->fam_prot != PP2_INET_STREAM && - header->fam_prot != PP2_INET_DGRAM && - header->fam_prot != PP2_INET6_STREAM && - header->fam_prot != PP2_INET6_DGRAM && - header->fam_prot != PP2_UNIX_STREAM && - header->fam_prot != PP2_UNIX_DGRAM) { + /* Check for supported family and protocol, and that len covers + * the per-family address block (proxy-protocol.txt s2.2). */ + switch(header->fam_prot) { + case PP2_UNSPEC_UNSPEC: + break; + case PP2_INET_STREAM: + case PP2_INET_DGRAM: + if(ntohs(header->len) < PP2_HEADER_LEN_INET) + return PP_PARSE_SIZE; + break; + case PP2_INET6_STREAM: + case PP2_INET6_DGRAM: + if(ntohs(header->len) < PP2_HEADER_LEN_INET6) + return PP_PARSE_SIZE; + break; + default: + /* PP2_UNIX_STREAM, PP2_UNIX_DGRAM, others. */ return PP_PARSE_UNKNOWN_FAM_PROT; } /* We have a correct header */ diff --git a/util/proxy_protocol.h b/util/proxy_protocol.h index ca81065bf..52a012815 100644 --- a/util/proxy_protocol.h +++ b/util/proxy_protocol.h @@ -54,6 +54,15 @@ /** PROXYv2 version (protocol value) */ #define PP2_VERSION 0x2 +/** PROXYv2 minimum header.len value for TCP/UDP over IPv4 */ +#define PP2_HEADER_LEN_INET 12 + +/** PROXYv2 minimum header.len value for TCP/UDP over IPv6 */ +#define PP2_HEADER_LEN_INET6 36 + +/** PROXYv2 minimum header.len value for TCP/UDP over AF_UNIX */ +#define PP2_HEADER_LEN_UNIX 216 + /** * PROXYv2 command (protocol value). */