Home Home > GIT Browse
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Kirjanov <dkirjanov@suse.com>2019-05-02 13:49:28 +0200
committerDenis Kirjanov <dkirjanov@suse.com>2019-05-02 13:49:49 +0200
commit7e7d068b03fa6633e5da5851bd1f33d95f29153d (patch)
tree720f33e580f98e082ce9c3d3ccbf6e60aa56f001
parent29883ea215a9a8adcab4fab66b9a5c5e2b1bc690 (diff)
net: Fix vlan untag for bridge and vlan_dev with reorder_hdr
off (git-fixes).
-rw-r--r--patches.fixes/0010-net-Fix-vlan-untag-for-bridge-and-vlan_dev-with-reor.patch124
-rw-r--r--series.conf1
2 files changed, 125 insertions, 0 deletions
diff --git a/patches.fixes/0010-net-Fix-vlan-untag-for-bridge-and-vlan_dev-with-reor.patch b/patches.fixes/0010-net-Fix-vlan-untag-for-bridge-and-vlan_dev-with-reor.patch
new file mode 100644
index 0000000000..f28650adc1
--- /dev/null
+++ b/patches.fixes/0010-net-Fix-vlan-untag-for-bridge-and-vlan_dev-with-reor.patch
@@ -0,0 +1,124 @@
+From: Toshiaki Makita <makita.toshiaki@lab.ntt.co.jp>
+Subject: net: Fix vlan untag for bridge and vlan_dev with
+ reorder_hdr off
+Patch-mainline: v4.16-rc7
+Git-commit: 4bbb3e0e8239f9079bf1fe20b3c0cb598714ae61
+References: git-fixes
+
+When we have a bridge with vlan_filtering on and a vlan device on top of
+it, packets would be corrupted in skb_vlan_untag() called from
+br_dev_xmit().
+
+The problem sits in skb_reorder_vlan_header() used in skb_vlan_untag(),
+which makes use of skb->mac_len. In this function mac_len is meant for
+handling rx path with vlan devices with reorder_header disabled, but in
+tx path mac_len is typically 0 and cannot be used, which is the problem
+in this case.
+
+The current code even does not properly handle rx path (skb_vlan_untag()
+called from __netif_receive_skb_core()) with reorder_header off actually.
+
+In rx path single tag case, it works as follows:
+
+- Before skb_reorder_vlan_header()
+
+ mac_header data
+ v v
+ +-------------------+-------------+------+----
+ | ETH | VLAN | ETH |
+ | ADDRS | TPID | TCI | TYPE |
+ +-------------------+-------------+------+----
+ <-------- mac_len --------->
+ <------------->
+ to be removed
+
+- After skb_reorder_vlan_header()
+
+ mac_header data
+ v v
+ +-------------------+------+----
+ | ETH | ETH |
+ | ADDRS | TYPE |
+ +-------------------+------+----
+ <-------- mac_len --------->
+
+This is ok, but in rx double tag case, it corrupts packets:
+
+- Before skb_reorder_vlan_header()
+
+ mac_header data
+ v v
+ +-------------------+-------------+-------------+------+----
+ | ETH | VLAN | VLAN | ETH |
+ | ADDRS | TPID | TCI | TPID | TCI | TYPE |
+ +-------------------+-------------+-------------+------+----
+ <--------------- mac_len ---------------->
+ <------------->
+ should be removed
+ <--------------------------->
+ actually will be removed
+
+- After skb_reorder_vlan_header()
+
+ mac_header data
+ v v
+ +-------------------+------+----
+ | ETH | ETH |
+ | ADDRS | TYPE |
+ +-------------------+------+----
+ <--------------- mac_len ---------------->
+
+So, two of vlan tags are both removed while only inner one should be
+removed and mac_header (and mac_len) is broken.
+
+skb_vlan_untag() is meant for removing the vlan header at (skb->data - 2),
+so use skb->data and skb->mac_header to calculate the right offset.
+
+Reported-by: Brandon Carpenter <brandon.carpenter@cypherpath.com>
+Fixes: a6e18ff11170 ("vlan: Fix untag operations of stacked vlans with REORDER_HEADER off")
+Signed-off-by: Toshiaki Makita <makita.toshiaki@lab.ntt.co.jp>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Acked-by: Denis Kirjanov <dkirjanov@suse.com>
+---
+ include/uapi/linux/if_ether.h | 1 +
+ net/core/skbuff.c | 7 +++++--
+ 2 files changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/include/uapi/linux/if_ether.h b/include/uapi/linux/if_ether.h
+index 5bc9bfd816b7..8a1e06c2f6c5 100644
+--- a/include/uapi/linux/if_ether.h
++++ b/include/uapi/linux/if_ether.h
+@@ -29,6 +29,7 @@
+ */
+
+ #define ETH_ALEN 6 /* Octets in one ethernet addr */
++#define ETH_TLEN 2 /* Octets in ethernet type field */
+ #define ETH_HLEN 14 /* Total octets in header. */
+ #define ETH_ZLEN 60 /* Min. octets in frame sans FCS */
+ #define ETH_DATA_LEN 1500 /* Max. octets in payload */
+diff --git a/net/core/skbuff.c b/net/core/skbuff.c
+index 8bb8cb4b4381..1997042119b4 100644
+--- a/net/core/skbuff.c
++++ b/net/core/skbuff.c
+@@ -4564,13 +4564,16 @@ EXPORT_SYMBOL_GPL(skb_gso_validate_mac_len);
+
+ static struct sk_buff *skb_reorder_vlan_header(struct sk_buff *skb)
+ {
++ int mac_len;
++
+ if (skb_cow(skb, skb_headroom(skb)) < 0) {
+ kfree_skb(skb);
+ return NULL;
+ }
+
+- memmove(skb->data - ETH_HLEN, skb->data - skb->mac_len - VLAN_HLEN,
+- 2 * ETH_ALEN);
++ mac_len = skb->data - skb_mac_header(skb);
++ memmove(skb_mac_header(skb) + VLAN_HLEN, skb_mac_header(skb),
++ mac_len - VLAN_HLEN - ETH_TLEN);
+ skb->mac_header += VLAN_HLEN;
+ return skb;
+ }
+--
+2.12.3
+
diff --git a/series.conf b/series.conf
index e41f8ee1f4..3ad3af9bec 100644
--- a/series.conf
+++ b/series.conf
@@ -14313,6 +14313,7 @@
patches.drivers/can-cc770-Fix-stalls-on-rt-linux-remove-redundant-IR
patches.drivers/can-cc770-Fix-queue-stall-dropped-RTR-reply
patches.drivers/net-sched-actions-return-explicit-error-when-tunnel_.patch
+ patches.fixes/0010-net-Fix-vlan-untag-for-bridge-and-vlan_dev-with-reor.patch
patches.suse/kcm-lock-lower-socket-in-kcm_attach.patch
patches.suse/net-systemport-Rewrite-__bcm_sysport_tx_reclaim.patch
patches.suse/net-iucv-Free-memory-obtained-by-kzalloc.patch