From 6e861947a018e659a813f08214671d7da32a8463 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Mon, 14 Aug 2017 16:03:54 +0200 Subject: [PATCH] libipsec: Make sure to expire the right SA If an IPsec SA is actually replaced with a rekeying its entry in the manager is freed. That means that when the hard expire is triggered a new entry might be found at the cached pointer location. So we have to make sure we trigger the expire only if we found the right SA. We could use SPI and addresses for the lookup, but this here requires a bit less memory and is just a small change. Another option would be to somehow cancel the queued job, but our scheduler doesn't allow that at the moment. Fixes #2399. --- src/libipsec/ipsec_sa_mgr.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/libipsec/ipsec_sa_mgr.c b/src/libipsec/ipsec_sa_mgr.c index 957d930f2..44d35244a 100644 --- a/src/libipsec/ipsec_sa_mgr.c +++ b/src/libipsec/ipsec_sa_mgr.c @@ -106,6 +106,11 @@ typedef struct { */ ipsec_sa_entry_t *entry; + /** + * SPI of the expired entry + */ + uint32_t spi; + /** * 0 if this is a hard expire, otherwise the offset in s (soft->hard) */ @@ -314,8 +319,9 @@ static job_requeue_t sa_expired(ipsec_sa_expired_t *expired) private_ipsec_sa_mgr_t *this = expired->manager; this->mutex->lock(this->mutex); - if (this->sas->find_first(this->sas, NULL, (void**)&expired->entry)) - { + if (this->sas->find_first(this->sas, NULL, (void**)&expired->entry) && + expired->spi == expired->entry->sa->get_spi(expired->entry->sa)) + { /* only if we find the right SA at this pointer location */ uint32_t hard_offset; hard_offset = expired->hard_offset; @@ -355,6 +361,7 @@ static void schedule_expiration(private_ipsec_sa_mgr_t *this, INIT(expired, .manager = this, .entry = entry, + .spi = entry->sa->get_spi(entry->sa), ); /* schedule a rekey first, a hard timeout will be scheduled then, if any */