Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net, bonding: Disallow vlan+srcmac with XDP

The new vlan+srcmac xmit policy is not implementable with XDP since
in many cases the 802.1Q payload is not present in the packet. This
can be for example due to hardware offload or in the case of veth
due to use of skbuffs internally.

This also fixes the NULL deref with the vlan+srcmac xmit policy
reported by Jonathan Toppins by additionally checking the skb
pointer.

Fixes: a815bde56b15 ("net, bonding: Refactor bond_xmit_hash for use with xdp_buff")
Reported-by: Jonathan Toppins <jtoppins@redhat.com>
Signed-off-by: Jussi Maki <joamaki@gmail.com>
Reviewed-by: Jonathan Toppins <jtoppins@redhat.com>
Link: https://lore.kernel.org/r/20210812145241.12449-1-joamaki@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Jussi Maki and committed by
Jakub Kicinski
39a0876d 876c14ad

+11 -7
+11 -7
drivers/net/bonding/bond_main.c
··· 322 322 switch (BOND_MODE(bond)) { 323 323 case BOND_MODE_ROUNDROBIN: 324 324 case BOND_MODE_ACTIVEBACKUP: 325 + return true; 325 326 case BOND_MODE_8023AD: 326 327 case BOND_MODE_XOR: 327 - return true; 328 + /* vlan+srcmac is not supported with XDP as in most cases the 802.1q 329 + * payload is not in the packet due to hardware offload. 330 + */ 331 + if (bond->params.xmit_policy != BOND_XMIT_POLICY_VLAN_SRCMAC) 332 + return true; 333 + fallthrough; 328 334 default: 329 335 return false; 330 336 } ··· 3750 3744 3751 3745 static u32 bond_vlan_srcmac_hash(struct sk_buff *skb, const void *data, int mhoff, int hlen) 3752 3746 { 3753 - struct ethhdr *mac_hdr; 3754 3747 u32 srcmac_vendor = 0, srcmac_dev = 0; 3755 - u16 vlan; 3748 + struct ethhdr *mac_hdr; 3749 + u16 vlan = 0; 3756 3750 int i; 3757 3751 3758 3752 data = bond_pull_data(skb, data, hlen, mhoff + sizeof(struct ethhdr)); ··· 3766 3760 for (i = 3; i < ETH_ALEN; i++) 3767 3761 srcmac_dev = (srcmac_dev << 8) | mac_hdr->h_source[i]; 3768 3762 3769 - if (!skb_vlan_tag_present(skb)) 3770 - return srcmac_vendor ^ srcmac_dev; 3771 - 3772 - vlan = skb_vlan_tag_get(skb); 3763 + if (skb && skb_vlan_tag_present(skb)) 3764 + vlan = skb_vlan_tag_get(skb); 3773 3765 3774 3766 return vlan ^ srcmac_vendor ^ srcmac_dev; 3775 3767 }