Skip to content

Commit 2eb5ddc

Browse files
congwanggregkh
authored andcommitted
bonding: validate ip header before check IPPROTO_IGMP
[ Upstream commit 9d1bc24 ] bond_xmit_roundrobin() checks for IGMP packets but it parses the IP header even before checking skb->protocol. We should validate the IP header with pskb_may_pull() before using iph->protocol. Reported-and-tested-by: syzbot+e5be16aa39ad6e755391@syzkaller.appspotmail.com Fixes: a2fd940 ("bonding: fix broken multicast with round-robin mode") Cc: Jay Vosburgh <j.vosburgh@gmail.com> Cc: Veaceslav Falico <vfalico@gmail.com> Cc: Andy Gospodarek <andy@greyhouse.net> Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 364e03f commit 2eb5ddc

1 file changed

Lines changed: 23 additions & 14 deletions

File tree

drivers/net/bonding/bond_main.c

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3714,8 +3714,8 @@ static u32 bond_rr_gen_slave_id(struct bonding *bond)
37143714
static int bond_xmit_roundrobin(struct sk_buff *skb, struct net_device *bond_dev)
37153715
{
37163716
struct bonding *bond = netdev_priv(bond_dev);
3717-
struct iphdr *iph = ip_hdr(skb);
37183717
struct slave *slave;
3718+
int slave_cnt;
37193719
u32 slave_id;
37203720

37213721
/* Start with the curr_active_slave that joined the bond as the
@@ -3724,23 +3724,32 @@ static int bond_xmit_roundrobin(struct sk_buff *skb, struct net_device *bond_dev
37243724
* send the join/membership reports. The curr_active_slave found
37253725
* will send all of this type of traffic.
37263726
*/
3727-
if (iph->protocol == IPPROTO_IGMP && skb->protocol == htons(ETH_P_IP)) {
3728-
slave = rcu_dereference(bond->curr_active_slave);
3729-
if (slave)
3730-
bond_dev_queue_xmit(bond, skb, slave->dev);
3731-
else
3732-
bond_xmit_slave_id(bond, skb, 0);
3733-
} else {
3734-
int slave_cnt = ACCESS_ONCE(bond->slave_cnt);
3727+
if (skb->protocol == htons(ETH_P_IP)) {
3728+
int noff = skb_network_offset(skb);
3729+
struct iphdr *iph;
37353730

3736-
if (likely(slave_cnt)) {
3737-
slave_id = bond_rr_gen_slave_id(bond);
3738-
bond_xmit_slave_id(bond, skb, slave_id % slave_cnt);
3739-
} else {
3740-
bond_tx_drop(bond_dev, skb);
3731+
if (unlikely(!pskb_may_pull(skb, noff + sizeof(*iph))))
3732+
goto non_igmp;
3733+
3734+
iph = ip_hdr(skb);
3735+
if (iph->protocol == IPPROTO_IGMP) {
3736+
slave = rcu_dereference(bond->curr_active_slave);
3737+
if (slave)
3738+
bond_dev_queue_xmit(bond, skb, slave->dev);
3739+
else
3740+
bond_xmit_slave_id(bond, skb, 0);
3741+
return NETDEV_TX_OK;
37413742
}
37423743
}
37433744

3745+
non_igmp:
3746+
slave_cnt = ACCESS_ONCE(bond->slave_cnt);
3747+
if (likely(slave_cnt)) {
3748+
slave_id = bond_rr_gen_slave_id(bond);
3749+
bond_xmit_slave_id(bond, skb, slave_id % slave_cnt);
3750+
} else {
3751+
bond_tx_drop(bond_dev, skb);
3752+
}
37443753
return NETDEV_TX_OK;
37453754
}
37463755

0 commit comments

Comments
 (0)