diff options
| author | Cy Schubert <cy@FreeBSD.org> | 2026-05-11 15:44:52 +0000 |
|---|---|---|
| committer | Cy Schubert <cy@FreeBSD.org> | 2026-05-20 15:32:37 +0000 |
| commit | 8dfb0805fc31cd78940429ab0560dae7e8ab6536 (patch) | |
| tree | 40801da765d4df151fd449157d69d94bbb81dfa2 | |
| parent | c796cc5afff2dffd542880c5f624439b25d74402 (diff) | |
ipfilter: Validate length before checksum
Validate the length of the packet listed in the mbuf is the same as
the calculated packet length. If not reject the packet and bump the
bad packet stat.
PR: 295198
MFC after: 1 week
Differential Revision: https://reviews.freebsd.org/D57095
| -rw-r--r-- | sys/netpfil/ipfilter/netinet/fil.c | 17 |
1 files changed, 13 insertions, 4 deletions
diff --git a/sys/netpfil/ipfilter/netinet/fil.c b/sys/netpfil/ipfilter/netinet/fil.c index 9217572aac50..cabc6c350981 100644 --- a/sys/netpfil/ipfilter/netinet/fil.c +++ b/sys/netpfil/ipfilter/netinet/fil.c @@ -1991,7 +1991,7 @@ ipf_checkcipso(fr_info_t *fin, u_char *s, int ol) /* ------------------------------------------------------------------------ */ /* Function: ipf_makefrip */ -/* Returns: int - 0 == packet ok, -1 == packet freed */ +/* Returns: int - 0 == packet ok, -1 == packet freed or bad length */ /* Parameters: hlen(I) - length of IP packet header */ /* ip(I) - pointer to the IP header */ /* fin(IO) - pointer to packet information */ @@ -2019,14 +2019,23 @@ ipf_makefrip(int hlen, ip_t *ip, fr_info_t *fin) if (v == 4) { fin->fin_plen = ntohs(ip->ip_len); fin->fin_dlen = fin->fin_plen - hlen; - ipf_pr_ipv4hdr(fin); + if (fin->fin_m != NULL && fin->fin_m->m_flags & M_PKTHDR && fin->fin_m->m_pkthdr.len < fin->fin_plen) { + LBUMPD(ipf_stats[fin->fin_out], fr_bad); + return (-1); + } else { + ipf_pr_ipv4hdr(fin); + } #ifdef USE_INET6 } else if (v == 6) { fin->fin_plen = ntohs(((ip6_t *)ip)->ip6_plen); fin->fin_dlen = fin->fin_plen; fin->fin_plen += hlen; - - ipf_pr_ipv6hdr(fin); + if (fin->fin_m != NULL && fin->fin_m->m_flags & M_PKTHDR && fin->fin_m->m_pkthdr.len < fin->fin_plen) { + LBUMPD(ipf_stats[fin->fin_out], fr_v6_bad); + return (-1); + } else { + ipf_pr_ipv6hdr(fin); + } #endif } if (fin->fin_ip == NULL) { |
