untrusted comment: signature from openbsd 6.2 base secret key
RWRVWzAMgtyg7hrX0W3MfBjHCqxXfZK8hxg53pU2kHsLGqoHEvQJr73pVWZIY3neMUmT4lSsyoaTsmV4XVSFMXhOrXNlYt/B9QA=

OpenBSD 6.2 errata 006, February 2nd, 2018:

Processing IPv6 fragments could incorrectly access memory of a mbuf
chain that is not within a mbuf.  This may crash the kernel.

Apply by doing:
   signify -Vep /etc/signify/openbsd-62-base.pub -x 006_prevhdr.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/frag6.c
===================================================================
RCS file: /cvs/src/sys/netinet6/frag6.c,v
retrieving revision 1.74
diff -u -p -r1.74 frag6.c
--- sys/netinet6/frag6.c        16 May 2017 12:24:02 -0000      1.74
+++ sys/netinet6/frag6.c        1 Feb 2018 19:18:07 -0000
@@ -476,14 +476,6 @@ frag6_input(struct mbuf **mp, int *offp,
               goto dropfrag;
       }

-       /*
-        * Store NXT to the original.
-        */
-       {
-               u_int8_t *prvnxtp = ip6_get_prevhdr(m, offset); /* XXX */
-               *prvnxtp = nxt;
-       }
-
       TAILQ_REMOVE(&frag6_queue, q6, ip6q_queue);
       frag6_nfrags -= q6->ip6q_nfrag;
       free(q6, M_FTABLE, sizeof(*q6));
@@ -494,6 +486,20 @@ frag6_input(struct mbuf **mp, int *offp,
               for (t = m; t; t = t->m_next)
                       plen += t->m_len;
               m->m_pkthdr.len = plen;
+       }
+
+       /*
+        * Restore NXT to the original.
+        */
+       {
+               int prvnxt = ip6_get_prevhdr(m, offset);
+               uint8_t *prvnxtp;
+
+               IP6_EXTHDR_GET(prvnxtp, uint8_t *, m, prvnxt,
+                   sizeof(*prvnxtp));
+               if (prvnxtp == NULL)
+                       goto dropfrag;
+               *prvnxtp = nxt;
       }

       ip6stat_inc(ip6s_reassembled);
Index: sys/netinet6/ip6_input.c
===================================================================
RCS file: /cvs/src/sys/netinet6/ip6_input.c,v
retrieving revision 1.202
diff -u -p -r1.202 ip6_input.c
--- sys/netinet6/ip6_input.c    22 Aug 2017 15:02:34 -0000      1.202
+++ sys/netinet6/ip6_input.c    1 Feb 2018 19:18:07 -0000
@@ -1189,50 +1189,44 @@ ip6_pullexthdr(struct mbuf *m, size_t of
}

/*
- * Get pointer to the previous header followed by the header
+ * Get offset to the previous header followed by the header
 * currently processed.
- * XXX: This function supposes that
- *     M includes all headers,
- *     the next header field and the header length field of each header
- *     are valid, and
- *     the sum of each header length equals to OFF.
- * Because of these assumptions, this function must be called very
- * carefully. Moreover, it will not be used in the near future when
- * we develop `neater' mechanism to process extension headers.
 */
-u_int8_t *
+int
ip6_get_prevhdr(struct mbuf *m, int off)
{
       struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);

-       if (off == sizeof(struct ip6_hdr))
-               return (&ip6->ip6_nxt);
-       else {
-               int len, nxt;
-               struct ip6_ext *ip6e = NULL;
+       if (off == sizeof(struct ip6_hdr)) {
+               return offsetof(struct ip6_hdr, ip6_nxt);
+       } else if (off < sizeof(struct ip6_hdr)) {
+               panic("%s: off < sizeof(struct ip6_hdr)", __func__);
+       } else {
+               int len, nlen, nxt;
+               struct ip6_ext ip6e;

               nxt = ip6->ip6_nxt;
               len = sizeof(struct ip6_hdr);
+               nlen = 0;
               while (len < off) {
-                       ip6e = (struct ip6_ext *)(mtod(m, caddr_t) + len);
+                       m_copydata(m, len, sizeof(ip6e), (caddr_t)&ip6e);

                       switch (nxt) {
                       case IPPROTO_FRAGMENT:
-                               len += sizeof(struct ip6_frag);
+                               nlen = sizeof(struct ip6_frag);
                               break;
                       case IPPROTO_AH:
-                               len += (ip6e->ip6e_len + 2) << 2;
+                               nlen = (ip6e.ip6e_len + 2) << 2;
                               break;
                       default:
-                               len += (ip6e->ip6e_len + 1) << 3;
+                               nlen = (ip6e.ip6e_len + 1) << 3;
                               break;
                       }
-                       nxt = ip6e->ip6e_nxt;
+                       len += nlen;
+                       nxt = ip6e.ip6e_nxt;
               }
-               if (ip6e)
-                       return (&ip6e->ip6e_nxt);
-               else
-                       return NULL;
+
+               return (len - nlen);
       }
}

Index: sys/netinet6/ip6_var.h
===================================================================
RCS file: /cvs/src/sys/netinet6/ip6_var.h,v
retrieving revision 1.78
diff -u -p -r1.78 ip6_var.h
--- sys/netinet6/ip6_var.h      13 Jul 2017 17:17:27 -0000      1.78
+++ sys/netinet6/ip6_var.h      1 Feb 2018 19:18:07 -0000
@@ -305,7 +305,7 @@ int ip6_input_if(struct mbuf **, int *,
void   ip6_freepcbopts(struct ip6_pktopts *);
void   ip6_freemoptions(struct ip6_moptions *);
int    ip6_unknown_opt(u_int8_t *, struct mbuf *, int);
-u_int8_t *ip6_get_prevhdr(struct mbuf *, int);
+int    ip6_get_prevhdr(struct mbuf *, int);
int    ip6_nexthdr(struct mbuf *, int, int, int *);
int    ip6_lasthdr(struct mbuf *, int, int, int *);
int    ip6_mforward(struct ip6_hdr *, struct ifnet *, struct mbuf *);
Index: sys/netinet6/raw_ip6.c
===================================================================
RCS file: /cvs/src/sys/netinet6/raw_ip6.c,v
retrieving revision 1.119
diff -u -p -r1.119 raw_ip6.c
--- sys/netinet6/raw_ip6.c      5 Sep 2017 07:59:11 -0000       1.119
+++ sys/netinet6/raw_ip6.c      1 Feb 2018 19:18:07 -0000
@@ -229,10 +229,10 @@ rip6_input(struct mbuf **mp, int *offp,
               if (proto == IPPROTO_NONE || proto == IPPROTO_ICMPV6) {
                       m_freem(m);
               } else {
-                       u_int8_t *prvnxtp = ip6_get_prevhdr(m, *offp); /* XXX */
+                       int prvnxt = ip6_get_prevhdr(m, *offp);
+
                       icmp6_error(m, ICMP6_PARAM_PROB,
-                           ICMP6_PARAMPROB_NEXTHEADER,
-                           prvnxtp - mtod(m, u_int8_t *));
+                           ICMP6_PARAMPROB_NEXTHEADER, prvnxt);
               }
               counters = counters_enter(&ref, ip6counters);
               counters[ip6s_delivered]--;