Path: csiph.com!eternal-september.org!feeder.eternal-september.org!aioe.org!bofh.it!news.nic.it!robomod From: Kamal Mostafa Newsgroups: linux.kernel Subject: [PATCH 3.13.y-ckt 70/78] packet: allow to transmit +4 byte in TX_RING slot for VLAN case Date: Thu, 17 Dec 2015 01:50:03 +0100 Message-ID: References: X-Original-To: linux-kernel@vger.kernel.org, stable@vger.kernel.org, kernel-team@lists.ubuntu.com X-Mailer: git-send-email 1.9.1 X-Extended-Stable: 3.13 Sender: robomod@news.nic.it List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Approved: robomod@news.nic.it Lines: 86 Organization: linux.* mail to news gateway X-Original-Cc: Daniel Borkmann , Ben Greear , Phil Sutter , "David S. Miller" , Kamal Mostafa X-Original-Date: Wed, 16 Dec 2015 16:39:54 -0800 X-Original-Message-ID: <1450312802-4938-71-git-send-email-kamal@canonical.com> X-Original-References: <1450312802-4938-1-git-send-email-kamal@canonical.com> X-Original-Sender: linux-kernel-owner@vger.kernel.org Xref: csiph.com linux.kernel:1293448 3.13.11-ckt32 -stable review patch. If anyone has any objections, please let me know. ------------------ From: Daniel Borkmann commit 52f1454f629fafbfb47ad6727e0837250e1f08c0 upstream. Commit 57f89bfa2140 ("network: Allow af_packet to transmit +4 bytes for VLAN packets.") added the possibility for non-mmaped frames to send extra 4 byte for VLAN header so the MTU increases from 1500 to 1504 byte, for example. Commit cbd89acb9eb2 ("af_packet: fix for sending VLAN frames via packet_mmap") attempted to fix that for the mmap part but was reverted as it caused regressions while using eth_type_trans() on output path. Lets just act analogous to 57f89bfa2140 and add a similar logic to TX_RING. We presume size_max as overcharged with +4 bytes and later on after skb has been built by tpacket_fill_skb() check for ETH_P_8021Q header on packets larger than normal MTU. Can be easily reproduced with a slightly modified trafgen in mmap(2) mode, test cases: { fill(0xff, 12) const16(0x8100) fill(0xff, <1504|1505>) } { fill(0xff, 12) const16(0x0806) fill(0xff, <1500|1501>) } Note that we need to do the test right after tpacket_fill_skb() as sockets can have PACKET_LOSS set where we would not fail but instead just continue to traverse the ring. Reported-by: Mathias Kretschmer Signed-off-by: Daniel Borkmann Cc: Ben Greear Cc: Phil Sutter Tested-by: Mathias Kretschmer Signed-off-by: David S. Miller Signed-off-by: Kamal Mostafa --- net/packet/af_packet.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index b4cb15b..870046d 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -2119,8 +2119,7 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg) if (unlikely(!(dev->flags & IFF_UP))) goto out_put; - reserve = dev->hard_header_len; - + reserve = dev->hard_header_len + VLAN_HLEN; size_max = po->tx_ring.frame_size - (po->tp_hdrlen - sizeof(struct sockaddr_ll)); @@ -2147,8 +2146,19 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg) goto out_status; tp_len = tpacket_fill_skb(po, skb, ph, dev, size_max, proto, - addr, hlen); + addr, hlen); + if (tp_len > dev->mtu + dev->hard_header_len) { + struct ethhdr *ehdr; + /* Earlier code assumed this would be a VLAN pkt, + * double-check this now that we have the actual + * packet in hand. + */ + skb_reset_mac_header(skb); + ehdr = eth_hdr(skb); + if (ehdr->h_proto != htons(ETH_P_8021Q)) + tp_len = -EMSGSIZE; + } if (unlikely(tp_len < 0)) { if (po->tp_loss) { __packet_set_status(po, ph, -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/