Index: sys/netinet6/ip6_output.c =================================================================== --- sys/netinet6/ip6_output.c +++ sys/netinet6/ip6_output.c @@ -2221,8 +2221,11 @@ sizeof(optval)); if (error) break; - if ((optval % 2) != 0) { - /* the API assumes even offset values */ + if (optval < -1 || (optval % 2) != 0) { + /* + * The API assumes non-negative even offset + * values or -1 as a special value. + */ error = EINVAL; } else if (so->so_proto->pr_protocol == IPPROTO_ICMPV6) { Index: sys/netinet6/raw_ip6.c =================================================================== --- sys/netinet6/raw_ip6.c +++ sys/netinet6/raw_ip6.c @@ -166,6 +166,7 @@ struct mbuf *opts = NULL; struct sockaddr_in6 fromsa; struct epoch_tracker et; + int drop = 0; RIP6STAT_INC(rip6s_ipackets); @@ -239,9 +240,11 @@ } if (in6p->in6p_cksum != -1) { RIP6STAT_INC(rip6s_isum); - if (in6_cksum(m, proto, *offp, + if (m->m_pkthdr.len - (*offp + in6p->in6p_cksum) < 2 || + in6_cksum(m, proto, *offp, m->m_pkthdr.len - *offp)) { RIP6STAT_INC(rip6s_badsum); + drop = 1; goto skip_2; } } @@ -328,7 +331,7 @@ RIP6STAT_INC(rip6s_nosock); if (m->m_flags & M_MCAST) RIP6STAT_INC(rip6s_nosockmcast); - if (proto == IPPROTO_NONE) + if (proto == IPPROTO_NONE || drop == 1) m_freem(m); else icmp6_error(m, ICMP6_PARAM_PROB, @@ -495,7 +498,7 @@ off = offsetof(struct icmp6_hdr, icmp6_cksum); else off = in6p->in6p_cksum; - if (plen < off + 1) { + if (plen < off + 2) { error = EINVAL; goto bad; }