untrusted comment: verify with openbsd-64-base.pub RWQq6XmS4eDAcfF84WcX0dX+IOx0kBYdvfCiuja1W7jQ7r13SSQ4tudOnRE103P0N26LdFkotBqzKPgkoQQJuhZ6Lhy9kTeMOwY= OpenBSD 6.4 errata 017, May 3, 2019: If a userland program sets the IPv6 checksum offset on a raw socket, an incoming packet could crash the kernel. ospf6d is such a program. Apply by doing: signify -Vep /etc/signify/openbsd-64-base.pub -x 017_rip6cksum.patch.sig \ -m - | (cd /usr/src && patch -p0) And then rebuild and install a new kernel: KK=`sysctl -n kern.osversion | cut -d# -f1` cd /usr/src/sys/arch/`machine`/compile/$KK make obj make config make make install Index: sys/netinet6/ip6_output.c =================================================================== RCS file: /cvs/src/sys/netinet6/ip6_output.c,v retrieving revision 1.239 diff -u -p -r1.239 ip6_output.c --- sys/netinet6/ip6_output.c 28 Aug 2018 15:15:02 -0000 1.239 +++ sys/netinet6/ip6_output.c 23 Apr 2019 01:42:50 -0000 @@ -1620,8 +1620,12 @@ ip6_raw_ctloutput(int op, struct socket break; } optval = *mtod(m, int *); - if ((optval % 2) != 0) { - /* the API assumes even offset values */ + if (optval < -1 || + (optval > 0 && (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) { if (optval != icmp6off) Index: sys/netinet6/raw_ip6.c =================================================================== RCS file: /cvs/src/sys/netinet6/raw_ip6.c,v retrieving revision 1.132 diff -u -p -r1.132 raw_ip6.c --- sys/netinet6/raw_ip6.c 4 Oct 2018 17:33:41 -0000 1.132 +++ sys/netinet6/raw_ip6.c 23 Apr 2019 01:42:50 -0000 @@ -185,7 +185,16 @@ rip6_input(struct mbuf **mp, int *offp, } if (proto != IPPROTO_ICMPV6 && in6p->inp_cksum6 != -1) { rip6stat_inc(rip6s_isum); - if (in6_cksum(m, proto, *offp, + /* + * Although in6_cksum() does not need the position of + * the checksum field for verification, enforce that it + * is located within the packet. Userland has given + * a checksum offset, a packet too short for that is + * invalid. Avoid overflow with user supplied offset. + */ + if (m->m_pkthdr.len < *offp + 2 || + m->m_pkthdr.len - *offp - 2 < in6p->inp_cksum6 || + in6_cksum(m, proto, *offp, m->m_pkthdr.len - *offp)) { rip6stat_inc(rip6s_badsum); continue; @@ -440,7 +449,7 @@ rip6_output(struct mbuf *m, struct socke off = offsetof(struct icmp6_hdr, icmp6_cksum); else off = in6p->inp_cksum6; - if (plen < off + 1) { + if (plen < 2 || plen - 2 < off) { error = EINVAL; goto bad; }