diff mbox series

[v2,1/5] linux-gen: ipsec: disallow using SAs while they are being created

Message ID 1517238014-22220-2-git-send-email-odpbot@yandex.ru
State New
Headers show
Series [v2,1/5] linux-gen: ipsec: disallow using SAs while they are being created | expand

Commit Message

Github ODP bot Jan. 29, 2018, 3 p.m. UTC
From: Dmitry Eremin-Solenikov <dmitry.ereminsolenikov@linaro.org>


Current code has a race condition between inbound traffic and creation
of new SA. It is possible for inbound traffic to trigger partially
created SA using SA_LOOKUP option (or INLINE mode). Add separate
(RESERVED) stage for SA which is in process of being created.

Fixes: https://bugs.linaro.org/show_bug.cgi?id=3594
Signed-off-by: Dmitry Eremin-Solenikov <dmitry.ereminsolenikov@linaro.org>

---
/** Email created from pull request 427 (lumag:ipsec-fix-sad)
 ** https://github.com/Linaro/odp/pull/427
 ** Patch: https://github.com/Linaro/odp/pull/427.patch
 ** Base sha: 27480d82bd93a881ae683a3c314c11042a68ce29
 ** Merge commit sha: 67c9dbf28c41ea7a53782ba841276b03f154c4ef
 **/
 platform/linux-generic/odp_ipsec_sad.c | 20 ++++++++++++++++----
 1 file changed, 16 insertions(+), 4 deletions(-)
diff mbox series

Patch

diff --git a/platform/linux-generic/odp_ipsec_sad.c b/platform/linux-generic/odp_ipsec_sad.c
index 845a73dea..bb984db38 100644
--- a/platform/linux-generic/odp_ipsec_sad.c
+++ b/platform/linux-generic/odp_ipsec_sad.c
@@ -17,7 +17,8 @@ 
 #include <string.h>
 
 #define IPSEC_SA_STATE_DISABLE	0x40000000
-#define IPSEC_SA_STATE_FREE	0xc0000000 /* This includes disable !!! */
+#define IPSEC_SA_STATE_FREE	0xc0000000
+#define IPSEC_SA_STATE_RESERVED	0x80000000
 
 typedef struct ipsec_sa_table_t {
 	ipsec_sa_t ipsec_sa[ODP_CONFIG_IPSEC_SAS];
@@ -108,7 +109,8 @@  static ipsec_sa_t *ipsec_sa_reserve(void)
 
 		ipsec_sa = ipsec_sa_entry(i);
 
-		if (odp_atomic_cas_acq_u32(&ipsec_sa->state, &state, 0))
+		if (odp_atomic_cas_acq_u32(&ipsec_sa->state, &state,
+					   IPSEC_SA_STATE_RESERVED))
 			return ipsec_sa;
 	}
 
@@ -120,6 +122,12 @@  static void ipsec_sa_release(ipsec_sa_t *ipsec_sa)
 	odp_atomic_store_rel_u32(&ipsec_sa->state, IPSEC_SA_STATE_FREE);
 }
 
+/* Mark reserved SA as available now */
+static void ipsec_sa_publish(ipsec_sa_t *ipsec_sa)
+{
+	odp_atomic_store_rel_u32(&ipsec_sa->state, 0);
+}
+
 static int ipsec_sa_lock(ipsec_sa_t *ipsec_sa)
 {
 	int cas = 0;
@@ -128,9 +136,11 @@  static int ipsec_sa_lock(ipsec_sa_t *ipsec_sa)
 	while (0 == cas) {
 		/*
 		 * This can be called from lookup path, so we really need this
-		 * check
+		 * check. Thanks to the way flags are defined we actually test
+		 * that the SA is not DISABLED, FREE or RESERVED using just one
+		 * condition.
 		 */
-		if (state & IPSEC_SA_STATE_DISABLE)
+		if (state & IPSEC_SA_STATE_FREE)
 			return -1;
 
 		cas = odp_atomic_cas_acq_u32(&ipsec_sa->state, &state,
@@ -438,6 +448,8 @@  odp_ipsec_sa_t odp_ipsec_sa_create(const odp_ipsec_sa_param_t *param)
 				      &ses_create_rc))
 		goto error;
 
+	ipsec_sa_publish(ipsec_sa);
+
 	return ipsec_sa->ipsec_sa_hdl;
 
 error: