forked from Minki/linux
net: Potential null skb->dev dereference
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>
This commit is contained in:
parent
54d259d474
commit
0641e4fbf2
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
@ -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;
|
||||
|
@ -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;
|
||||
@ -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++;
|
||||
|
Loading…
Reference in New Issue
Block a user