From: Jesse Gross Date: Thu, 24 Feb 2011 22:07:29 +0000 (-0800) Subject: datapath: Destroy internal devices before freeing datapath. X-Git-Tag: v1.1.0~209 X-Git-Url: http://git.onelab.eu/?a=commitdiff_plain;h=99620d2c1b01045a652d586da3c46608f7c59eda;p=sliver-openvswitch.git 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 --- diff --git a/datapath/datapath.c b/datapath/datapath.c index 531afebca..733acad72 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();