| From foo@baz Sat Jan 26 10:22:50 CET 2019 |
| From: Yunjian Wang <wangyunjian@huawei.com> |
| Date: Thu, 17 Jan 2019 09:46:41 +0800 |
| Subject: net: bridge: Fix ethernet header pointer before check skb forwardable |
| |
| From: Yunjian Wang <wangyunjian@huawei.com> |
| |
| [ Upstream commit 28c1382fa28f2e2d9d0d6f25ae879b5af2ecbd03 ] |
| |
| The skb header should be set to ethernet header before using |
| is_skb_forwardable. Because the ethernet header length has been |
| considered in is_skb_forwardable(including dev->hard_header_len |
| length). |
| |
| To reproduce the issue: |
| 1, add 2 ports on linux bridge br using following commands: |
| $ brctl addbr br |
| $ brctl addif br eth0 |
| $ brctl addif br eth1 |
| 2, the MTU of eth0 and eth1 is 1500 |
| 3, send a packet(Data 1480, UDP 8, IP 20, Ethernet 14, VLAN 4) |
| from eth0 to eth1 |
| |
| So the expect result is packet larger than 1500 cannot pass through |
| eth0 and eth1. But currently, the packet passes through success, it |
| means eth1's MTU limit doesn't take effect. |
| |
| Fixes: f6367b4660dd ("bridge: use is_skb_forwardable in forward path") |
| Cc: bridge@lists.linux-foundation.org |
| Cc: Nkolay Aleksandrov <nikolay@cumulusnetworks.com> |
| Cc: Roopa Prabhu <roopa@cumulusnetworks.com> |
| Cc: Stephen Hemminger <stephen@networkplumber.org> |
| Signed-off-by: Yunjian Wang <wangyunjian@huawei.com> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| net/bridge/br_forward.c | 9 ++++----- |
| 1 file changed, 4 insertions(+), 5 deletions(-) |
| |
| --- a/net/bridge/br_forward.c |
| +++ b/net/bridge/br_forward.c |
| @@ -36,10 +36,10 @@ static inline int should_deliver(const s |
| |
| int br_dev_queue_push_xmit(struct net *net, struct sock *sk, struct sk_buff *skb) |
| { |
| + skb_push(skb, ETH_HLEN); |
| if (!is_skb_forwardable(skb->dev, skb)) |
| goto drop; |
| |
| - skb_push(skb, ETH_HLEN); |
| br_drop_fake_rtable(skb); |
| |
| if (skb->ip_summed == CHECKSUM_PARTIAL && |
| @@ -98,12 +98,11 @@ static void __br_forward(const struct ne |
| net = dev_net(indev); |
| } else { |
| if (unlikely(netpoll_tx_running(to->br->dev))) { |
| - if (!is_skb_forwardable(skb->dev, skb)) { |
| + skb_push(skb, ETH_HLEN); |
| + if (!is_skb_forwardable(skb->dev, skb)) |
| kfree_skb(skb); |
| - } else { |
| - skb_push(skb, ETH_HLEN); |
| + else |
| br_netpoll_send_skb(to, skb); |
| - } |
| return; |
| } |
| br_hook = NF_BR_LOCAL_OUT; |