3.16.40-rc1 review patch. If anyone has any objections, please let me know. ------------------ From: Willem de Bruijn <willemb@xxxxxxxxxx> commit 104ba78c98808ae837d1f63aae58c183db5505df upstream. When transmitting on a packet socket with PACKET_VNET_HDR and PACKET_QDISC_BYPASS, validate device support for features requested in vnet_hdr. Drop TSO packets sent to devices that do not support TSO or have the feature disabled. Note that the latter currently do process those packets correctly, regardless of not advertising the feature. Because of SKB_GSO_DODGY, it is not sufficient to test device features with netif_needs_gso. Full validate_xmit_skb is needed. Switch to software checksum for non-TSO packets that request checksum offload if that device feature is unsupported or disabled. Note that similar to the TSO case, device drivers may perform checksum offload correctly even when not advertising it. When switching to software checksum, packets hit skb_checksum_help, which has two BUG_ON checksum not in linear segment. Packet sockets always allocate at least up to csum_start + csum_off + 2 as linear. Tested by running github.com/wdebruij/kerneltools/psock_txring_vnet.c ethtool -K eth0 tso off tx on psock_txring_vnet -d $dst -s $src -i eth0 -l 2000 -n 1 -q -v psock_txring_vnet -d $dst -s $src -i eth0 -l 2000 -n 1 -q -v -N ethtool -K eth0 tx off psock_txring_vnet -d $dst -s $src -i eth0 -l 1000 -n 1 -q -v -G psock_txring_vnet -d $dst -s $src -i eth0 -l 1000 -n 1 -q -v -G -N v2: - add EXPORT_SYMBOL_GPL(validate_xmit_skb_list) Fixes: d346a3fae3ff ("packet: introduce PACKET_QDISC_BYPASS socket option") Signed-off-by: Willem de Bruijn <willemb@xxxxxxxxxx> Acked-by: Eric Dumazet <edumazet@xxxxxxxxxx> Acked-by: Daniel Borkmann <daniel@xxxxxxxxxxxxx> Signed-off-by: David S. Miller <davem@xxxxxxxxxxxxx> [bwh: Backported to 3.16: open-code the necessary checks as we don't have validate_xmit_skb_list()] Signed-off-by: Ben Hutchings <ben@xxxxxxxxxxxxxxx> --- --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -251,9 +251,20 @@ static int packet_direct_xmit(struct sk_ goto drop; features = netif_skb_features(skb); + if (vlan_tx_tag_present(skb) && + !vlan_hw_offload_capable(features, skb->vlan_proto)) + goto drop; + if (netif_needs_gso(skb, features)) + goto drop; if (skb_needs_linearize(skb, features) && __skb_linearize(skb)) goto drop; + if (skb->ip_summed == CHECKSUM_PARTIAL) { + skb_set_transport_header(skb, skb_checksum_start_offset(skb)); + if (!(features & NETIF_F_ALL_CSUM) && + skb_checksum_help(skb)) + goto drop; + } queue_map = skb_get_queue_mapping(skb); txq = netdev_get_tx_queue(dev, queue_map);