Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0641e4fb authored by Eric Dumazet's avatar Eric Dumazet Committed by David S. Miller
Browse files

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: default avatarEric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 54d259d4
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -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)
{
	if (master) {
		struct net_device *dev = skb->dev;
	struct net_device *master = dev->master;

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

+2 −2
Original line number Diff line number Diff line
@@ -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;
+5 −3
Original line number Diff line number Diff line
@@ -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++;