Module Name: src Committed By: ozaki-r Date: Tue Jul 23 04:29:27 UTC 2019
Modified Files: src/sys/netipsec: key.c Log Message: ipsec: fix a regression of the update API The update API updates an SA by creating a new SA and removing an existing SA. The previous change removed a newly added SA wrongly if an existing SA had been created by the getspi API. To generate a diff of this commit: cvs rdiff -u -r1.264 -r1.265 src/sys/netipsec/key.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/netipsec/key.c diff -u src/sys/netipsec/key.c:1.264 src/sys/netipsec/key.c:1.265 --- src/sys/netipsec/key.c:1.264 Wed Jul 17 07:07:59 2019 +++ src/sys/netipsec/key.c Tue Jul 23 04:29:26 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: key.c,v 1.264 2019/07/17 07:07:59 ozaki-r Exp $ */ +/* $NetBSD: key.c,v 1.265 2019/07/23 04:29:26 ozaki-r Exp $ */ /* $FreeBSD: key.c,v 1.3.2.3 2004/02/14 22:23:23 bms Exp $ */ /* $KAME: key.c,v 1.191 2001/06/27 10:46:49 sakane Exp $ */ @@ -32,7 +32,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: key.c,v 1.264 2019/07/17 07:07:59 ozaki-r Exp $"); +__KERNEL_RCSID(0, "$NetBSD: key.c,v 1.265 2019/07/23 04:29:26 ozaki-r Exp $"); /* * This code is referred to RFC 2367 @@ -3530,7 +3530,8 @@ out: * others : found, pointer to a SA. */ static struct secasvar * -key_lookup_and_remove_sav(struct secashead *sah, u_int32_t spi) +key_lookup_and_remove_sav(struct secashead *sah, u_int32_t spi, + const struct secasvar *hint) { struct secasvar *sav = NULL; u_int state; @@ -3542,6 +3543,8 @@ key_lookup_and_remove_sav(struct secashe KASSERT(sav->state == state); if (sav->spi == spi) { + if (hint != NULL && hint != sav) + continue; sav->state = SADB_SASTATE_DEAD; SAVLIST_WRITER_REMOVE(sav); SAVLUT_WRITER_REMOVE(sav); @@ -5807,7 +5810,8 @@ key_api_update(struct socket *so, struct * We need to lookup and remove the sav atomically, so get it again * here by a special API while we have a reference to it. */ - oldsav = key_lookup_and_remove_sav(sah, sa0->sadb_sa_spi); + oldsav = key_lookup_and_remove_sav(sah, sa0->sadb_sa_spi, sav); + KASSERT(oldsav == NULL || oldsav == sav); /* We can release the reference because of oldsav */ KEY_SA_UNREF(&sav); if (oldsav == NULL) { @@ -6222,7 +6226,7 @@ key_api_delete(struct socket *so, struct sah = key_getsah_ref(&saidx, CMP_HEAD); if (sah != NULL) { /* get a SA with SPI. */ - sav = key_lookup_and_remove_sav(sah, sa0->sadb_sa_spi); + sav = key_lookup_and_remove_sav(sah, sa0->sadb_sa_spi, NULL); key_sah_unref(sah); }