In ovs 2.1, the unref functions for ipfix and sflow are called in ofproto/ofproto-dpif-upcall.c without the protection of any lock. If the unprotected call of unref function removes the last reference, and at the same time, other thread is trying to ref the same struct, the race could cause abortion of ovs.
To fix this issue, this commit protects the ref and unref functions using the global mutex of the ipfix and sflow modules respectively. Reported-by: Xiao Ma <cumtb_max...@163.com> Signed-off-by: Alex Wang <al...@nicira.com> --- ofproto/ofproto-dpif-ipfix.c | 6 ++++-- ofproto/ofproto-dpif-sflow.c | 14 +++++--------- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/ofproto/ofproto-dpif-ipfix.c b/ofproto/ofproto-dpif-ipfix.c index a9cc73e..8deace8 100644 --- a/ofproto/ofproto-dpif-ipfix.c +++ b/ofproto/ofproto-dpif-ipfix.c @@ -647,11 +647,13 @@ struct dpif_ipfix * dpif_ipfix_ref(const struct dpif_ipfix *di_) { struct dpif_ipfix *di = CONST_CAST(struct dpif_ipfix *, di_); + ovs_mutex_lock(&mutex); if (di) { int orig; atomic_add(&di->ref_cnt, 1, &orig); ovs_assert(orig > 0); } + ovs_mutex_unlock(&mutex); return di; } @@ -689,16 +691,16 @@ dpif_ipfix_unref(struct dpif_ipfix *di) OVS_EXCLUDED(mutex) return; } + ovs_mutex_lock(&mutex); atomic_sub(&di->ref_cnt, 1, &orig); ovs_assert(orig > 0); if (orig == 1) { - ovs_mutex_lock(&mutex); dpif_ipfix_clear(di); dpif_ipfix_bridge_exporter_destroy(&di->bridge_exporter); hmap_destroy(&di->flow_exporter_map); free(di); - ovs_mutex_unlock(&mutex); } + ovs_mutex_unlock(&mutex); } static void diff --git a/ofproto/ofproto-dpif-sflow.c b/ofproto/ofproto-dpif-sflow.c index 158887f..07a5c4b 100644 --- a/ofproto/ofproto-dpif-sflow.c +++ b/ofproto/ofproto-dpif-sflow.c @@ -292,14 +292,6 @@ dpif_sflow_clear__(struct dpif_sflow *ds) OVS_REQUIRES(mutex) ds->probability = 0; } -void -dpif_sflow_clear(struct dpif_sflow *ds) OVS_EXCLUDED(mutex) -{ - ovs_mutex_lock(&mutex); - dpif_sflow_clear__(ds); - ovs_mutex_unlock(&mutex); -} - bool dpif_sflow_is_enabled(const struct dpif_sflow *ds) OVS_EXCLUDED(mutex) { @@ -336,11 +328,13 @@ struct dpif_sflow * dpif_sflow_ref(const struct dpif_sflow *ds_) { struct dpif_sflow *ds = CONST_CAST(struct dpif_sflow *, ds_); + ovs_mutex_lock(&mutex); if (ds) { int orig; atomic_add(&ds->ref_cnt, 1, &orig); ovs_assert(orig > 0); } + ovs_mutex_unlock(&mutex); return ds; } @@ -366,19 +360,21 @@ dpif_sflow_unref(struct dpif_sflow *ds) OVS_EXCLUDED(mutex) return; } + ovs_mutex_lock(&mutex); atomic_sub(&ds->ref_cnt, 1, &orig); ovs_assert(orig > 0); if (orig == 1) { struct dpif_sflow_port *dsp, *next; route_table_unregister(); - dpif_sflow_clear(ds); + dpif_sflow_clear__(ds); HMAP_FOR_EACH_SAFE (dsp, next, hmap_node, &ds->ports) { dpif_sflow_del_port__(ds, dsp); } hmap_destroy(&ds->ports); free(ds); } + ovs_mutex_unlock(&mutex); } static void -- 1.7.9.5 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev