[NET]: Make device event notification network namespace safe
authorEric W. Biederman <ebiederm@xmission.com>
Wed, 12 Sep 2007 11:02:17 +0000 (13:02 +0200)
committerDavid S. Miller <davem@sunset.davemloft.net>
Wed, 10 Oct 2007 23:49:09 +0000 (16:49 -0700)
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>
Signed-off-by: David S. Miller <davem@davemloft.net>
38 files changed:
arch/ia64/hp/sim/simeth.c
drivers/net/bonding/bond_main.c
drivers/net/hamradio/bpqether.c
drivers/net/pppoe.c
drivers/net/wan/dlci.c
drivers/net/wan/hdlc.c
drivers/net/wan/lapbether.c
net/8021q/vlan.c
net/appletalk/aarp.c
net/appletalk/ddp.c
net/atm/clip.c
net/atm/mpc.c
net/ax25/af_ax25.c
net/bridge/br_notify.c
net/core/dst.c
net/core/fib_rules.c
net/core/pktgen.c
net/core/rtnetlink.c
net/decnet/af_decnet.c
net/econet/af_econet.c
net/ipv4/arp.c
net/ipv4/devinet.c
net/ipv4/fib_frontend.c
net/ipv4/ipmr.c
net/ipv4/netfilter/ip_queue.c
net/ipv4/netfilter/ipt_MASQUERADE.c
net/ipv6/addrconf.c
net/ipv6/ndisc.c
net/ipv6/netfilter/ip6_queue.c
net/ipx/af_ipx.c
net/netfilter/nfnetlink_queue.c
net/netrom/af_netrom.c
net/packet/af_packet.c
net/rose/af_rose.c
net/tipc/eth_media.c
net/x25/af_x25.c
net/xfrm/xfrm_policy.c
security/selinux/netif.c

index 4017696ada637d0633998daf750a668336b5189c..08b117e2c54bdade231aa96c29cac4f4ce1bc728 100644 (file)
@@ -294,6 +294,9 @@ simeth_device_event(struct notifier_block *this,unsigned long event, void *ptr)
                return NOTIFY_DONE;
        }
 
+       if (dev->nd_net != &init_net)
+               return NOTIFY_DONE;
+
        if ( event != NETDEV_UP && event != NETDEV_DOWN ) return NOTIFY_DONE;
 
        /*
index e4e5fdc0430b78514794469ff7c63a46988f33cb..cf97d8a6326e21544ebe5d04b186b273fc9335ee 100644 (file)
@@ -3299,6 +3299,9 @@ static int bond_netdev_event(struct notifier_block *this, unsigned long event, v
 {
        struct net_device *event_dev = (struct net_device *)ptr;
 
+       if (event_dev->nd_net != &init_net)
+               return NOTIFY_DONE;
+
        dprintk("event_dev: %s, event: %lx\n",
                (event_dev ? event_dev->name : "None"),
                event);
index 85fb8e7efacf0a2bdbf127a10510f342c01f788c..df09210f7351ff03a681898c3ed10a1e829fea1b 100644 (file)
@@ -563,6 +563,9 @@ static int bpq_device_event(struct notifier_block *this,unsigned long event, voi
 {
        struct net_device *dev = (struct net_device *)ptr;
 
+       if (dev->nd_net != &init_net)
+               return NOTIFY_DONE;
+
        if (!dev_is_ethdev(dev))
                return NOTIFY_DONE;
 
index 60c0e4e17875685dcca9657994023f9b08de99aa..c5c70e4b1d3616a2c7902d7bca22fe7e62d03183 100644 (file)
@@ -301,6 +301,9 @@ static int pppoe_device_event(struct notifier_block *this,
 {
        struct net_device *dev = (struct net_device *) ptr;
 
+       if (dev->nd_net != &init_net)
+               return NOTIFY_DONE;
+
        /* Only look at sockets that are using this specific device. */
        switch (event) {
        case NETDEV_CHANGEMTU:
index 66be20c292b6dcd8855ec84830a15e7850c70baa..61041d5186ac087c79dd3dbe7cd39f318f15aebe 100644 (file)
@@ -513,6 +513,9 @@ static int dlci_dev_event(struct notifier_block *unused,
 {
        struct net_device *dev = (struct net_device *) ptr;
 
+       if (dev->nd_net != &init_net)
+               return NOTIFY_DONE;
+
        if (event == NETDEV_UNREGISTER) {
                struct dlci_local *dlp;
 
index 3b57350eacca7a6e9a671e1fd9e469a83e7f5c55..ee23b91f23d9b860ee2a6b5947e33ec683e20e79 100644 (file)
@@ -109,6 +109,9 @@ static int hdlc_device_event(struct notifier_block *this, unsigned long event,
        unsigned long flags;
        int on;
  
+       if (dev->nd_net != &init_net)
+               return NOTIFY_DONE;
+
        if (dev->get_stats != hdlc_get_stats)
                return NOTIFY_DONE; /* not an HDLC device */
  
index ca8b3c3cb931850c8df19de6de82054e0cf2abde..699b93406dfbe10c83d2d81c2ab5d036b2deb29c 100644 (file)
@@ -394,6 +394,9 @@ static int lapbeth_device_event(struct notifier_block *this,
        struct lapbethdev *lapbeth;
        struct net_device *dev = ptr;
 
+       if (dev->nd_net != &init_net)
+               return NOTIFY_DONE;
+
        if (!dev_is_ethdev(dev))
                return NOTIFY_DONE;
 
index 2a546919d6fbd72e10ea6c01dc908e84eb012aa4..d0d36fdedbe988123e5458c5271351b98ba55498 100644 (file)
@@ -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"
@@ -603,6 +604,9 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
        int i, flgs;
        struct net_device *vlandev;
 
+       if (dev->nd_net != &init_net)
+               return NOTIFY_DONE;
+
        if (!grp)
                goto out;
 
index 9267f4818795d3d469f68b667c8ab0fe9792d592..e9a51a69870ef1b01f983241ac2188b4a3625696 100644 (file)
@@ -333,6 +333,9 @@ static int aarp_device_event(struct notifier_block *this, unsigned long event,
        struct net_device *dev = ptr;
        int ct;
 
+       if (dev->nd_net != &init_net)
+               return NOTIFY_DONE;
+
        if (event == NETDEV_DOWN) {
                write_lock_bh(&aarp_lock);
 
index c1f1367cad483c5eba04f72a4d14938b9e9cdf7c..36fcdbf923c4362e457141a19fe9827b3abd333c 100644 (file)
@@ -649,6 +649,9 @@ static int ddp_device_event(struct notifier_block *this, unsigned long event,
 {
        struct net_device *dev = ptr;
 
+       if (dev->nd_net != &init_net)
+               return NOTIFY_DONE;
+
        if (event == NETDEV_DOWN)
                /* Discard any use of this */
                atalk_dev_down(dev);
index 806ea98567c6fb2bf20d583198e94cfa5d5e4d41..741742f0079715604430491a71de39288e429ff0 100644 (file)
@@ -612,6 +612,9 @@ static int clip_device_event(struct notifier_block *this, unsigned long event,
 {
        struct net_device *dev = arg;
 
+       if (dev->nd_net != &init_net)
+               return NOTIFY_DONE;
+
        if (event == NETDEV_UNREGISTER) {
                neigh_ifdown(&clip_tbl, dev);
                return NOTIFY_DONE;
index 7c85aa551d5e98977e7e9f91a0a6949f31bf9544..0968430a7f58274dfb459737c0eb4db660e3d311 100644 (file)
@@ -956,6 +956,10 @@ static int mpoa_event_listener(struct notifier_block *mpoa_notifier, unsigned lo
        struct lec_priv *priv;
 
        dev = (struct net_device *)dev_ptr;
+
+       if (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 */
 
index def6c42ad165bfde1b82e652d173cb341031e96a..8d13a8bca0e01128cd5a220d9c8f457254858435 100644 (file)
@@ -104,6 +104,9 @@ static int ax25_device_event(struct notifier_block *this, unsigned long event,
 {
        struct net_device *dev = (struct net_device *)ptr;
 
+       if (dev->nd_net != &init_net)
+               return NOTIFY_DONE;
+
        /* Reject non AX.25 devices */
        if (dev->type != ARPHRD_AX25)
                return NOTIFY_DONE;
index c8451d3a070c5f937c72d8409f70e4ca39882e0e..07ac3ae68d8ff089000a78c19024a5d40c3baf9a 100644 (file)
@@ -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 (dev->nd_net != &init_net)
+               return NOTIFY_DONE;
+
        /* not a port of a bridge */
        if (p == NULL)
                return NOTIFY_DONE;
index c6a05879d58cd3c87fb854541bb3c3440d858de9..32267a16e01e0a2999f6f4ea0a444afdf879e293 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/skbuff.h>
 #include <linux/string.h>
 #include <linux/types.h>
+#include <net/net_namespace.h>
 
 #include <net/dst.h>
 
@@ -252,6 +253,9 @@ static int dst_dev_event(struct notifier_block *this, unsigned long event, void
        struct net_device *dev = ptr;
        struct dst_entry *dst;
 
+       if (dev->nd_net != &init_net)
+               return NOTIFY_DONE;
+
        switch (event) {
        case NETDEV_UNREGISTER:
        case NETDEV_DOWN:
index 8c5474e16683aa22971b1bed0390354b728a0f64..9eabe1ae01dc3ca147487558ce322ef4dc028129 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/list.h>
+#include <net/net_namespace.h>
 #include <net/fib_rules.h>
 
 static LIST_HEAD(rules_ops);
@@ -596,6 +597,9 @@ static int fib_rules_event(struct notifier_block *this, unsigned long event,
        struct net_device *dev = ptr;
        struct fib_rules_ops *ops;
 
+       if (dev->nd_net != &init_net)
+               return NOTIFY_DONE;
+
        ASSERT_RTNL();
        rcu_read_lock();
 
index 33d7247fb19d9c951e292243aed49c3e727205bd..d7c30ce095a18ea02077495d6dd928975ec77b9e 100644 (file)
@@ -1975,6 +1975,9 @@ static int pktgen_device_event(struct notifier_block *unused,
 {
        struct net_device *dev = ptr;
 
+       if (dev->nd_net != &init_net)
+               return NOTIFY_DONE;
+
        /* It is OK that we do not hold the group lock right now,
         * as we run under the RTNL lock.
         */
index dca9e80ba574b2fe2a164f9a4fc7ab360d8f3520..41859508bedd8d7455daa4702ea3e1928989bb06 100644 (file)
@@ -1286,6 +1286,10 @@ static void rtnetlink_rcv(struct sock *sk, int len)
 static int rtnetlink_event(struct notifier_block *this, unsigned long event, void *ptr)
 {
        struct net_device *dev = ptr;
+
+       if (dev->nd_net != &init_net)
+               return NOTIFY_DONE;
+
        switch (event) {
        case NETDEV_UNREGISTER:
                rtmsg_ifinfo(RTM_DELLINK, dev, ~0U);
index aca4c4930eb6aaaac698582416026327a20ad175..83398da5d7636bd1455ac464f788c4efd3860a45 100644 (file)
@@ -2089,6 +2089,9 @@ static int dn_device_event(struct notifier_block *this, unsigned long event,
 {
        struct net_device *dev = (struct net_device *)ptr;
 
+       if (dev->nd_net != &init_net)
+               return NOTIFY_DONE;
+
        switch(event) {
                case NETDEV_UP:
                        dn_dev_up(dev);
index 7de3006af206c7feb0dc42de79e2690ee8d9331b..f877f3b5c72529d635c277f3f04055545fbb0690 100644 (file)
@@ -1122,6 +1122,9 @@ static int econet_notifier(struct notifier_block *this, unsigned long msg, void
        struct net_device *dev = (struct net_device *)data;
        struct ec_device *edev;
 
+       if (dev->nd_net != &init_net)
+               return NOTIFY_DONE;
+
        switch (msg) {
        case NETDEV_UNREGISTER:
                /* A device has gone down - kill any data we hold for it. */
index bde129708e2282e310d10e56157a77e389a4a5ea..a11e7a5c1da4312ccebb28adf4e4f4cf93532394 100644 (file)
@@ -1205,6 +1205,9 @@ static int arp_netdev_event(struct notifier_block *this, unsigned long event, vo
 {
        struct net_device *dev = ptr;
 
+       if (dev->nd_net != &init_net)
+               return NOTIFY_DONE;
+
        switch (event) {
        case NETDEV_CHANGEADDR:
                neigh_changeaddr(&arp_tbl, dev);
index 5dbe5803b7d591968a6c1376f37f25692ea1c302..c5eb1a29a5cfbbf1a3e9183fe46511890f549637 100644 (file)
@@ -1051,6 +1051,9 @@ static int inetdev_event(struct notifier_block *this, unsigned long event,
        struct net_device *dev = ptr;
        struct in_device *in_dev = __in_dev_get_rtnl(dev);
 
+       if (dev->nd_net != &init_net)
+               return NOTIFY_DONE;
+
        ASSERT_RTNL();
 
        if (!in_dev) {
index eff6bce453eed8c178f70863a934dc5207c2c17b..cefb55ec3d627166a02efee2181ae75aec998b90 100644 (file)
@@ -860,6 +860,9 @@ static int fib_netdev_event(struct notifier_block *this, unsigned long event, vo
        struct net_device *dev = ptr;
        struct in_device *in_dev = __in_dev_get_rtnl(dev);
 
+       if (dev->nd_net != &init_net)
+               return NOTIFY_DONE;
+
        if (event == NETDEV_UNREGISTER) {
                fib_disable_ip(dev, 2);
                return NOTIFY_DONE;
index 35683e1a42e8e884b3e23f66389740297f6e8c0d..036598835c636ee6de233cbc09f235ea3f4ebe53 100644 (file)
@@ -1083,13 +1083,18 @@ int ipmr_ioctl(struct sock *sk, int cmd, void __user *arg)
 
 static int ipmr_device_event(struct notifier_block *this, unsigned long event, void *ptr)
 {
+       struct net_device *dev = ptr;
        struct vif_device *v;
        int ct;
+
+       if (dev->nd_net != &init_net)
+               return NOTIFY_DONE;
+
        if (event != NETDEV_UNREGISTER)
                return NOTIFY_DONE;
        v=&vif_table[0];
        for (ct=0;ct<maxvif;ct++,v++) {
-               if (v->dev==ptr)
+               if (v->dev==dev)
                        vif_delete(ct);
        }
        return NOTIFY_DONE;
index cb5e61a1d7ab97c52e0b3a5e8b433aae27ba28ab..d91856097f257705a0d883b5bd8ae747b773e663 100644 (file)
@@ -557,6 +557,9 @@ ipq_rcv_dev_event(struct notifier_block *this,
 {
        struct net_device *dev = ptr;
 
+       if (dev->nd_net != &init_net)
+               return NOTIFY_DONE;
+
        /* Drop any packets associated with the downed device */
        if (event == NETDEV_DOWN)
                ipq_dev_drop(dev->ifindex);
index 7c4e4be7c8b3e40de45716346e8abf19022e8eb5..3e0b562b2db704571b044b928e6bea712b9167b7 100644 (file)
@@ -125,6 +125,9 @@ static int masq_device_event(struct notifier_block *this,
 {
        const struct net_device *dev = ptr;
 
+       if (dev->nd_net != &init_net)
+               return NOTIFY_DONE;
+
        if (event == NETDEV_DOWN) {
                /* Device was downed.  Search entire table for
                   conntracks which were associated with that device,
index cd2db728d183d031dd9cfa3232d3555950908c8b..1a6783646520aa341c6d1e6b4d2d552711ed16cd 100644 (file)
@@ -2259,6 +2259,9 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event,
        int run_pending = 0;
        int err;
 
+       if (dev->nd_net != &init_net)
+               return NOTIFY_DONE;
+
        switch(event) {
        case NETDEV_REGISTER:
                if (!idev && dev->mtu >= IPV6_MIN_MTU) {
index 5b596659177cbbd8bd5e6c2db62b803af4ca1817..d2d44dc22f194f80e969aa3ba351cbe5d8fa80d8 100644 (file)
@@ -1525,6 +1525,9 @@ static int ndisc_netdev_event(struct notifier_block *this, unsigned long event,
 {
        struct net_device *dev = ptr;
 
+       if (dev->nd_net != &init_net)
+               return NOTIFY_DONE;
+
        switch (event) {
        case NETDEV_CHANGEADDR:
                neigh_changeaddr(&nd_tbl, dev);
index dfc58fbdb68b346f1a280149c31435ba159f5b67..64536a3ef2f6c2b30205d0080704435d68d6b87e 100644 (file)
@@ -547,6 +547,9 @@ ipq_rcv_dev_event(struct notifier_block *this,
 {
        struct net_device *dev = ptr;
 
+       if (dev->nd_net != &init_net)
+               return NOTIFY_DONE;
+
        /* Drop any packets associated with the downed device */
        if (event == NETDEV_DOWN)
                ipq_dev_drop(dev->ifindex);
index f7b4d383c60958a8daebc38c1188cfacc69254ef..24921f12e9af21863fb7aa7144ae946f541d50a7 100644 (file)
@@ -347,6 +347,9 @@ static int ipxitf_device_event(struct notifier_block *notifier,
        struct net_device *dev = ptr;
        struct ipx_interface *i, *tmp;
 
+       if (dev->nd_net != &init_net)
+               return NOTIFY_DONE;
+
        if (event != NETDEV_DOWN && event != NETDEV_UP)
                goto out;
 
index bb65a38c816c79d88561feaacaa6734df57a6a5e..5a8e8ff766414438ad0a3ea9f3c338b9af3905d5 100644 (file)
@@ -734,6 +734,9 @@ nfqnl_rcv_dev_event(struct notifier_block *this,
 {
        struct net_device *dev = ptr;
 
+       if (dev->nd_net != &init_net)
+               return NOTIFY_DONE;
+
        /* Drop any packets associated with the downed device */
        if (event == NETDEV_DOWN)
                nfqnl_dev_drop(dev->ifindex);
index e969d1bc765c1d673d5c1eba1c1f23b9bed976c4..3a4d479ea64e493c342f9fde022f28adbbeb29c1 100644 (file)
@@ -106,6 +106,9 @@ static int nr_device_event(struct notifier_block *this, unsigned long event, voi
 {
        struct net_device *dev = (struct net_device *)ptr;
 
+       if (dev->nd_net != &init_net)
+               return NOTIFY_DONE;
+
        if (event != NETDEV_DOWN)
                return NOTIFY_DONE;
 
index cae1ee4f2ad68a7f1d13552dd97c5787fc71479c..ad0052524e88574f33bbf6f537cfe4cc584f5215 100644 (file)
@@ -1477,6 +1477,9 @@ static int packet_notifier(struct notifier_block *this, unsigned long msg, void
        struct hlist_node *node;
        struct net_device *dev = data;
 
+       if (dev->nd_net != &init_net)
+               return NOTIFY_DONE;
+
        read_lock(&packet_sklist_lock);
        sk_for_each(sk, node, &packet_sklist) {
                struct packet_sock *po = pkt_sk(sk);
index 67e06ab7f85458e356a567030669f6a5c6d3c9a7..509defe53ee53fb5b49f37c0b2372edfa83cc68b 100644 (file)
@@ -197,6 +197,9 @@ static int rose_device_event(struct notifier_block *this, unsigned long event,
 {
        struct net_device *dev = (struct net_device *)ptr;
 
+       if (dev->nd_net != &init_net)
+               return NOTIFY_DONE;
+
        if (event != NETDEV_DOWN)
                return NOTIFY_DONE;
 
index d2ed23704189d3c59238c20fc4c25510512cb9a6..406f0d26fa812a81d940e48826cbc00017745acc 100644 (file)
@@ -198,6 +198,9 @@ static int recv_notification(struct notifier_block *nb, unsigned long evt,
        struct eth_bearer *eb_ptr = &eth_bearers[0];
        struct eth_bearer *stop = &eth_bearers[MAX_ETH_BEARERS];
 
+       if (dev->nd_net != &init_net)
+               return NOTIFY_DONE;
+
        while ((eb_ptr->dev != dev)) {
                if (++eb_ptr == stop)
                        return NOTIFY_DONE;     /* couldn't find device */
index 2e9931571a4d29f092e07725465ec3a28563981e..fc416f9606a9e259e22f2e641c602107e06b9200 100644 (file)
@@ -191,6 +191,9 @@ static int x25_device_event(struct notifier_block *this, unsigned long event,
        struct net_device *dev = ptr;
        struct x25_neigh *nb;
 
+       if (dev->nd_net != &init_net)
+               return NOTIFY_DONE;
+
        if (dev->type == ARPHRD_X25
 #if defined(CONFIG_LLC) || defined(CONFIG_LLC_MODULE)
         || dev->type == ARPHRD_ETHER
index 36dd31c40f4ab7b0efb69a8a83a0bbe1fa22bbfd..50682d3cd7a97c9bd66d6f5125d5f59cadd3179e 100644 (file)
@@ -2236,6 +2236,11 @@ static void xfrm_policy_unlock_afinfo(struct xfrm_policy_afinfo *afinfo)
 
 static int xfrm_dev_event(struct notifier_block *this, unsigned long event, void *ptr)
 {
+       struct net_device *dev = ptr;
+
+       if (dev->nd_net != &init_net)
+               return NOTIFY_DONE;
+
        switch (event) {
        case NETDEV_DOWN:
                xfrm_flush_bundles();
index b10c34e8a74344f97afce95012a41ebaf7157242..e87ab948104c05a263163752dbbe173c9403f144 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/notifier.h>
 #include <linux/netdevice.h>
 #include <linux/rcupdate.h>
+#include <net/net_namespace.h>
 
 #include "security.h"
 #include "objsec.h"
@@ -234,6 +235,9 @@ static int sel_netif_netdev_notifier_handler(struct notifier_block *this,
 {
        struct net_device *dev = ptr;
 
+       if (dev->nd_net != &init_net)
+               return NOTIFY_DONE;
+
        if (event == NETDEV_DOWN)
                sel_netif_kill(dev);