diff options
| author | Denys Fedoryshchenko <denys.f@collabora.com> | 2026-09-01 09:31:53 +0300 |
|---|---|---|
| committer | Denys Fedoryshchenko <denys.f@collabora.com> | 2026-09-01 09:31:53 +0300 |
| commit | d22666a84cc38b8018d839483db5df125fc6728b (patch) | |
| tree | f98ca13c11a4fbaa29b527ff7532025d88958cd9 | |
| parent | 7d4f8524f57ba0ac77e47171bebfc0370df667b1 (diff) | |
| download | accel-ppp-d22666a84cc38b8018d839483db5df125fc6728b.tar.gz accel-ppp-d22666a84cc38b8018d839483db5df125fc6728b.zip | |
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.
| -rw-r--r-- | accel-pppd/ppp/ppp_ipcp.c | 2 | ||||
| -rw-r--r-- | 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; } |
