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