]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
libipsec: Make sure to expire the right SA
authorTobias Brunner <tobias@strongswan.org>
Mon, 14 Aug 2017 14:03:54 +0000 (16:03 +0200)
committerTobias Brunner <tobias@strongswan.org>
Mon, 18 Sep 2017 08:51:39 +0000 (10:51 +0200)
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

index 957d930f2697df1fcda1112e3f7a66726086be23..44d35244a54ae8f0ff65522dd1f374fbf17e91b5 100644 (file)
@@ -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 */