From d22666a84cc38b8018d839483db5df125fc6728b Mon Sep 17 00:00:00 2001 From: Denys Fedoryshchenko Date: Tue, 1 Sep 2026 09:31:53 +0300 Subject: ppp: bound IPCP and IPV6CP packets by the received size ipcp_recv() and ipv6cp_recv() only rejected packets whose header length field was below PPP_HEADERLEN. The upper bound was missing, so the option walker was handed a size derived purely from the peer chosen hdr->len. ppp->buf is a fixed 8192 byte mempool block and ppp->buf_size holds the number of bytes actually read, so a short frame declaring hdr->len 0xffff made the option loop run off the end of the block: it kept fetching option headers from whatever followed in the heap and stored pointers to them in the ropt list. The read is harmless in itself but easily reaches unmapped memory and kills the daemon. Reject any packet whose declared length does not fit in what was received, the way lcp_recv() and ccp_recv() already do. The two byte slack accounts for the protocol field that precedes the header inside the buffer, and the existing buf_size >= PPP_HEADERLEN + 2 test just above keeps the subtraction from underflowing. --- accel-pppd/ppp/ppp_ipcp.c | 2 +- accel-pppd/ppp/ppp_ipv6cp.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/accel-pppd/ppp/ppp_ipcp.c b/accel-pppd/ppp/ppp_ipcp.c index b67bfa44..a919883a 100644 --- a/accel-pppd/ppp/ppp_ipcp.c +++ b/accel-pppd/ppp/ppp_ipcp.c @@ -695,7 +695,7 @@ static void ipcp_recv(struct ppp_handler_t*h) } hdr = (struct ipcp_hdr_t *)ipcp->ppp->buf; - if (ntohs(hdr->len) < PPP_HEADERLEN) { + if (ntohs(hdr->len) < PPP_HEADERLEN || ntohs(hdr->len) > ipcp->ppp->buf_size - 2) { log_ppp_warn("IPCP: short packet received\n"); return; } diff --git a/accel-pppd/ppp/ppp_ipv6cp.c b/accel-pppd/ppp/ppp_ipv6cp.c index 755e8903..5f08e46c 100644 --- a/accel-pppd/ppp/ppp_ipv6cp.c +++ b/accel-pppd/ppp/ppp_ipv6cp.c @@ -699,7 +699,7 @@ static void ipv6cp_recv(struct ppp_handler_t*h) } hdr = (struct ipv6cp_hdr_t *)ipv6cp->ppp->buf; - if (ntohs(hdr->len) < PPP_HEADERLEN) { + if (ntohs(hdr->len) < PPP_HEADERLEN || ntohs(hdr->len) > ipv6cp->ppp->buf_size - 2) { log_ppp_warn("IPV6CP: short packet received\n"); return; } -- cgit v1.2.3