From: Ben Pfaff Date: Thu, 14 May 2009 18:20:10 +0000 (-0700) Subject: datapath: Fix VLAN-related kernel OOPS on XenServer. X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8615ea2ee7ed1500bd4ba535f4ea3f9c2df43f6f;p=openvswitch datapath: Fix VLAN-related kernel OOPS on XenServer. In deleting internal ports (other than the local port) we were failing to call dp_del_if_hook even though we had called dp_add_if_hook when we added it. This prevented the sysfs kobject from being released and caused the wrong address to be passed to kfree. The former could cause random memory corruption; the latter may be benign since the address was still in the same slab object. --- diff --git a/datapath/datapath.c b/datapath/datapath.c index 25db7d4f..e3e50308 100644 --- a/datapath/datapath.c +++ b/datapath/datapath.c @@ -454,7 +454,7 @@ int dp_del_port(struct net_bridge_port *p, struct list_head *dp_devs) ASSERT_RTNL(); #ifdef SUPPORT_SYSFS - if (!is_dp_dev(p->dev) && dp_del_if_hook) + if (p->port_no != ODPP_LOCAL && dp_del_if_hook) sysfs_remove_link(&p->dp->ifobj, p->dev->name); #endif dp_ifinfo_notify(RTM_DELLINK, p); @@ -471,17 +471,17 @@ int dp_del_port(struct net_bridge_port *p, struct list_head *dp_devs) synchronize_rcu(); free_snat(p); - if (!is_dp_dev(p->dev) && dp_del_if_hook) { + if (is_dp_dev(p->dev)) { + dp_dev_destroy(p->dev); + if (dp_devs) { + struct dp_dev *dp_dev = dp_dev_priv(p->dev); + list_add(&dp_dev->list, dp_devs); + } + } + if (p->port_no != ODPP_LOCAL && dp_del_if_hook) { dp_del_if_hook(p); } else { dev_put(p->dev); - if (is_dp_dev(p->dev)) { - dp_dev_destroy(p->dev); - if (dp_devs) { - struct dp_dev *dp_dev = dp_dev_priv(p->dev); - list_add(&dp_dev->list, dp_devs); - } - } kfree(p); }