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

[NET]: Make packet reception network namespace safe

This patch modifies every packet receive function
registered with dev_add_pack() to drop packets if they
are not from the initial network namespace.

This should ensure that the various network stacks do
not receive packets in a anything but the initial network
namespace until the code has been converted and is ready
for them.
Signed-off-by: default avatarEric W. Biederman <ebiederm@xmission.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 6d34b1c2
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <linux/blkdev.h> #include <linux/blkdev.h>
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <linux/moduleparam.h> #include <linux/moduleparam.h>
#include <net/net_namespace.h>
#include <asm/unaligned.h> #include <asm/unaligned.h>
#include "aoe.h" #include "aoe.h"
...@@ -114,6 +115,9 @@ aoenet_rcv(struct sk_buff *skb, struct net_device *ifp, struct packet_type *pt, ...@@ -114,6 +115,9 @@ aoenet_rcv(struct sk_buff *skb, struct net_device *ifp, struct packet_type *pt,
struct aoe_hdr *h; struct aoe_hdr *h;
u32 n; u32 n;
if (ifp->nd_net != &init_net)
goto exit;
skb = skb_share_check(skb, GFP_ATOMIC); skb = skb_share_check(skb, GFP_ATOMIC);
if (skb == NULL) if (skb == NULL)
return 0; return 0;
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include <linux/ethtool.h> #include <linux/ethtool.h>
#include <linux/if_bonding.h> #include <linux/if_bonding.h>
#include <linux/pkt_sched.h> #include <linux/pkt_sched.h>
#include <net/net_namespace.h>
#include "bonding.h" #include "bonding.h"
#include "bond_3ad.h" #include "bond_3ad.h"
...@@ -2448,6 +2449,9 @@ int bond_3ad_lacpdu_recv(struct sk_buff *skb, struct net_device *dev, struct pac ...@@ -2448,6 +2449,9 @@ int bond_3ad_lacpdu_recv(struct sk_buff *skb, struct net_device *dev, struct pac
struct slave *slave = NULL; struct slave *slave = NULL;
int ret = NET_RX_DROP; int ret = NET_RX_DROP;
if (dev->nd_net != &init_net)
goto out;
if (!(dev->flags & IFF_MASTER)) if (!(dev->flags & IFF_MASTER))
goto out; goto out;
......
...@@ -345,6 +345,9 @@ static int rlb_arp_recv(struct sk_buff *skb, struct net_device *bond_dev, struct ...@@ -345,6 +345,9 @@ static int rlb_arp_recv(struct sk_buff *skb, struct net_device *bond_dev, struct
struct arp_pkt *arp = (struct arp_pkt *)skb->data; struct arp_pkt *arp = (struct arp_pkt *)skb->data;
int res = NET_RX_DROP; int res = NET_RX_DROP;
if (bond_dev->nd_net != &init_net)
goto out;
if (!(bond_dev->flags & IFF_MASTER)) if (!(bond_dev->flags & IFF_MASTER))
goto out; goto out;
......
...@@ -2458,6 +2458,9 @@ static int bond_arp_rcv(struct sk_buff *skb, struct net_device *dev, struct pack ...@@ -2458,6 +2458,9 @@ static int bond_arp_rcv(struct sk_buff *skb, struct net_device *dev, struct pack
unsigned char *arp_ptr; unsigned char *arp_ptr;
u32 sip, tip; u32 sip, tip;
if (dev->nd_net != &init_net)
goto out;
if (!(dev->priv_flags & IFF_BONDING) || !(dev->flags & IFF_MASTER)) if (!(dev->priv_flags & IFF_BONDING) || !(dev->flags & IFF_MASTER))
goto out; goto out;
......
...@@ -173,6 +173,9 @@ static int bpq_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_ty ...@@ -173,6 +173,9 @@ static int bpq_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_ty
struct ethhdr *eth; struct ethhdr *eth;
struct bpqdev *bpq; struct bpqdev *bpq;
if (dev->nd_net != &init_net)
goto drop;
if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL)
return NET_RX_DROP; return NET_RX_DROP;
......
...@@ -389,6 +389,9 @@ static int pppoe_rcv(struct sk_buff *skb, ...@@ -389,6 +389,9 @@ static int pppoe_rcv(struct sk_buff *skb,
if (!(skb = skb_share_check(skb, GFP_ATOMIC))) if (!(skb = skb_share_check(skb, GFP_ATOMIC)))
goto out; goto out;
if (dev->nd_net != &init_net)
goto drop;
if (!pskb_may_pull(skb, sizeof(struct pppoe_hdr))) if (!pskb_may_pull(skb, sizeof(struct pppoe_hdr)))
goto drop; goto drop;
...@@ -418,6 +421,9 @@ static int pppoe_disc_rcv(struct sk_buff *skb, ...@@ -418,6 +421,9 @@ static int pppoe_disc_rcv(struct sk_buff *skb,
struct pppoe_hdr *ph; struct pppoe_hdr *ph;
struct pppox_sock *po; struct pppox_sock *po;
if (dev->nd_net != &init_net)
goto abort;
if (!pskb_may_pull(skb, sizeof(struct pppoe_hdr))) if (!pskb_may_pull(skb, sizeof(struct pppoe_hdr)))
goto abort; goto abort;
......
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
#include <linux/rtnetlink.h> #include <linux/rtnetlink.h>
#include <linux/notifier.h> #include <linux/notifier.h>
#include <linux/hdlc.h> #include <linux/hdlc.h>
#include <net/net_namespace.h>
static const char* version = "HDLC support module revision 1.21"; static const char* version = "HDLC support module revision 1.21";
...@@ -66,6 +67,12 @@ static int hdlc_rcv(struct sk_buff *skb, struct net_device *dev, ...@@ -66,6 +67,12 @@ static int hdlc_rcv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *p, struct net_device *orig_dev) struct packet_type *p, struct net_device *orig_dev)
{ {
struct hdlc_device_desc *desc = dev_to_desc(dev); struct hdlc_device_desc *desc = dev_to_desc(dev);
if (dev->nd_net != &init_net) {
kfree_skb(skb);
return 0;
}
if (desc->netif_rx) if (desc->netif_rx)
return desc->netif_rx(skb); return desc->netif_rx(skb);
......
...@@ -91,6 +91,9 @@ static int lapbeth_rcv(struct sk_buff *skb, struct net_device *dev, struct packe ...@@ -91,6 +91,9 @@ static int lapbeth_rcv(struct sk_buff *skb, struct net_device *dev, struct packe
int len, err; int len, err;
struct lapbethdev *lapbeth; struct lapbethdev *lapbeth;
if (dev->nd_net != &init_net)
goto drop;
if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL)
return NET_RX_DROP; return NET_RX_DROP;
......
...@@ -51,6 +51,7 @@ ...@@ -51,6 +51,7 @@
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/rcupdate.h> #include <linux/rcupdate.h>
#include <net/net_namespace.h>
#include <net/syncppp.h> #include <net/syncppp.h>
#include <asm/byteorder.h> #include <asm/byteorder.h>
...@@ -1445,6 +1446,11 @@ static void sppp_print_bytes (u_char *p, u16 len) ...@@ -1445,6 +1446,11 @@ static void sppp_print_bytes (u_char *p, u16 len)
static int sppp_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *p, struct net_device *orig_dev) static int sppp_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *p, struct net_device *orig_dev)
{ {
if (dev->nd_net != &init_net) {
kfree_skb(skb);
return 0;
}
if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL)
return NET_RX_DROP; return NET_RX_DROP;
sppp_input(dev,skb); sppp_input(dev,skb);
......
...@@ -122,6 +122,11 @@ int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev, ...@@ -122,6 +122,11 @@ int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev,
unsigned short vlan_TCI; unsigned short vlan_TCI;
__be16 proto; __be16 proto;
if (dev->nd_net != &init_net) {
kfree_skb(skb);
return -1;
}
if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL)
return -1; return -1;
......
...@@ -713,6 +713,9 @@ static int aarp_rcv(struct sk_buff *skb, struct net_device *dev, ...@@ -713,6 +713,9 @@ static int aarp_rcv(struct sk_buff *skb, struct net_device *dev,
struct atalk_addr sa, *ma, da; struct atalk_addr sa, *ma, da;
struct atalk_iface *ifa; struct atalk_iface *ifa;
if (dev->nd_net != &init_net)
goto out0;
/* We only do Ethernet SNAP AARP. */ /* We only do Ethernet SNAP AARP. */
if (dev->type != ARPHRD_ETHER) if (dev->type != ARPHRD_ETHER)
goto out0; goto out0;
......
...@@ -1403,6 +1403,9 @@ static int atalk_rcv(struct sk_buff *skb, struct net_device *dev, ...@@ -1403,6 +1403,9 @@ static int atalk_rcv(struct sk_buff *skb, struct net_device *dev,
int origlen; int origlen;
__u16 len_hops; __u16 len_hops;
if (dev->nd_net != &init_net)
goto freeit;
/* Don't mangle buffer if shared */ /* Don't mangle buffer if shared */
if (!(skb = skb_share_check(skb, GFP_ATOMIC))) if (!(skb = skb_share_check(skb, GFP_ATOMIC)))
goto out; goto out;
...@@ -1488,6 +1491,9 @@ static int atalk_rcv(struct sk_buff *skb, struct net_device *dev, ...@@ -1488,6 +1491,9 @@ static int atalk_rcv(struct sk_buff *skb, struct net_device *dev,
static int ltalk_rcv(struct sk_buff *skb, struct net_device *dev, static int ltalk_rcv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *pt, struct net_device *orig_dev) struct packet_type *pt, struct net_device *orig_dev)
{ {
if (dev->nd_net != &init_net)
goto freeit;
/* Expand any short form frames */ /* Expand any short form frames */
if (skb_mac_header(skb)[2] == 1) { if (skb_mac_header(skb)[2] == 1) {
struct ddpehdr *ddp; struct ddpehdr *ddp;
......
...@@ -451,6 +451,11 @@ int ax25_kiss_rcv(struct sk_buff *skb, struct net_device *dev, ...@@ -451,6 +451,11 @@ int ax25_kiss_rcv(struct sk_buff *skb, struct net_device *dev,
skb->sk = NULL; /* Initially we don't know who it's for */ skb->sk = NULL; /* Initially we don't know who it's for */
skb->destructor = NULL; /* Who initializes this, dammit?! */ skb->destructor = NULL; /* Who initializes this, dammit?! */
if (dev->nd_net != &init_net) {
kfree_skb(skb);
return 0;
}
if ((*skb->data & 0x0F) != 0) { if ((*skb->data & 0x0F) != 0) {
kfree_skb(skb); /* Not a KISS data frame */ kfree_skb(skb); /* Not a KISS data frame */
return 0; return 0;
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <linux/netfilter_bridge.h> #include <linux/netfilter_bridge.h>
#include <linux/etherdevice.h> #include <linux/etherdevice.h>
#include <linux/llc.h> #include <linux/llc.h>
#include <net/net_namespace.h>
#include <net/llc.h> #include <net/llc.h>
#include <net/llc_pdu.h> #include <net/llc_pdu.h>
#include <asm/unaligned.h> #include <asm/unaligned.h>
...@@ -141,6 +142,9 @@ int br_stp_rcv(struct sk_buff *skb, struct net_device *dev, ...@@ -141,6 +142,9 @@ int br_stp_rcv(struct sk_buff *skb, struct net_device *dev,
struct net_bridge *br; struct net_bridge *br;
const unsigned char *buf; const unsigned char *buf;
if (dev->nd_net != &init_net)
goto err;
if (!p) if (!p)
goto err; goto err;
......
...@@ -584,6 +584,9 @@ int dn_route_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type ...@@ -584,6 +584,9 @@ int dn_route_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type
struct dn_dev *dn = (struct dn_dev *)dev->dn_ptr; struct dn_dev *dn = (struct dn_dev *)dev->dn_ptr;
unsigned char padlen = 0; unsigned char padlen = 0;
if (dev->nd_net != &init_net)
goto dump_it;
if (dn == NULL) if (dn == NULL)
goto dump_it; goto dump_it;
......
...@@ -1065,6 +1065,9 @@ static int econet_rcv(struct sk_buff *skb, struct net_device *dev, struct packet ...@@ -1065,6 +1065,9 @@ static int econet_rcv(struct sk_buff *skb, struct net_device *dev, struct packet
struct sock *sk; struct sock *sk;
struct ec_device *edev = dev->ec_ptr; struct ec_device *edev = dev->ec_ptr;
if (dev->nd_net != &init_net)
goto drop;
if (skb->pkt_type == PACKET_OTHERHOST) if (skb->pkt_type == PACKET_OTHERHOST)
goto drop; goto drop;
......
...@@ -932,6 +932,9 @@ static int arp_rcv(struct sk_buff *skb, struct net_device *dev, ...@@ -932,6 +932,9 @@ static int arp_rcv(struct sk_buff *skb, struct net_device *dev,
{ {
struct arphdr *arp; struct arphdr *arp;
if (dev->nd_net != &init_net)
goto freeskb;
/* ARP header, plus 2 device addresses, plus 2 IP addresses. */ /* ARP header, plus 2 device addresses, plus 2 IP addresses. */
if (!pskb_may_pull(skb, (sizeof(struct arphdr) + if (!pskb_may_pull(skb, (sizeof(struct arphdr) +
(2 * dev->addr_len) + (2 * dev->addr_len) +
......
...@@ -382,6 +382,9 @@ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, ...@@ -382,6 +382,9 @@ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt,
struct iphdr *iph; struct iphdr *iph;
u32 len; u32 len;
if (dev->nd_net != &init_net)
goto drop;
/* When the interface is in promisc. mode, drop all the crap /* When the interface is in promisc. mode, drop all the crap
* that it receives, do not try to analyse it. * that it receives, do not try to analyse it.
*/ */
......
...@@ -426,6 +426,9 @@ ic_rarp_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt ...@@ -426,6 +426,9 @@ ic_rarp_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
unsigned char *sha, *tha; /* s for "source", t for "target" */ unsigned char *sha, *tha; /* s for "source", t for "target" */
struct ic_device *d; struct ic_device *d;
if (dev->nd_net != &init_net)
goto drop;
if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL)
return NET_RX_DROP; return NET_RX_DROP;
...@@ -835,6 +838,9 @@ static int __init ic_bootp_recv(struct sk_buff *skb, struct net_device *dev, str ...@@ -835,6 +838,9 @@ static int __init ic_bootp_recv(struct sk_buff *skb, struct net_device *dev, str
struct ic_device *d; struct ic_device *d;
int len, ext_len; int len, ext_len;
if (dev->nd_net != &init_net)
goto drop;
/* Perform verifications before taking the lock. */ /* Perform verifications before taking the lock. */
if (skb->pkt_type == PACKET_OTHERHOST) if (skb->pkt_type == PACKET_OTHERHOST)
goto drop; goto drop;
......
...@@ -61,6 +61,11 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt ...@@ -61,6 +61,11 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
u32 pkt_len; u32 pkt_len;
struct inet6_dev *idev; struct inet6_dev *idev;
if (dev->nd_net != &init_net) {
kfree_skb(skb);
return 0;
}
if (skb->pkt_type == PACKET_OTHERHOST) { if (skb->pkt_type == PACKET_OTHERHOST) {
kfree_skb(skb); kfree_skb(skb);
return 0; return 0;
......
...@@ -1647,6 +1647,9 @@ static int ipx_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_ty ...@@ -1647,6 +1647,9 @@ static int ipx_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_ty
u16 ipx_pktsize; u16 ipx_pktsize;
int rc = 0; int rc = 0;
if (dev->nd_net != &init_net)
goto drop;
/* Not ours */ /* Not ours */
if (skb->pkt_type == PACKET_OTHERHOST) if (skb->pkt_type == PACKET_OTHERHOST)
goto drop; goto drop;
......
...@@ -1326,6 +1326,9 @@ int irlap_driver_rcv(struct sk_buff *skb, struct net_device *dev, ...@@ -1326,6 +1326,9 @@ int irlap_driver_rcv(struct sk_buff *skb, struct net_device *dev,
int command; int command;
__u8 control; __u8 control;
if (dev->nd_net != &init_net)
goto out;
/* FIXME: should we get our own field? */ /* FIXME: should we get our own field? */
self = (struct irlap_cb *) dev->atalk_ptr; self = (struct irlap_cb *) dev->atalk_ptr;
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
* See the GNU General Public License for more details. * See the GNU General Public License for more details.
*/ */
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <net/net_namespace.h>
#include <net/llc.h> #include <net/llc.h>
#include <net/llc_pdu.h> #include <net/llc_pdu.h>
#include <net/llc_sap.h> #include <net/llc_sap.h>
...@@ -145,6 +146,9 @@ int llc_rcv(struct sk_buff *skb, struct net_device *dev, ...@@ -145,6 +146,9 @@ int llc_rcv(struct sk_buff *skb, struct net_device *dev,
int (*rcv)(struct sk_buff *, struct net_device *, int (*rcv)(struct sk_buff *, struct net_device *,
struct packet_type *, struct net_device *); struct packet_type *, struct net_device *);
if (dev->nd_net != &init_net)
goto drop;
/* /*
* When the interface is in promisc. mode, drop all the crap that it * When the interface is in promisc. mode, drop all the crap that it
* receives, do not try to analyse it. * receives, do not try to analyse it.
......
...@@ -252,6 +252,9 @@ static int packet_rcv_spkt(struct sk_buff *skb, struct net_device *dev, struct ...@@ -252,6 +252,9 @@ static int packet_rcv_spkt(struct sk_buff *skb, struct net_device *dev, struct
struct sock *sk; struct sock *sk;
struct sockaddr_pkt *spkt; struct sockaddr_pkt *spkt;
if (dev->nd_net != &init_net)
goto out;
/* /*
* When we registered the protocol we saved the socket in the data * When we registered the protocol we saved the socket in the data
* field for just this event. * field for just this event.
...@@ -452,6 +455,9 @@ static int packet_rcv(struct sk_buff *skb, struct net_device *dev, struct packet ...@@ -452,6 +455,9 @@ static int packet_rcv(struct sk_buff *skb, struct net_device *dev, struct packet
int skb_len = skb->len; int skb_len = skb->len;
unsigned int snaplen, res; unsigned int snaplen, res;
if (dev->nd_net != &init_net)
goto drop;
if (skb->pkt_type == PACKET_LOOPBACK) if (skb->pkt_type == PACKET_LOOPBACK)
goto drop; goto drop;
...@@ -568,6 +574,9 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, struct packe ...@@ -568,6 +574,9 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, struct packe
struct sk_buff *copy_skb = NULL; struct sk_buff *copy_skb = NULL;
struct timeval tv; struct timeval tv;
if (dev->nd_net != &init_net)
goto drop;
if (skb->pkt_type == PACKET_LOOPBACK) if (skb->pkt_type == PACKET_LOOPBACK)
goto drop; goto drop;
......
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
#include <net/tipc/tipc_bearer.h> #include <net/tipc/tipc_bearer.h>
#include <net/tipc/tipc_msg.h> #include <net/tipc/tipc_msg.h>
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <net/net_namespace.h>
#define MAX_ETH_BEARERS 2 #define MAX_ETH_BEARERS 2
#define ETH_LINK_PRIORITY TIPC_DEF_LINK_PRI #define ETH_LINK_PRIORITY TIPC_DEF_LINK_PRI
...@@ -100,6 +101,11 @@ static int recv_msg(struct sk_buff *buf, struct net_device *dev, ...@@ -100,6 +101,11 @@ static int recv_msg(struct sk_buff *buf, struct net_device *dev,
struct eth_bearer *eb_ptr = (struct eth_bearer *)pt->af_packet_priv; struct eth_bearer *eb_ptr = (struct eth_bearer *)pt->af_packet_priv;
u32 size; u32 size;
if (dev->nd_net != &init_net) {
kfree_skb(buf);
return 0;
}
if (likely(eb_ptr->bearer)) { if (likely(eb_ptr->bearer)) {
if (likely(buf->pkt_type <= PACKET_BROADCAST)) { if (likely(buf->pkt_type <= PACKET_BROADCAST)) {
size = msg_size((struct tipc_msg *)buf->data); size = msg_size((struct tipc_msg *)buf->data);
......
...@@ -95,6 +95,9 @@ int x25_lapb_receive_frame(struct sk_buff *skb, struct net_device *dev, ...@@ -95,6 +95,9 @@ int x25_lapb_receive_frame(struct sk_buff *skb, struct net_device *dev,
struct sk_buff *nskb; struct sk_buff *nskb;
struct x25_neigh *nb; struct x25_neigh *nb;
if (dev->nd_net != &init_net)
goto drop;
nskb = skb_copy(skb, GFP_ATOMIC); nskb = skb_copy(skb, GFP_ATOMIC);
if (!nskb) if (!nskb)
goto drop; goto drop;
......
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