Home Home > GIT Browse > SLE12-SP4-AZURE
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2019-02-20 12:35:52 +0100
committerTakashi Iwai <tiwai@suse.de>2019-02-20 12:35:56 +0100
commit6f15474b239da521fba5cb015babad0dd5451139 (patch)
tree638b5c670bc9fc1f8e4974ff3b44f1a120495f40
parente1eeeb69fbd7b699bcbbfc53605018725d936b22 (diff)
openvswitch: Remove padding from packet before L3+ conntrack
processing (bsc#1051510).
-rw-r--r--patches.fixes/openvswitch-Remove-padding-from-packet-before-L3-con.patch103
-rw-r--r--series.conf1
2 files changed, 104 insertions, 0 deletions
diff --git a/patches.fixes/openvswitch-Remove-padding-from-packet-before-L3-con.patch b/patches.fixes/openvswitch-Remove-padding-from-packet-before-L3-con.patch
new file mode 100644
index 0000000000..1dbdf20ad5
--- /dev/null
+++ b/patches.fixes/openvswitch-Remove-padding-from-packet-before-L3-con.patch
@@ -0,0 +1,103 @@
+From 9382fe71c0058465e942a633869629929102843d Mon Sep 17 00:00:00 2001
+From: Ed Swierk <eswierk@skyportsystems.com>
+Date: Wed, 31 Jan 2018 18:48:02 -0800
+Subject: [PATCH] openvswitch: Remove padding from packet before L3+ conntrack processing
+Git-commit: 9382fe71c0058465e942a633869629929102843d
+Patch-mainline: v4.16-rc1
+References: bsc#1051510
+
+IPv4 and IPv6 packets may arrive with lower-layer padding that is not
+included in the L3 length. For example, a short IPv4 packet may have
+up to 6 bytes of padding following the IP payload when received on an
+Ethernet device with a minimum packet length of 64 bytes.
+
+Higher-layer processing functions in netfilter (e.g. nf_ip_checksum(),
+and help() in nf_conntrack_ftp) assume skb->len reflects the length of
+the L3 header and payload, rather than referring back to
+ip_hdr->tot_len or ipv6_hdr->payload_len, and get confused by
+lower-layer padding.
+
+In the normal IPv4 receive path, ip_rcv() trims the packet to
+ip_hdr->tot_len before invoking netfilter hooks. In the IPv6 receive
+path, ip6_rcv() does the same using ipv6_hdr->payload_len. Similarly
+in the br_netfilter receive path, br_validate_ipv4() and
+br_validate_ipv6() trim the packet to the L3 length before invoking
+netfilter hooks.
+
+Currently in the OVS conntrack receive path, ovs_ct_execute() pulls
+the skb to the L3 header but does not trim it to the L3 length before
+calling nf_conntrack_in(NF_INET_PRE_ROUTING). When
+nf_conntrack_proto_tcp encounters a packet with lower-layer padding,
+nf_ip_checksum() fails causing a "nf_ct_tcp: bad TCP checksum" log
+message. While extra zero bytes don't affect the checksum, the length
+in the IP pseudoheader does. That length is based on skb->len, and
+without trimming, it doesn't match the length the sender used when
+computing the checksum.
+
+In ovs_ct_execute(), trim the skb to the L3 length before higher-layer
+processing.
+
+Signed-off-by: Ed Swierk <eswierk@skyportsystems.com>
+Acked-by: Pravin B Shelar <pshelar@ovn.org>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Acked-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ net/openvswitch/conntrack.c | 34 ++++++++++++++++++++++++++++++++++
+ 1 file changed, 34 insertions(+)
+
+diff --git a/net/openvswitch/conntrack.c b/net/openvswitch/conntrack.c
+index 62f36cc938ca..c5904f629091 100644
+--- a/net/openvswitch/conntrack.c
++++ b/net/openvswitch/conntrack.c
+@@ -1098,6 +1098,36 @@ static int ovs_ct_commit(struct net *net, struct sw_flow_key *key,
+ return 0;
+ }
+
++/* Trim the skb to the length specified by the IP/IPv6 header,
++ * removing any trailing lower-layer padding. This prepares the skb
++ * for higher-layer processing that assumes skb->len excludes padding
++ * (such as nf_ip_checksum). The caller needs to pull the skb to the
++ * network header, and ensure ip_hdr/ipv6_hdr points to valid data.
++ */
++static int ovs_skb_network_trim(struct sk_buff *skb)
++{
++ unsigned int len;
++ int err;
++
++ switch (skb->protocol) {
++ case htons(ETH_P_IP):
++ len = ntohs(ip_hdr(skb)->tot_len);
++ break;
++ case htons(ETH_P_IPV6):
++ len = sizeof(struct ipv6hdr)
++ + ntohs(ipv6_hdr(skb)->payload_len);
++ break;
++ default:
++ len = skb->len;
++ }
++
++ err = pskb_trim_rcsum(skb, len);
++ if (err)
++ kfree_skb(skb);
++
++ return err;
++}
++
+ /* Returns 0 on success, -EINPROGRESS if 'skb' is stolen, or other nonzero
+ * value if 'skb' is freed.
+ */
+@@ -1112,6 +1142,10 @@ int ovs_ct_execute(struct net *net, struct sk_buff *skb,
+ nh_ofs = skb_network_offset(skb);
+ skb_pull_rcsum(skb, nh_ofs);
+
++ err = ovs_skb_network_trim(skb);
++ if (err)
++ return err;
++
+ if (key->ip.frag != OVS_FRAG_TYPE_NONE) {
+ err = handle_fragments(net, key, info->zone.id, skb);
+ if (err)
+--
+2.16.4
+
diff --git a/series.conf b/series.conf
index 6d09635e36..49e9545f87 100644
--- a/series.conf
+++ b/series.conf
@@ -13099,6 +13099,7 @@
patches.drivers/net-create-skb_gso_validate_mac_len.patch
patches.drivers/bnx2x-disable-GSO-where-gso_size-is-too-big-for-hard.patch
patches.fixes/tcp_bbr-fix-pacing_gain-to-always-be-unity-when-usin.patch
+ patches.fixes/openvswitch-Remove-padding-from-packet-before-L3-con.patch
patches.suse/rocker-fix-possible-null-pointer-dereference-in-rock.patch
patches.fixes/netfilter-x_tables-fix-pointer-leaks-to-userspace.patch
patches.fixes/netfilter-ipt_CLUSTERIP-fix-out-of-bounds-accesses-i.patch