From dd1ccb4fd3b4428714ffcc5bd669fb8c11e46e8e Mon Sep 17 00:00:00 2001
From: Benoît Ganne <bganne@cisco.com>
Date: Mon, 5 Aug 2019 17:07:20 +0200
Subject: rdma: fix double-free in rdma-tx
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

In case of tx success after multiple retries, the last buffers to be
enqueued will be both enqueued for tx and freed.

Type: fix
Fixes: 211ef2eb24

Change-Id: I57d218cff58b74c1f3d6dc5722624327f0821758
Signed-off-by: Benoît Ganne <bganne@cisco.com>
---
 src/plugins/rdma/input.c  | 12 ++++++------
 src/plugins/rdma/output.c |  7 ++++---
 2 files changed, 10 insertions(+), 9 deletions(-)

(limited to 'src')

diff --git a/src/plugins/rdma/input.c b/src/plugins/rdma/input.c
index 7ced1ec66d4..f5091db4719 100644
--- a/src/plugins/rdma/input.c
+++ b/src/plugins/rdma/input.c
@@ -128,12 +128,12 @@ rdma_device_input_refill (vlib_main_t * vm, rdma_device_t * rd,
 
   w[-1].next = 0;		/* fix next pointer in WR linked-list last item */
 
-  w = wr;
-  ibv_post_wq_recv (rxq->wq, wr, &w);
-  n = wr == w ? n_alloc : (uintptr_t) (w - wr);
-
-  if (PREDICT_FALSE (n != n_alloc))
-    vlib_buffer_free (vm, buffers + n, n_alloc - n);
+  n = n_alloc;
+  if (ibv_post_wq_recv (rxq->wq, wr, &w) != 0)
+    {
+      n = w - wr;
+      vlib_buffer_free (vm, buffers + n, n_alloc - n);
+    }
 
   rxq->n_enq += n;
 }
diff --git a/src/plugins/rdma/output.c b/src/plugins/rdma/output.c
index bb25abe1a98..ddda81a4b19 100644
--- a/src/plugins/rdma/output.c
+++ b/src/plugins/rdma/output.c
@@ -57,7 +57,7 @@ VNET_DEVICE_CLASS_TX_FN (rdma_device_class) (vlib_main_t * vm,
   vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b = bufs;
   struct ibv_send_wr wr[VLIB_FRAME_SIZE], *w = wr;
   struct ibv_sge sge[VLIB_FRAME_SIZE], *s = sge;
-  int i;
+  int i, ret;
 
   f = from = vlib_frame_vector_args (frame);
   n_left_from = frame->n_vectors;
@@ -155,12 +155,13 @@ VNET_DEVICE_CLASS_TX_FN (rdma_device_class) (vlib_main_t * vm,
   for (i = 0; i < 5; i++)
     {
       rdma_device_output_free (vm, txq);
-      if (0 == ibv_post_send (txq->qp, w, &w))
+      ret = ibv_post_send (txq->qp, w, &w);
+      if (0 == ret)
 	break;
     }
   clib_spinlock_unlock_if_init (&txq->lock);
 
-  n_tx_packets = w == wr ? frame->n_vectors : w - wr;
+  n_tx_packets = 0 == ret ? frame->n_vectors : w - wr;
   n_tx_failed = frame->n_vectors - n_tx_packets;
 
   if (PREDICT_FALSE (n_tx_failed))
-- 
cgit