When pmd thread interates through all ports for queue loading, the main thread may unreference and 'rcu-free' a port before pmd thread take new reference of it. This could cause pmd thread fail the reference and access freed memory later.
This commit fixes this race by introducing port_try_ref() which uses ovs_refcount_try_ref_rcu(). And the pmd thread will only load the port's queue, if port_try_ref() returns true. Found by inspection. Signed-off-by: Alex Wang <al...@nicira.com> --- lib/dpif-netdev.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c index 2476435..4297db0 100644 --- a/lib/dpif-netdev.c +++ b/lib/dpif-netdev.c @@ -880,6 +880,16 @@ port_ref(struct dp_netdev_port *port) } } +static bool +port_try_ref(struct dp_netdev_port *port) +{ + if (port) { + return ovs_refcount_try_ref_rcu(&port->ref_cnt); + } + + return false; +} + static void port_destroy__(struct dp_netdev_port *port) { @@ -1864,7 +1874,10 @@ pmd_load_queues(struct pmd_thread *f, index = 0; CMAP_FOR_EACH (port, node, &f->dp->ports) { - if (netdev_is_pmd(port->netdev)) { + /* Calls port_try_ref() to prevent the main thread + * from deleting the port. */ + if (netdev_is_pmd(port->netdev) + && port_try_ref(port)) { int i; for (i = 0; i < netdev_n_rxq(port->netdev); i++) { @@ -1878,6 +1891,8 @@ pmd_load_queues(struct pmd_thread *f, } index++; } + /* Unrefs the port_try_ref(). */ + port_unref(port); } } -- 1.7.9.5 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev