From patchwork Tue Feb 17 19:23:10 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pravin B Shelar X-Patchwork-Id: 440695 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3EE5914010F for ; Wed, 18 Feb 2015 06:23:41 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753797AbbBQTXh (ORCPT ); Tue, 17 Feb 2015 14:23:37 -0500 Received: from na3sys009aog109.obsmtp.com ([74.125.149.201]:38621 "HELO na3sys009aog109.obsmtp.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with SMTP id S1753114AbbBQTXg (ORCPT ); Tue, 17 Feb 2015 14:23:36 -0500 Received: from mail-pd0-f173.google.com ([209.85.192.173]) (using TLSv1) by na3sys009aob109.postini.com ([74.125.148.12]) with SMTP ID DSNKVOOVN4PxN2DL/llCRTIkDv4Nzhr+JzyN@postini.com; Tue, 17 Feb 2015 11:23:35 PST Received: by mail-pd0-f173.google.com with SMTP id v10so45731847pde.7 for ; Tue, 17 Feb 2015 11:23:35 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=AFF4jOt9nj4EG00usKXC+c+B4HWyTF6BzQHYLRcbB7s=; b=i/1soyiGi4b42FMQpSmgHw36cMg0cW+k3vCLab2YdjeGKso1Ev8ZQMzj9mrvU3RofQ 5NNBUuIAvShWU5g3jE4BPfh8X62w+cvhA/CqA6fW8FmTNgNA8BixPhAyLp6IMft+96ng uR7gBXLEU+P1UbKiMzs8aB+Ln4/Gicofa/Ij0z+aJDnERJh7CYMQ6PDoaQfjg/nLS4ZA UyBCBwLMIiTG8O8hOFuTte4ZgJW0b+vruQTorrOMBzu+4oKX2jtWOd1Ji6MJhLowSypp x15QiT7TEzKqCznGD+v6AGTkjPRVlvGQMAR3J5RiEbfs2jFSJJn+UVfXYOUWaqt2vuEc ztFw== X-Gm-Message-State: ALoCoQlfwh43wZpVZNDIRyqqHBgILIhTkM9L/a9OkqUawSlpopp2KKYVrlWMJzg1mfcG5aCvRqGo2+DHyp222oQ2VLd9nEbR/o3gDvE5m4mHGQi+Td6H/n6oWdo5UeM3jOce/Y3ncC+G1jOoBtbE3X47U0O4ZZGErQ== X-Received: by 10.68.242.163 with SMTP id wr3mr52306956pbc.159.1424201015243; Tue, 17 Feb 2015 11:23:35 -0800 (PST) X-Received: by 10.68.242.163 with SMTP id wr3mr52306940pbc.159.1424201015130; Tue, 17 Feb 2015 11:23:35 -0800 (PST) Received: from localhost ([208.91.2.3]) by mx.google.com with ESMTPSA id n2sm18501108pdo.0.2015.02.17.11.23.34 (version=TLSv1.1 cipher=RC4-SHA bits=128/128); Tue, 17 Feb 2015 11:23:34 -0800 (PST) From: Pravin B Shelar To: davem@davemloft.net Cc: netdev@vger.kernel.org, dev@openvswitch.org, amuller@redhat.com, Pravin B Shelar Subject: [PATCH net] openvswitch: Fix net exit. Date: Tue, 17 Feb 2015 11:23:10 -0800 Message-Id: <1424200990-1558-1-git-send-email-pshelar@nicira.com> X-Mailer: git-send-email 1.7.1 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Open vSwitch allows moving internal vport to different namespace while still connected to the bridge. But when namespace deleted OVS does not detach these vports, that results in dangling pointer to netdevice which causes kernel panic as follows. This issue is fixed by detaching all ovs ports from the deleted namespace at net-exit. BUG: unable to handle kernel NULL pointer dereference at 0000000000000028 IP: [] ovs_vport_locate+0x35/0x80 [openvswitch] Oops: 0000 [#1] SMP Call Trace: [] lookup_vport+0x21/0xd0 [openvswitch] [] ovs_vport_cmd_get+0x59/0xf0 [openvswitch] [] genl_family_rcv_msg+0x1bc/0x3e0 [] genl_rcv_msg+0x79/0xc0 [] netlink_rcv_skb+0xb9/0xe0 [] genl_rcv+0x2c/0x40 [] netlink_unicast+0x12d/0x1c0 [] netlink_sendmsg+0x34a/0x6b0 [] sock_sendmsg+0xa0/0xe0 [] ___sys_sendmsg+0x408/0x420 [] __sys_sendmsg+0x51/0x90 [] SyS_sendmsg+0x12/0x20 [] system_call_fastpath+0x12/0x17 Reported-by: Assaf Muller Fixes: 46df7b81454("openvswitch: Add support for network namespaces.") Signed-off-by: Pravin B Shelar Reviewed-by: Thomas Graf --- net/openvswitch/datapath.c | 45 ++++++++++++++++++++++++++++++++++++++++++- net/openvswitch/vport.h | 2 + 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c index ae5e77c..5bae724 100644 --- a/net/openvswitch/datapath.c +++ b/net/openvswitch/datapath.c @@ -2194,14 +2194,55 @@ static int __net_init ovs_init_net(struct net *net) return 0; } -static void __net_exit ovs_exit_net(struct net *net) +static void __net_exit list_vports_from_net(struct net *net, struct net *dnet, + struct list_head *head) { - struct datapath *dp, *dp_next; struct ovs_net *ovs_net = net_generic(net, ovs_net_id); + struct datapath *dp; + + list_for_each_entry(dp, &ovs_net->dps, list_node) { + int i; + + for (i = 0; i < DP_VPORT_HASH_BUCKETS; i++) { + struct vport *vport; + + hlist_for_each_entry(vport, &dp->ports[i], dp_hash_node) { + struct netdev_vport *netdev_vport; + + if (vport->ops->type != OVS_VPORT_TYPE_INTERNAL) + continue; + + netdev_vport = netdev_vport_priv(vport); + if (dev_net(netdev_vport->dev) == dnet) + list_add(&vport->detach_list, head); + } + } + } +} + +static void __net_exit ovs_exit_net(struct net *dnet) +{ + struct datapath *dp, *dp_next; + struct ovs_net *ovs_net = net_generic(dnet, ovs_net_id); + struct vport *vport, *vport_next; + struct net *net; + LIST_HEAD(head); ovs_lock(); list_for_each_entry_safe(dp, dp_next, &ovs_net->dps, list_node) __dp_destroy(dp); + + rtnl_lock(); + for_each_net(net) + list_vports_from_net(net, dnet, &head); + rtnl_unlock(); + + /* Detach all vports from given namespace. */ + list_for_each_entry_safe(vport, vport_next, &head, detach_list) { + list_del(&vport->detach_list); + ovs_dp_detach_port(vport); + } + ovs_unlock(); cancel_work_sync(&ovs_net->dp_notify_work); diff --git a/net/openvswitch/vport.h b/net/openvswitch/vport.h index f8ae295..bc85331 100644 --- a/net/openvswitch/vport.h +++ b/net/openvswitch/vport.h @@ -103,6 +103,7 @@ struct vport_portids { * @ops: Class structure. * @percpu_stats: Points to per-CPU statistics used and maintained by vport * @err_stats: Points to error statistics used and maintained by vport + * @detach_list: list used for detaching vport in net-exit call. */ struct vport { struct rcu_head rcu; @@ -117,6 +118,7 @@ struct vport { struct pcpu_sw_netstats __percpu *percpu_stats; struct vport_err_stats err_stats; + struct list_head detach_list; }; /**