untrusted comment: signature from openbsd 6.2 base secret key
RWRVWzAMgtyg7gRLOEq05ScMhvGwVOtOWgAgzELGN8wwfvx3CbSBYSKwXo7xr/PC444JXfTnnefmn6xgl/UMAvgnWeLL+BN/PwA=

OpenBSD 6.2 errata 005, February 2nd, 2018:

Specially crafted IPsec AH packets with IP options or IPv6 extension
headers could crash or hang the kernel.

Apply by doing:
   signify -Vep /etc/signify/openbsd-62-base.pub -x 005_ahopts.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/netinet/ip_ah.c
===================================================================
RCS file: /cvs/src/sys/netinet/ip_ah.c,v
retrieving revision 1.131
diff -u -p -r1.131 ip_ah.c
--- sys/netinet/ip_ah.c 11 Aug 2017 21:24:19 -0000      1.131
+++ sys/netinet/ip_ah.c 1 Feb 2018 19:15:45 -0000
@@ -202,7 +202,7 @@ ah_massage_headers(struct mbuf **m0, int
#ifdef INET6
       struct ip6_ext *ip6e;
       struct ip6_hdr ip6;
-       int ad, alloc, nxt;
+       int ad, alloc, nxt, noff;
#endif /* INET6 */

       switch (proto) {
@@ -226,7 +226,7 @@ ah_massage_headers(struct mbuf **m0, int
               ip->ip_sum = 0;
               ip->ip_off = 0;

-               ptr = mtod(m, unsigned char *) + sizeof(struct ip);
+               ptr = mtod(m, unsigned char *);

               /* IPv4 option processing */
               for (off = sizeof(struct ip); off < skip;) {
@@ -293,10 +293,12 @@ ah_massage_headers(struct mbuf **m0, int
                                * what the destination's IP header
                                * will look like.
                                */
-                               if (out)
-                                       bcopy(ptr + off + ptr[off + 1] -
+                               if (out &&
+                                   ptr[off + 1] >= 2 + sizeof(struct in_addr))
+                                       memcpy(&ip->ip_dst,
+                                           ptr + off + ptr[off + 1] -
                                           sizeof(struct in_addr),
-                                           &(ip->ip_dst), sizeof(struct in_addr));
+                                           sizeof(struct in_addr));

                               /* FALLTHROUGH */
                       default:
@@ -312,7 +314,7 @@ ah_massage_headers(struct mbuf **m0, int

                               /* Zeroize all other options. */
                               count = ptr[off + 1];
-                               memcpy(ptr, ipseczeroes, count);
+                               memset(ptr + off, 0, count);
                               off += count;
                               break;
                       }
@@ -389,57 +391,46 @@ ah_massage_headers(struct mbuf **m0, int
               nxt = ip6.ip6_nxt & 0xff; /* Next header type. */

               for (off = 0; off < skip - sizeof(struct ip6_hdr);) {
+                       if (off + sizeof(struct ip6_ext) >
+                           skip - sizeof(struct ip6_hdr))
+                               goto error6;
+                       ip6e = (struct ip6_ext *)(ptr + off);
+
                       switch (nxt) {
                       case IPPROTO_HOPOPTS:
                       case IPPROTO_DSTOPTS:
-                               ip6e = (struct ip6_ext *) (ptr + off);
+                               noff = off + ((ip6e->ip6e_len + 1) << 3);
+
+                               /* Sanity check. */
+                               if (noff > skip - sizeof(struct ip6_hdr))
+                                       goto error6;

                               /*
-                                * Process the mutable/immutable
-                                * options -- borrows heavily from the
-                                * KAME code.
+                                * Zero out mutable options.
                                */
                               for (count = off + sizeof(struct ip6_ext);
-                                    count < off + ((ip6e->ip6e_len + 1) << 3);) {
+                                    count < noff;) {
                                       if (ptr[count] == IP6OPT_PAD1) {
                                               count++;
                                               continue; /* Skip padding. */
                                       }

-                                       /* Sanity check. */
-                                       if (count > off +
-                                           ((ip6e->ip6e_len + 1) << 3)) {
-                                               ahstat.ahs_hdrops++;
-                                               m_freem(m);
-
-                                               /* Free, if we allocated. */
-                                               if (alloc)
-                                                       free(ptr, M_XDATA, 0);
-                                               return EINVAL;
-                                       }
-
-                                       ad = ptr[count + 1];
+                                       if (count + 2 > noff)
+                                               goto error6;
+                                       ad = ptr[count + 1] + 2;
+                                       if (count + ad > noff)
+                                               goto error6;

                                       /* If mutable option, zeroize. */
                                       if (ptr[count] & IP6OPT_MUTABLE)
-                                               memcpy(ptr + count, ipseczeroes,
-                                                   ptr[count + 1]);
+                                               memset(ptr + count, 0, ad);

                                       count += ad;
-
-                                       /* Sanity check. */
-                                       if (count >
-                                           skip - sizeof(struct ip6_hdr)) {
-                                               ahstat.ahs_hdrops++;
-                                               m_freem(m);
-
-                                               /* Free, if we allocated. */
-                                               if (alloc)
-                                                       free(ptr, M_XDATA, 0);
-                                               return EINVAL;
-                                       }
                               }

+                               if (count != noff)
+                                       goto error6;
+
                               /* Advance. */
                               off += ((ip6e->ip6e_len + 1) << 3);
                               nxt = ip6e->ip6e_nxt;
@@ -453,7 +444,6 @@ ah_massage_headers(struct mbuf **m0, int
                           {
                               struct ip6_rthdr *rh;

-                               ip6e = (struct ip6_ext *) (ptr + off);
                               rh = (struct ip6_rthdr *)(ptr + off);
                               /*
                                * must adjust content to make it look like
@@ -498,6 +488,7 @@ ah_massage_headers(struct mbuf **m0, int
                       default:
                               DPRINTF(("ah_massage_headers(): unexpected "
                                   "IPv6 header type %d\n", off));
+error6:
                               if (alloc)
                                       free(ptr, M_XDATA, 0);
                               ahstat.ahs_hdrops++;