[ovs-dev] [bugfixes 2/6] ofproto-dpif: Fix use-after-free deleting a bridge with active traffic.

Ben Pfaff blp at nicira.com
Wed Sep 4 19:39:44 UTC 2013


When a bridge that has active traffic is deleted, the bridge's ofproto can
be referenced by in-flight "flow_miss"es.  This commit fixes the problem
by destroying "flow_miss"es that reference the ofproto that is being
deleted.

I found the problem by adding and removing a bridge that had active traffic
(via hping3) while running under valgrind.

Signed-off-by: Ben Pfaff <blp at nicira.com>
---
 ofproto/ofproto-dpif-upcall.c |   31 +++++++++++++++++++++++++++++++
 ofproto/ofproto-dpif-upcall.h |    3 +++
 ofproto/ofproto-dpif.c        |    2 ++
 3 files changed, 36 insertions(+)

diff --git a/ofproto/ofproto-dpif-upcall.c b/ofproto/ofproto-dpif-upcall.c
index 22cdf1b..3294d3b 100644
--- a/ofproto/ofproto-dpif-upcall.c
+++ b/ofproto/ofproto-dpif-upcall.c
@@ -347,6 +347,37 @@ flow_miss_batch_destroy(struct flow_miss_batch *fmb)
     free(fmb);
 }
 
+/* Discards any flow miss batches queued up in 'udpif' for 'ofproto' (because
+ * 'ofproto' is being destroyed).
+ *
+ * 'ofproto''s xports must already have been removed, otherwise new flow miss
+ * batches could still end up getting queued. */
+void
+flow_miss_batch_ofproto_destroyed(struct udpif *udpif,
+                                  const struct ofproto_dpif *ofproto)
+{
+    struct flow_miss_batch *fmb, *next_fmb;
+
+    ovs_mutex_lock(&udpif->fmb_mutex);
+    LIST_FOR_EACH_SAFE (fmb, next_fmb, list_node, &udpif->fmbs) {
+        struct flow_miss *miss, *next_miss;
+
+        HMAP_FOR_EACH_SAFE (miss, next_miss, hmap_node, &fmb->misses) {
+            if (miss->ofproto == ofproto) {
+                hmap_remove(&fmb->misses, &miss->hmap_node);
+                miss_destroy(miss);
+            }
+        }
+
+        if (hmap_is_empty(&fmb->misses)) {
+            list_remove(&fmb->list_node);
+            flow_miss_batch_destroy(fmb);
+            udpif->n_fmbs--;
+        }
+    }
+    ovs_mutex_unlock(&udpif->fmb_mutex);
+}
+
 /* Retreives the next drop key which ofproto-dpif needs to process.  The caller
  * is responsible for destroying it with drop_key_destroy(). */
 struct drop_key *
diff --git a/ofproto/ofproto-dpif-upcall.h b/ofproto/ofproto-dpif-upcall.h
index f597672..8e8264e 100644
--- a/ofproto/ofproto-dpif-upcall.h
+++ b/ofproto/ofproto-dpif-upcall.h
@@ -109,6 +109,9 @@ struct flow_miss_batch {
 
 struct flow_miss_batch *flow_miss_batch_next(struct udpif *);
 void flow_miss_batch_destroy(struct flow_miss_batch *);
+
+void flow_miss_batch_ofproto_destroyed(struct udpif *,
+                                       const struct ofproto_dpif *);
 
 /* Drop keys are odp flow keys which have drop flows installed in the kernel.
  * These are datapath flows which have no associated ofproto, if they did we
diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
index 336453c..c8c56bb 100644
--- a/ofproto/ofproto-dpif.c
+++ b/ofproto/ofproto-dpif.c
@@ -1437,6 +1437,8 @@ destruct(struct ofproto *ofproto_)
     xlate_remove_ofproto(ofproto);
     ovs_rwlock_unlock(&xlate_rwlock);
 
+    flow_miss_batch_ofproto_destroyed(ofproto->backer->udpif, ofproto);
+
     hmap_remove(&all_ofproto_dpifs, &ofproto->all_ofproto_dpifs_node);
     complete_operations(ofproto);
 
-- 
1.7.10.4




More information about the dev mailing list