Skip to content

Commit

Permalink
net: Potential null skb->dev dereference
Browse files Browse the repository at this point in the history
When doing "ifenslave -d bond0 eth0", there is chance to get NULL
dereference in netif_receive_skb(), because dev->master suddenly becomes
NULL after we tested it.

We should use ACCESS_ONCE() to avoid this (or rcu_dereference())

Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Eric Dumazet authored and David S. Miller committed Mar 19, 2010
1 parent 54d259d commit 0641e4f
Show file tree
Hide file tree
Showing 3 changed files with 11 additions and 9 deletions.
8 changes: 4 additions & 4 deletions include/linux/netdevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -2059,12 +2059,12 @@ static inline void skb_bond_set_mac_by_master(struct sk_buff *skb,
* duplicates except for 802.3ad ETH_P_SLOW, alb non-mcast/bcast, and
* ARP on active-backup slaves with arp_validate enabled.
*/
static inline int skb_bond_should_drop(struct sk_buff *skb)
static inline int skb_bond_should_drop(struct sk_buff *skb,
struct net_device *master)
{
struct net_device *dev = skb->dev;
struct net_device *master = dev->master;

if (master) {
struct net_device *dev = skb->dev;

if (master->priv_flags & IFF_MASTER_ARPMON)
dev->last_rx = jiffies;

Expand Down
4 changes: 2 additions & 2 deletions net/8021q/vlan_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ int __vlan_hwaccel_rx(struct sk_buff *skb, struct vlan_group *grp,
if (netpoll_rx(skb))
return NET_RX_DROP;

if (skb_bond_should_drop(skb))
if (skb_bond_should_drop(skb, ACCESS_ONCE(skb->dev->master)))
goto drop;

skb->skb_iif = skb->dev->ifindex;
Expand Down Expand Up @@ -83,7 +83,7 @@ vlan_gro_common(struct napi_struct *napi, struct vlan_group *grp,
{
struct sk_buff *p;

if (skb_bond_should_drop(skb))
if (skb_bond_should_drop(skb, ACCESS_ONCE(skb->dev->master)))
goto drop;

skb->skb_iif = skb->dev->ifindex;
Expand Down
8 changes: 5 additions & 3 deletions net/core/dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -2483,6 +2483,7 @@ int netif_receive_skb(struct sk_buff *skb)
{
struct packet_type *ptype, *pt_prev;
struct net_device *orig_dev;
struct net_device *master;
struct net_device *null_or_orig;
struct net_device *null_or_bond;
int ret = NET_RX_DROP;
Expand All @@ -2503,11 +2504,12 @@ int netif_receive_skb(struct sk_buff *skb)

null_or_orig = NULL;
orig_dev = skb->dev;
if (orig_dev->master) {
if (skb_bond_should_drop(skb))
master = ACCESS_ONCE(orig_dev->master);
if (master) {
if (skb_bond_should_drop(skb, master))
null_or_orig = orig_dev; /* deliver only exact match */
else
skb->dev = orig_dev->master;
skb->dev = master;
}

__get_cpu_var(netdev_rx_stat).total++;
Expand Down

0 comments on commit 0641e4f

Please sign in to comment.