From: fuzhantao <[email protected]>

classifier_destroy() didn't postpone destroying subtables enough.

Signed-off-by: Ben Pfaff <[email protected]>
---
I need a Signed-off-by from fuzhantao.

 lib/classifier.c | 24 ++++++++++++++++--------
 1 file changed, 16 insertions(+), 8 deletions(-)

diff --git a/lib/classifier.c b/lib/classifier.c
index edb40c89c608..595d2fdf54c3 100644
--- a/lib/classifier.c
+++ b/lib/classifier.c
@@ -1468,6 +1468,19 @@ miniflow_get_map_in_range(const struct miniflow 
*miniflow, uint8_t start,
     return map;
 }
 
+static void
+subtable_destroy_cb(struct cls_subtable *subtable)
+{
+    int i;
+
+    for (i = 0; i < subtable->n_indices; i++) {
+        ccmap_destroy(&subtable->indices[i]);
+    }
+    cmap_destroy(&subtable->rules);
+
+    ovsrcu_postpone(free, subtable);
+}
+
 /* The new subtable will be visible to the readers only after this. */
 static struct cls_subtable *
 insert_subtable(struct classifier *cls, const struct minimask *mask)
@@ -1530,12 +1543,11 @@ insert_subtable(struct classifier *cls, const struct 
minimask *mask)
     return subtable;
 }
 
-/* RCU readers may still access the subtable before it is actually freed. */
+/* RCU readers may still access the subtable before it is actually freed.
+ * double postpone for subtable to avoid use-after-free. */
 static void
 destroy_subtable(struct classifier *cls, struct cls_subtable *subtable)
 {
-    int i;
-
     pvector_remove(&cls->subtables, subtable);
     cmap_remove(&cls->subtables_map, &subtable->cmap_node,
                 minimask_hash(&subtable->mask, 0));
@@ -1545,11 +1557,7 @@ destroy_subtable(struct classifier *cls, struct 
cls_subtable *subtable)
     ovs_assert(cmap_is_empty(&subtable->rules));
     ovs_assert(rculist_is_empty(&subtable->rules_list));
 
-    for (i = 0; i < subtable->n_indices; i++) {
-        ccmap_destroy(&subtable->indices[i]);
-    }
-    cmap_destroy(&subtable->rules);
-    ovsrcu_postpone(free, subtable);
+    ovsrcu_postpone(subtable_destroy_cb, subtable);
 }
 
 static unsigned int be_get_bit_at(const ovs_be32 value[], unsigned int ofs);
-- 
2.20.1

_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to