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); }