From 99620d2c1b01045a652d586da3c46608f7c59eda Mon Sep 17 00:00:00 2001 From: Jesse Gross Date: Thu, 24 Feb 2011 14:07:29 -0800 Subject: [PATCH] datapath: Destroy internal devices before freeing datapath. 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 Acked-by: Ben Pfaff --- datapath/datapath.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/datapath/datapath.c b/datapath/datapath.c index 531afebc..733acad7 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(); -- 2.30.2