untrusted comment: signature from openbsd 6.3 base secret key
RWRxzbLwAd76ZR2V57MYsY1AlkK7ncG5eulRKwgJx9OQhV7OeNWw49j2HXIZvAHh6HP3m/TL8gdurHsFCF4P76KZjdsw1xi3GgQ=

OpenBSD 6.3 errata 013, July 25, 2018:

When an IPsec key expired, the kernel could panic due to unfinished
timeout tasks.

Apply by doing:
   signify -Vep /etc/signify/openbsd-63-base.pub -x 013_ipsecexpire.patch.sig \
       -m - | (cd /usr/src && patch -p0)

And then rebuild and install the 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_ipsp.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ip_ipsp.c,v
retrieving revision 1.229
diff -u -p -r1.229 ip_ipsp.c
--- sys/netinet/ip_ipsp.c       6 Nov 2017 15:12:43 -0000       1.229
+++ sys/netinet/ip_ipsp.c       23 Jul 2018 13:35:52 -0000
@@ -79,10 +79,11 @@ void tdb_hashstats(void);
#endif

void           tdb_rehash(void);
-void           tdb_timeout(void *v);
-void           tdb_firstuse(void *v);
-void           tdb_soft_timeout(void *v);
-void           tdb_soft_firstuse(void *v);
+void           tdb_reaper(void *);
+void           tdb_timeout(void *);
+void           tdb_firstuse(void *);
+void           tdb_soft_timeout(void *);
+void           tdb_soft_firstuse(void *);
int            tdb_hash(u_int, u_int32_t, union sockaddr_union *, u_int8_t);

int ipsec_in_use = 0;
@@ -541,14 +542,13 @@ tdb_timeout(void *v)
{
       struct tdb *tdb = v;

-       if (!(tdb->tdb_flags & TDBF_TIMER))
-               return;
-
       NET_LOCK();
-       /* If it's an "invalid" TDB do a silent expiration. */
-       if (!(tdb->tdb_flags & TDBF_INVALID))
-               pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_HARD);
-       tdb_delete(tdb);
+       if (tdb->tdb_flags & TDBF_TIMER) {
+               /* If it's an "invalid" TDB do a silent expiration. */
+               if (!(tdb->tdb_flags & TDBF_INVALID))
+                       pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_HARD);
+               tdb_delete(tdb);
+       }
       NET_UNLOCK();
}

@@ -557,14 +557,13 @@ tdb_firstuse(void *v)
{
       struct tdb *tdb = v;

-       if (!(tdb->tdb_flags & TDBF_SOFT_FIRSTUSE))
-               return;
-
       NET_LOCK();
-       /* If the TDB hasn't been used, don't renew it. */
-       if (tdb->tdb_first_use != 0)
-               pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_HARD);
-       tdb_delete(tdb);
+       if (tdb->tdb_flags & TDBF_SOFT_FIRSTUSE) {
+               /* If the TDB hasn't been used, don't renew it. */
+               if (tdb->tdb_first_use != 0)
+                       pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_HARD);
+               tdb_delete(tdb);
+       }
       NET_UNLOCK();
}

@@ -573,13 +572,12 @@ tdb_soft_timeout(void *v)
{
       struct tdb *tdb = v;

-       if (!(tdb->tdb_flags & TDBF_SOFT_TIMER))
-               return;
-
       NET_LOCK();
-       /* Soft expirations. */
-       pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_SOFT);
-       tdb->tdb_flags &= ~TDBF_SOFT_TIMER;
+       if (tdb->tdb_flags & TDBF_SOFT_TIMER) {
+               /* Soft expirations. */
+               pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_SOFT);
+               tdb->tdb_flags &= ~TDBF_SOFT_TIMER;
+       }
       NET_UNLOCK();
}

@@ -588,14 +586,13 @@ tdb_soft_firstuse(void *v)
{
       struct tdb *tdb = v;

-       if (!(tdb->tdb_flags & TDBF_SOFT_FIRSTUSE))
-               return;
-
       NET_LOCK();
-       /* If the TDB hasn't been used, don't renew it. */
-       if (tdb->tdb_first_use != 0)
-               pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_SOFT);
-       tdb->tdb_flags &= ~TDBF_SOFT_FIRSTUSE;
+       if (tdb->tdb_flags & TDBF_SOFT_FIRSTUSE) {
+               /* If the TDB hasn't been used, don't renew it. */
+               if (tdb->tdb_first_use != 0)
+                       pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_SOFT);
+               tdb->tdb_flags &= ~TDBF_SOFT_FIRSTUSE;
+       }
       NET_UNLOCK();
}

@@ -841,14 +838,6 @@ tdb_free(struct tdb *tdbp)
               ipo->ipo_last_searched = 0; /* Force a re-search. */
       }

-       /* Remove expiration timeouts. */
-       tdbp->tdb_flags &= ~(TDBF_FIRSTUSE | TDBF_SOFT_FIRSTUSE | TDBF_TIMER |
-           TDBF_SOFT_TIMER);
-       timeout_del(&tdbp->tdb_timer_tmo);
-       timeout_del(&tdbp->tdb_first_tmo);
-       timeout_del(&tdbp->tdb_stimer_tmo);
-       timeout_del(&tdbp->tdb_sfirst_tmo);
-
       if (tdbp->tdb_ids) {
               ipsp_ids_free(tdbp->tdb_ids);
               tdbp->tdb_ids = NULL;
@@ -866,6 +855,23 @@ tdb_free(struct tdb *tdbp)

       if ((tdbp->tdb_inext) && (tdbp->tdb_inext->tdb_onext == tdbp))
               tdbp->tdb_inext->tdb_onext = NULL;
+
+       /* Remove expiration timeouts. */
+       tdbp->tdb_flags &= ~(TDBF_FIRSTUSE | TDBF_SOFT_FIRSTUSE | TDBF_TIMER |
+           TDBF_SOFT_TIMER);
+       timeout_del(&tdbp->tdb_timer_tmo);
+       timeout_del(&tdbp->tdb_first_tmo);
+       timeout_del(&tdbp->tdb_stimer_tmo);
+       timeout_del(&tdbp->tdb_sfirst_tmo);
+
+       timeout_set_proc(&tdbp->tdb_timer_tmo, tdb_reaper, tdbp);
+       timeout_add(&tdbp->tdb_timer_tmo, 0);
+}
+
+void
+tdb_reaper(void *xtdbp)
+{
+       struct tdb *tdbp = xtdbp;

       free(tdbp, M_TDB, 0);
}