Hi, yunjian and Ilya, this patch reminds me of the discussion we have in March last year, and during the discussion, you have spotted this thread-safety issue of uuid map. Unfortunately, in that email, you did not reply to the mailist, so I cannot give a link to the email. I attach it as a reference.
I quote it here: " That is an interesting example here... I can't help but notice that this function is typically called from different handler or pmd threads and modified by the main thread while upcalls enabled. And hmap is not a thread-safe structure. I guess, we have another possible problem here. We need to protect at least this hmap and the other one with rw lock or something... Am I right or am I missing something? What else we need to protect? " And this patch fixes exactly the problem you stated. wangyunjian via dev <ovs-dev@openvswitch.org> 于2022年1月8日周六 17:18写道: > Friendly ping. > > > -----Original Message----- > > From: wangyunjian > > Sent: Friday, December 3, 2021 7:25 PM > > To: d...@openvswitch.org; i.maxim...@ovn.org > > Cc: dingxiaoxiong <dingxiaoxi...@huawei.com>; xudingke > > <xudin...@huawei.com>; wangyunjian <wangyunj...@huawei.com>; Justin > > Pettit <jpet...@ovn.org> > > Subject: [ovs-dev] [PATCH] ofproto: fix use-after-free for "ofproto". > > > > When handler threads lookup a "ofproto" and use it, main thread maybe > > remove and free the "ofproto" at the same time. The "ofproto" has not > > been protected well, which can lead to an OVS crash. > > > > This patch fixes this by making the "ofproto" lookup RCU-safe by using > > cmap instead of hmap and moving remove "ofproto" call before > > xlate_txn_commit(). > > > > (gdb) bt > > hmap_next (hmap.h:398) > > seq_wake_waiters (seq.c:326) > > seq_change_protected (seq.c:134) > > seq_change (seq.c:144) > > ofproto_dpif_send_async_msg (ofproto_dpif.c:263) > > process_upcall (ofproto_dpif_upcall.c:1782) > > recv_upcalls (ofproto_dpif_upcall.c:1026) > > udpif_upcall_handler (ofproto/ofproto_dpif_upcall.c:945) > > ovsthread_wrapper (ovs_thread.c:734) > > > > Cc: Justin Pettit <jpet...@ovn.org> > > Fixes: fcb9579be3c7 ("ofproto: Add 'ofproto_uuid' and 'ofp_in_port' to > user > > action cookie.") > > Signed-off-by: Yunjian Wang <wangyunj...@huawei.com> > > --- > > ofproto/ofproto-dpif.c | 12 ++++++------ > > ofproto/ofproto-dpif.h | 2 +- > > 2 files changed, 7 insertions(+), 7 deletions(-) > > > > diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c > > index cba49a99e..aa8d32f81 100644 > > --- a/ofproto/ofproto-dpif.c > > +++ b/ofproto/ofproto-dpif.c > > @@ -216,8 +216,7 @@ static struct hmap all_ofproto_dpifs_by_name = > > > > HMAP_INITIALIZER(&all_ofproto_dpifs_by_name); > > > > /* All existing ofproto_dpif instances, indexed by ->uuid. */ > > -static struct hmap all_ofproto_dpifs_by_uuid = > > - > > HMAP_INITIALIZER(&all_ofproto_dpifs_by_uuid); > > +static struct cmap all_ofproto_dpifs_by_uuid = CMAP_INITIALIZER; > > > > static bool ofproto_use_tnl_push_pop = true; > > static void ofproto_unixctl_init(void); > > @@ -1682,7 +1681,7 @@ construct(struct ofproto *ofproto_) > > hmap_insert(&all_ofproto_dpifs_by_name, > > &ofproto->all_ofproto_dpifs_by_name_node, > > hash_string(ofproto->up.name, 0)); > > - hmap_insert(&all_ofproto_dpifs_by_uuid, > > + cmap_insert(&all_ofproto_dpifs_by_uuid, > > &ofproto->all_ofproto_dpifs_by_uuid_node, > > uuid_hash(&ofproto->uuid)); > > memset(&ofproto->stats, 0, sizeof ofproto->stats); > > @@ -1778,12 +1777,13 @@ destruct(struct ofproto *ofproto_, bool del) > > ofproto->backer->need_revalidate = REV_RECONFIGURE; > > xlate_txn_start(); > > xlate_remove_ofproto(ofproto); > > + cmap_remove(&all_ofproto_dpifs_by_uuid, > > + &ofproto->all_ofproto_dpifs_by_uuid_node, > > + uuid_hash(&ofproto->uuid)); > I guess some comments are needed here, you actually make use of the rcu_synchronize in the xlate_txn_commit to avoid access to the ofproto from other thread through uuid map. > > xlate_txn_commit(); > > > > hmap_remove(&all_ofproto_dpifs_by_name, > > &ofproto->all_ofproto_dpifs_by_name_node); > > - hmap_remove(&all_ofproto_dpifs_by_uuid, > > - &ofproto->all_ofproto_dpifs_by_uuid_node); > > > > OFPROTO_FOR_EACH_TABLE (table, &ofproto->up) { > > CLS_FOR_EACH (rule, up.cr, &table->cls) { > > @@ -5781,7 +5781,7 @@ ofproto_dpif_lookup_by_uuid(const struct uuid > > *uuid) > > { > > struct ofproto_dpif *ofproto; > > > > - HMAP_FOR_EACH_WITH_HASH (ofproto, > > all_ofproto_dpifs_by_uuid_node, > > + CMAP_FOR_EACH_WITH_HASH (ofproto, > > all_ofproto_dpifs_by_uuid_node, > > uuid_hash(uuid), > > &all_ofproto_dpifs_by_uuid) { > > if (uuid_equals(&ofproto->uuid, uuid)) { > > return ofproto; > > diff --git a/ofproto/ofproto-dpif.h b/ofproto/ofproto-dpif.h > > index 191cfcb0d..fba03f2cc 100644 > > --- a/ofproto/ofproto-dpif.h > > +++ b/ofproto/ofproto-dpif.h > > @@ -295,7 +295,7 @@ struct ofproto_dpif { > > struct hmap_node all_ofproto_dpifs_by_name_node; > > > > /* In 'all_ofproto_dpifs_by_uuid'. */ > > - struct hmap_node all_ofproto_dpifs_by_uuid_node; > > + struct cmap_node all_ofproto_dpifs_by_uuid_node; > > > > struct ofproto up; > > struct dpif_backer *backer; > > -- > > 2.27.0 > > _______________________________________________ > dev mailing list > d...@openvswitch.org > https://mail.openvswitch.org/mailman/listinfo/ovs-dev > -- hepeng _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev