From: Eric W. Biederman <ebiederm@xmission.com> - unquoted
Every user of the network device notifiers is either a protocol
stack or a pseudo device. If a protocol stack that does not have
support for multiple network namespaces receives an event for a
device that is not in the initial network namespace it quite possibly
can get confused and do the wrong thing.
To avoid problems until all of the protocol stacks are converted
this patch modifies all netdev event handlers to ignore events on
devices that are not in the initial network namespace.
As the rest of the code is made network namespace aware these
checks can be removed.
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
---
arch/ia64/hp/sim/simeth.c | 3 +++
drivers/net/bonding/bond_main.c | 3 +++
drivers/net/hamradio/bpqether.c | 3 +++
drivers/net/pppoe.c | 3 +++
drivers/net/wan/dlci.c | 3 +++
drivers/net/wan/hdlc.c | 3 +++
drivers/net/wan/lapbether.c | 3 +++
net/8021q/vlan.c | 4 ++++
net/appletalk/aarp.c | 3 +++
net/appletalk/ddp.c | 3 +++
net/atm/clip.c | 3 +++
net/atm/mpc.c | 4 ++++
net/ax25/af_ax25.c | 3 +++
net/bridge/br_notify.c | 4 ++++
net/core/dst.c | 4 ++++
net/core/fib_rules.c | 4 ++++
net/core/pktgen.c | 3 +++
net/core/rtnetlink.c | 4 ++++
net/decnet/af_decnet.c | 3 +++
net/econet/af_econet.c | 3 +++
net/ipv4/arp.c | 3 +++
net/ipv4/devinet.c | 3 +++
net/ipv4/fib_frontend.c | 3 +++
net/ipv4/ipmr.c | 7 ++++++-
net/ipv4/multipath_drr.c | 3 +++
net/ipv4/netfilter/ip_queue.c | 3 +++
net/ipv4/netfilter/ipt_MASQUERADE.c | 3 +++
net/ipv6/addrconf.c | 3 +++
net/ipv6/ndisc.c | 3 +++
net/ipv6/netfilter/ip6_queue.c | 3 +++
net/ipx/af_ipx.c | 3 +++
net/netfilter/nfnetlink_queue.c | 3 +++
net/netrom/af_netrom.c | 3 +++
net/packet/af_packet.c | 3 +++
net/rose/af_rose.c | 3 +++
net/tipc/eth_media.c | 3 +++
net/wanrouter/af_wanpipe.c | 3 +++
net/x25/af_x25.c | 3 +++
net/xfrm/xfrm_policy.c | 5 +++++
security/selinux/netif.c | 3 +++
40 files changed, 131 insertions(+), 1 deletions(-)
diff --git a/arch/ia64/hp/sim/simeth.c b/arch/ia64/hp/sim/simeth.c
index 424e925..1cbaa9e 100644
--- a/arch/ia64/hp/sim/simeth.c
+++ b/arch/ia64/hp/sim/simeth.c
@@ -300,6 +300,9 @@ simeth_device_event(struct notifier_block *this,unsigned long event, void *ptr)
return NOTIFY_DONE;
}
+ if (!net_eq(dev->nd_net, init_net()))
+ return NOTIFY_DONE;
+
if ( event != NETDEV_UP && event != NETDEV_DOWN ) return NOTIFY_DONE;
/*
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 9c70568..3e04f58 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -3325,6 +3325,9 @@ static int bond_netdev_event(struct notifier_block *this, unsigned long event, v
{
struct net_device *event_dev = (struct net_device *)ptr;
+ if (!net_eq(event_dev->nd_net, init_net()))
+ return NOTIFY_DONE;
+
dprintk("event_dev: %s, event: %lx\n",
(event_dev ? event_dev->name : "None"),
event);
diff --git a/drivers/net/hamradio/bpqether.c b/drivers/net/hamradio/bpqether.c
index c513e90..8826a96 100644
--- a/drivers/net/hamradio/bpqether.c
+++ b/drivers/net/hamradio/bpqether.c
@@ -564,6 +564,9 @@ static int bpq_device_event(struct notifier_block *this,unsigned long event, voi
{
struct net_device *dev = (struct net_device *)ptr;
+ if (!net_eq(dev->nd_net, init_net()))
+ return NOTIFY_DONE;
+
if (!dev_is_ethdev(dev))
return NOTIFY_DONE;
diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c
index caf8ca3..3618862 100644
--- a/drivers/net/pppoe.c
+++ b/drivers/net/pppoe.c
@@ -299,6 +299,9 @@ static int pppoe_device_event(struct notifier_block *this,
{
struct net_device *dev = (struct net_device *) ptr;
+ if (!net_eq(dev->nd_net, init_net()))
+ return NOTIFY_DONE;
+
/* Only look at sockets that are using this specific device. */
switch (event) {
case NETDEV_CHANGEMTU:
diff --git a/drivers/net/wan/dlci.c b/drivers/net/wan/dlci.c
index 7369875..f826494 100644
--- a/drivers/net/wan/dlci.c
+++ b/drivers/net/wan/dlci.c
@@ -513,6 +513,9 @@ static int dlci_dev_event(struct notifier_block *unused,
{
struct net_device *dev = (struct net_device *) ptr;
+ if (!net_eq(dev->nd_net, init_net()))
+ return NOTIFY_DONE;
+
if (event == NETDEV_UNREGISTER) {
struct dlci_local *dlp;
diff --git a/drivers/net/wan/hdlc.c b/drivers/net/wan/hdlc.c
index f3bf160..e56e0a1 100644
--- a/drivers/net/wan/hdlc.c
+++ b/drivers/net/wan/hdlc.c
@@ -110,6 +110,9 @@ static int hdlc_device_event(struct notifier_block *this, unsigned long event,
unsigned long flags;
int on;
+ if (!net_eq(dev->nd_net, init_net()))
+ return NOTIFY_DONE;
+
if (dev->get_stats != hdlc_get_stats)
return NOTIFY_DONE; /* not an HDLC device */
diff --git a/drivers/net/wan/lapbether.c b/drivers/net/wan/lapbether.c
index c1de21e..a3560a9 100644
--- a/drivers/net/wan/lapbether.c
+++ b/drivers/net/wan/lapbether.c
@@ -395,6 +395,9 @@ static int lapbeth_device_event(struct notifier_block *this,
struct lapbethdev *lapbeth;
struct net_device *dev = ptr;
+ if (!net_eq(dev->nd_net, init_net()))
+ return NOTIFY_DONE;
+
if (!dev_is_ethdev(dev))
return NOTIFY_DONE;
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index 18fcb9f..f80cfdd 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -31,6 +31,7 @@
#include <net/arp.h>
#include <linux/rtnetlink.h>
#include <linux/notifier.h>
+#include <net/net_namespace.h>
#include <linux/if_vlan.h>
#include "vlan.h"
@@ -595,6 +596,9 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
int i, flgs;
struct net_device *vlandev;
+ if (!net_eq(dev->nd_net, init_net()))
+ return NOTIFY_DONE;
+
if (!grp)
goto out;
diff --git a/net/appletalk/aarp.c b/net/appletalk/aarp.c
index 85c4dbc..6fd58a6 100644
--- a/net/appletalk/aarp.c
+++ b/net/appletalk/aarp.c
@@ -327,6 +327,9 @@ static int aarp_device_event(struct notifier_block *this, unsigned long event,
struct net_device *dev = ptr;
int ct;
+ if (!net_eq(dev->nd_net, init_net()))
+ return NOTIFY_DONE;
+
if (event == NETDEV_DOWN) {
write_lock_bh(&aarp_lock);
diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c
index f4ff8aa..61f36b1 100644
--- a/net/appletalk/ddp.c
+++ b/net/appletalk/ddp.c
@@ -649,6 +649,9 @@ static int ddp_device_event(struct notifier_block *this, unsigned long event,
{
struct net_device *dev = ptr;
+ if (!net_eq(dev->nd_net, init_net()))
+ return NOTIFY_DONE;
+
if (event == NETDEV_DOWN)
/* Discard any use of this */
atalk_dev_down(dev);
diff --git a/net/atm/clip.c b/net/atm/clip.c
index 5f8a1d2..7d150c2 100644
--- a/net/atm/clip.c
+++ b/net/atm/clip.c
@@ -629,6 +629,9 @@ static int clip_device_event(struct notifier_block *this, unsigned long event,
{
struct net_device *dev = arg;
+ if (!net_eq(dev->nd_net, init_net()))
+ return NOTIFY_DONE;
+
if (event == NETDEV_UNREGISTER) {
neigh_ifdown(&clip_tbl, dev);
return NOTIFY_DONE;
diff --git a/net/atm/mpc.c b/net/atm/mpc.c
index c18f737..4fdb1af 100644
--- a/net/atm/mpc.c
+++ b/net/atm/mpc.c
@@ -953,6 +953,10 @@ static int mpoa_event_listener(struct notifier_block *mpoa_notifier, unsigned lo
struct lec_priv *priv;
dev = (struct net_device *)dev_ptr;
+
+ if (!net_eq(dev->nd_net, init_net()))
+ return NOTIFY_DONE;
+
if (dev->name == NULL || strncmp(dev->name, "lec", 3))
return NOTIFY_DONE; /* we are only interested in lec:s */
diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
index cdbf3f6..8c187a6 100644
--- a/net/ax25/af_ax25.c
+++ b/net/ax25/af_ax25.c
@@ -105,6 +105,9 @@ static int ax25_device_event(struct notifier_block *this, unsigned long event,
{
struct net_device *dev = (struct net_device *)ptr;
+ if (!net_eq(dev->nd_net, init_net()))
+ return NOTIFY_DONE;
+
/* Reject non AX.25 devices */
if (dev->type != ARPHRD_AX25)
return NOTIFY_DONE;
diff --git a/net/bridge/br_notify.c b/net/bridge/br_notify.c
index 2027849..0d56bc2 100644
--- a/net/bridge/br_notify.c
+++ b/net/bridge/br_notify.c
@@ -15,6 +15,7 @@
#include <linux/kernel.h>
#include <linux/rtnetlink.h>
+#include <net/net_namespace.h>
#include "br_private.h"
@@ -36,6 +37,9 @@ static int br_device_event(struct notifier_block *unused, unsigned long event, v
struct net_bridge_port *p = dev->br_port;
struct net_bridge *br;
+ if (!net_eq(dev->nd_net, init_net()))
+ return NOTIFY_DONE;
+
/* not a port of a bridge */
if (p == NULL)
return NOTIFY_DONE;
diff --git a/net/core/dst.c b/net/core/dst.c
index 836ec66..8c4a272 100644
--- a/net/core/dst.c
+++ b/net/core/dst.c
@@ -16,6 +16,7 @@
#include <linux/skbuff.h>
#include <linux/string.h>
#include <linux/types.h>
+#include <net/net_namespace.h>
#include <net/dst.h>
@@ -256,6 +257,9 @@ static int dst_dev_event(struct notifier_block *this, unsigned long event, void
struct net_device *dev = ptr;
struct dst_entry *dst;
+ if (!net_eq(dev->nd_net, init_net()))
+ return NOTIFY_DONE;
+
switch (event) {
case NETDEV_UNREGISTER:
case NETDEV_DOWN:
diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c
index 1df6cd4..ffc31c1 10064
...