When destroying vports we account for two types of synchronization mechanisms: RTNL and RCU. However, it is possible to call into network device methods with just a device reference without either of these. These device methods can use the datapath data structures but we don't wait for all of the references to go away before freeing the datapath. The actual wait happens in rtnl_unlock(), so by moving up that call we can avoid the possibility of use after free with internal devices.
Signed-off-by: Jesse Gross <[email protected]> --- datapath/datapath.c | 10 +++++++++- 1 files changed, 9 insertions(+), 1 deletions(-) diff --git a/datapath/datapath.c b/datapath/datapath.c index 531afeb..733acad 100644 --- a/datapath/datapath.c +++ b/datapath/datapath.c @@ -1450,12 +1450,20 @@ static int odp_dp_cmd_del(struct sk_buff *skb, struct genl_info *info) list_del(&dp->list_node); dp_detach_port(get_vport_protected(dp, ODPP_LOCAL)); + /* rtnl_unlock() will wait until all the references to devices that + * are pending unregistration have been dropped. We do it here to + * ensure that any internal devices (which contain DP pointers) are + * fully destroyed before freeing the datapath. + */ + rtnl_unlock(); + call_rcu(&dp->rcu, destroy_dp_rcu); module_put(THIS_MODULE); genl_notify(reply, genl_info_net(info), info->snd_pid, dp_datapath_multicast_group.id, info->nlhdr, GFP_KERNEL); - err = 0; + + return 0; exit_unlock: rtnl_unlock(); -- 1.7.1 _______________________________________________ dev mailing list [email protected] http://openvswitch.org/mailman/listinfo/dev_openvswitch.org
