git: 1fe3a2897b4a - stable/14 - rawip: Fix handling of checksums in rip6_input()
Mark Johnston <[email protected]>
| Newsgroups | gmane.os.freebsd.devel.cvs.src |
|---|---|
| Message-ID | <6a861a40.30fb8.2082cdb8__5007.83757758967$1787173473$gmane$org@gitrepo.freebsd.org> |
The branch stable/14 has been updated by markj: URL: https://cgit.FreeBSD.org/src/commit/?id=1fe3a2897b4ad7a9b9128efd6ec0c24b371bf5bd commit 1fe3a2897b4ad7a9b9128efd6ec0c24b371bf5bd Author: Mark Johnston <[email protected]> AuthorDate: 2026-08-04 13:35:35 +0000 Commit: Mark Johnston <[email protected]> CommitDate: 2026-08-19 18:08:59 +0000 rawip: Fix handling of checksums in rip6_input() A v6 raw socket may ask the kernel to validate the checksum of an inbound packet. If it does, and the validation fails, we discard the packet, but this isn't really right: other raw sockets may wish to receive a copy of the packet anyway. Rework checksum handling to address this problem, and use a flag to avoid computing the checksum more than once for a given packet. Fixes: de2d47842e880281 ("SMR protection for inpcbs") Reviewed by: pouria, glebius Reported by: Yunzhi Ke MFC after: 1 week Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D58559 (cherry picked from commit 196874ce2e97e3e6425493b1d501e716b356bc36) --- sys/netinet6/raw_ip6.c | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/sys/netinet6/raw_ip6.c b/sys/netinet6/raw_ip6.c index caefba22c0ca..1a1d7f37145f 100644 --- a/sys/netinet6/raw_ip6.c +++ b/sys/netinet6/raw_ip6.c @@ -194,7 +194,8 @@ rip6_input(struct mbuf **mp, int *offp, int proto) struct rip6_inp_match_ctx ctx = { .ip6 = ip6, .proto = proto }; struct inpcb_iterator inpi = INP_ITERATOR(&V_ripcbinfo, INPLOOKUP_RLOCKPCB, rip6_inp_match, &ctx); - int delivered = 0, fib; + int cksum, delivered = 0, fib; + bool cksum_computed = false; M_ASSERTPKTHDR(m); NET_EPOCH_ASSERT(); @@ -234,19 +235,22 @@ rip6_input(struct mbuf **mp, int *offp, int proto) */ continue; if (inp->in6p_cksum != -1) { - RIP6STAT_INC(rip6s_isum); - if (m->m_pkthdr.len - (*offp + inp->in6p_cksum) < 2 || - in6_cksum(m, proto, *offp, - m->m_pkthdr.len - *offp)) { - RIP6STAT_INC(rip6s_badsum); + if (m->m_pkthdr.len - (*offp + inp->in6p_cksum) < 2) + continue; + if (!cksum_computed) { + cksum = in6_cksum(m, proto, *offp, + m->m_pkthdr.len - *offp); + cksum_computed = true; + RIP6STAT_INC(rip6s_isum); + if (cksum != 0) + RIP6STAT_INC(rip6s_badsum); + } + if (cksum != 0) { /* - * Drop the received message, don't send an - * ICMP6 message. Set proto to IPPROTO_NONE - * to achieve that. + * Drop the packet, don't send an ICMP6 message. */ - INP_RUNLOCK(inp); proto = IPPROTO_NONE; - break; + continue; } } /*