Commit e9dc8653 authored by Eric W. Biederman's avatar Eric W. Biederman Committed by David S. Miller

[NET]: Make device event notification network namespace safe

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: default avatarEric W. Biederman <ebiederm@xmission.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent e730c155
......@@ -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;
/*
......
......@@ -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);
......
......@@ -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;
......
......@@ -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:
......
......@@ -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;
......
......@@ -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 */
......
......@@ -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;
......
......@@ -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;
......
......@@ -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);
......
......@@ -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);
......
......@@ -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;
......
......@@ -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 */
......
......@@ -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;
......
......@@ -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;
......
......@@ -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:
......
......@@ -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();
......
......@@ -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.
*/
......
......@@ -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);
......
......@@ -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);
......
......@@ -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. */
......
......@@ -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);
......
......@@ -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) {
......
......@@ -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;
......
......@@ -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;
......
......@@ -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);
......
......@@ -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,
......
......@@ -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) {
......
......@@ -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);
......
......@@ -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);
......
......@@ -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;
......
......@@ -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);
......
......@@ -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;
......
......@@ -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);
......
......@@ -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;
......
......@@ -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 */
......
......@@ -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
......
......@@ -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();
......
......@@ -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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment