[SRU][Xenial][PATCH 0/1] skb_warn_bad_offload kernel splat due to CHECKSUM target not compatible with GSO skbs

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

[SRU][Xenial][PATCH 0/1] skb_warn_bad_offload kernel splat due to CHECKSUM target not compatible with GSO skbs

Matthew Ruffell
BugLink: https://bugs.launchpad.net/bugs/1840619

[Impact]

In environments which have CHECKSUM iptables rules set, the following kernel
call trace will be created when a GSO skb is processed by the CHECKSUM target:

WARNING: CPU: 34 PID: 806048 at /build/linux-zdslHp/linux-4.4.0/net/core/dev.c
:2456 skb_warn_bad_offload+0xcf/0x110()
qr-f78bfdf7-fe: caps=(0x000000000fdb58e9, 0x000000000fdb58e9) len=1955
data_len=479 gso_size=1448 gso_type=1 ip_summed=3
CPU: 34 PID: 806048 Comm: haproxy Tainted: G W OE 4.4.0-138-generic #164-Ubuntu
Call Trace:
 dump_stack+0x63/0x90
 warn_slowpath_common+0x82/0xc0
 warn_slowpath_fmt+0x5c/0x80
 ? ___ratelimit+0xa2/0xe0
 skb_warn_bad_offload+0xcf/0x110
 skb_checksum_help+0x185/0x1a0
 checksum_tg+0x22/0x29 [xt_CHECKSUM]
 ipt_do_table+0x301/0x730 [ip_tables]
 ? ipt_do_table+0x349/0x730 [ip_tables]
 iptable_mangle_hook+0x39/0x107 [iptable_mangle]
 nf_iterate+0x68/0x80
 nf_hook_slow+0x73/0xd0
 ip_output+0xcf/0xe0
 ? __ip_flush_pending_frames.isra.43+0x90/0x90
 ip_local_out+0x3b/0x50
 ip_queue_xmit+0x154/0x390
 __tcp_transmit_skb+0x52b/0x9b0
 tcp_write_xmit+0x1dd/0xf50
 __tcp_push_pending_frames+0x31/0xd0
 tcp_push+0xec/0x110
 tcp_sendmsg+0x749/0xba0
 inet_sendmsg+0x6b/0xa0
 sock_sendmsg+0x3e/0x50
 SYSC_sendto+0x101/0x190
 ? __sys_sendmsg+0x51/0x90
 SyS_sendto+0xe/0x10
 entry_SYSCALL_64_fastpath+0x22/0xc1

The CHECKSUM target does not support GSO skbs, and when a GSO skb is passed to
skb_checksum_help(), it errors out and skb_warn_bad_offload() is called.

The above call trace was found in a customer environment which has an Openstack
deployment, with the following sorts of iptables rules set:

-A neutron-l3-agent-POSTROUTING -o qr-+ -p tcp -m tcp --sport 9697 -j CHECKSUM
--checksum-fill
-A neutron-dhcp-age-POSTROUTING -p udp -m udp --dport 68 -j CHECKSUM
--checksum-fill

This was causing haproxy running on the node to crash and restart every time a
GSO skb was processed by the CHECKSUM target.

I recommend reading the netdev mailing list thread for more details:
https://www.spinics.net/lists/netdev/msg517366.html

[Fix]

This was fixed in 4.19 upstream with the below commit:

commit 10568f6c5761db24249c610c94d6e44d5505a0ba
Author: Florian Westphal <[hidden email]>
Date: Wed Aug 22 11:33:27 2018 +0200
Subject: netfilter: xt_checksum: ignore gso skbs

This commit adds a check to see if the current skb is a gso skb, and if it is,
skips skb_checksum_help(). It then continues on to check if the packet uses udp,
and if it does, exits early. Otherwise it prints a single warning that CHECKSUM
should be avoided, and if really needed, only for use with outbound udp.

Note, 10568f6c5761db24249c610c94d6e44d5505a0ba was included in upstream stable
version 4.18.13, and was backported to bionic in 4.15.0-58.64 by LP #1836426.

This patch required minor backporting for 4.4, by slightly adjusting the context
in the final patch hunk.

[Testcase]

You can reproduce this by adding the following iptables rule to the mangle
table:

-t mangle -A POSTROUTING -p tcp -m tcp --sport 80 -j CHECKSUM --checksum-fill

and running traffic over port 80 with incorrect checksums in the ip header.

I built a test kernel, which is available here:

https://launchpad.net/~mruffell/+archive/ubuntu/sf216537-test

For unpatched kernels, this causes the process which was handling the socket to
crash, as seen by haproxy crashing on a node in production which hits this
issue.

On patched kernels you see the below warning printed to dmesg and no crashes
occur.

xt_CHECKSUM: CHECKSUM should be avoided.  If really needed, restrict with
"-p udp" and only use in OUTPUT

[Regression Potential]

The changes are limited only to users which have CHECKSUM rules enabled in their
iptables configs. Openstack commonly configures such rules on deployment, even
though they are not necessary, as almost all packets have their checksum
calculated by NICs these days, and CHECKSUM is only around to service old dhcp
clients which would discard UDP packets with empty checksums.

This commit was selected for upstream -stable 4.18.13, and has made its way into
bionic 4.15.0-58.64 by LP #1836426. There have been no reported problems and
those kernels would have had sufficient testing with Openstack and its
configured iptables rules.

If any users are affected by regression, then they can simply delete any
CHECKSUM entries in their iptables configs.

Florian Westphal (1):
  netfilter: xt_checksum: ignore gso skbs

 net/netfilter/Kconfig       | 12 ++++++------
 net/netfilter/xt_CHECKSUM.c | 23 ++++++++++++++++++++++-
 2 files changed, 28 insertions(+), 7 deletions(-)

--
2.20.1


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

[SRU][Xenial][PATCH 1/1] netfilter: xt_checksum: ignore gso skbs

Matthew Ruffell
From: Florian Westphal <[hidden email]>

BugLink: https://bugs.launchpad.net/bugs/1840619

Satish Patel reports a skb_warn_bad_offload() splat caused
by -j CHECKSUM rules:

-A POSTROUTING -p tcp -m tcp --sport 80 -j CHECKSUM

The CHECKSUM target has never worked with GSO skbs, and the above rule
makes no sense as kernel will handle checksum updates on transmit.

Unfortunately, there are 3rd party tools that install such rules, so we
cannot reject this from the config plane without potential breakage.

Amend Kconfig text to clarify that the CHECKSUM target is only useful
in virtualized environments, where old dhcp clients that use AF_PACKET
used to discard UDP packets with a 'bad' header checksum and add a
one-time warning in case such rule isn't restricted to UDP.

v2: check IP6T_F_PROTO flag before cmp (Michal Kubecek)

Reported-by: Satish Patel <[hidden email]>
Reported-by: Markos Chandras <[hidden email]>
Reported-by: Michal Kubecek <[hidden email]>
Signed-off-by: Florian Westphal <[hidden email]>
Reviewed-by: Michal Kubecek <[hidden email]>
Signed-off-by: Pablo Neira Ayuso <[hidden email]>
(backported from commit 10568f6c5761db24249c610c94d6e44d5505a0ba)
[mruffell: minor context adjustment]
Signed-off-by: Matthew Ruffell <[hidden email]>
---
 net/netfilter/Kconfig       | 12 ++++++------
 net/netfilter/xt_CHECKSUM.c | 23 ++++++++++++++++++++++-
 2 files changed, 28 insertions(+), 7 deletions(-)

diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index 4692782b5280..e13e2eecbaf4 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -635,13 +635,13 @@ config NETFILTER_XT_TARGET_CHECKSUM
  depends on NETFILTER_ADVANCED
  ---help---
   This option adds a `CHECKSUM' target, which can be used in the iptables mangle
-  table.
+  table to work around buggy DHCP clients in virtualized environments.
 
-  You can use this target to compute and fill in the checksum in
-  a packet that lacks a checksum.  This is particularly useful,
-  if you need to work around old applications such as dhcp clients,
-  that do not work well with checksum offloads, but don't want to disable
-  checksum offload in your device.
+  Some old DHCP clients drop packets because they are not aware
+  that the checksum would normally be offloaded to hardware and
+  thus should be considered valid.
+  This target can be used to fill in the checksum using iptables
+  when such packets are sent via a virtual network device.
 
   To compile it as a module, choose M here.  If unsure, say N.
 
diff --git a/net/netfilter/xt_CHECKSUM.c b/net/netfilter/xt_CHECKSUM.c
index 0f642ef8cd26..db286fc0bc32 100644
--- a/net/netfilter/xt_CHECKSUM.c
+++ b/net/netfilter/xt_CHECKSUM.c
@@ -16,6 +16,9 @@
 #include <linux/netfilter/x_tables.h>
 #include <linux/netfilter/xt_CHECKSUM.h>
 
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv6/ip6_tables.h>
+
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Michael S. Tsirkin <[hidden email]>");
 MODULE_DESCRIPTION("Xtables: checksum modification");
@@ -25,7 +28,7 @@ MODULE_ALIAS("ip6t_CHECKSUM");
 static unsigned int
 checksum_tg(struct sk_buff *skb, const struct xt_action_param *par)
 {
- if (skb->ip_summed == CHECKSUM_PARTIAL)
+ if (skb->ip_summed == CHECKSUM_PARTIAL && !skb_is_gso(skb))
  skb_checksum_help(skb);
 
  return XT_CONTINUE;
@@ -34,6 +37,8 @@ checksum_tg(struct sk_buff *skb, const struct xt_action_param *par)
 static int checksum_tg_check(const struct xt_tgchk_param *par)
 {
  const struct xt_CHECKSUM_info *einfo = par->targinfo;
+ const struct ip6t_ip6 *i6 = par->entryinfo;
+ const struct ipt_ip *i4 = par->entryinfo;
 
  if (einfo->operation & ~XT_CHECKSUM_OP_FILL) {
  pr_info("unsupported CHECKSUM operation %x\n", einfo->operation);
@@ -43,6 +48,22 @@ static int checksum_tg_check(const struct xt_tgchk_param *par)
  pr_info("no CHECKSUM operation enabled\n");
  return -EINVAL;
  }
+
+ switch (par->family) {
+ case NFPROTO_IPV4:
+ if (i4->proto == IPPROTO_UDP &&
+    (i4->invflags & XT_INV_PROTO) == 0)
+ return 0;
+ break;
+ case NFPROTO_IPV6:
+ if ((i6->flags & IP6T_F_PROTO) &&
+    i6->proto == IPPROTO_UDP &&
+    (i6->invflags & XT_INV_PROTO) == 0)
+ return 0;
+ break;
+ }
+
+ pr_warn_once("CHECKSUM should be avoided.  If really needed, restrict with \"-p udp\" and only use in OUTPUT\n");
  return 0;
 }
 
--
2.20.1


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

ACK/Cmnt: [SRU][Xenial][PATCH 1/1] netfilter: xt_checksum: ignore gso skbs

Stefan Bader-2
On 21.08.19 05:20, Matthew Ruffell wrote:

> From: Florian Westphal <[hidden email]>
>
> BugLink: https://bugs.launchpad.net/bugs/1840619
>
> Satish Patel reports a skb_warn_bad_offload() splat caused
> by -j CHECKSUM rules:
>
> -A POSTROUTING -p tcp -m tcp --sport 80 -j CHECKSUM
>
> The CHECKSUM target has never worked with GSO skbs, and the above rule
> makes no sense as kernel will handle checksum updates on transmit.
>
> Unfortunately, there are 3rd party tools that install such rules, so we
> cannot reject this from the config plane without potential breakage.
>
> Amend Kconfig text to clarify that the CHECKSUM target is only useful
> in virtualized environments, where old dhcp clients that use AF_PACKET
> used to discard UDP packets with a 'bad' header checksum and add a
> one-time warning in case such rule isn't restricted to UDP.
>
> v2: check IP6T_F_PROTO flag before cmp (Michal Kubecek)
>
> Reported-by: Satish Patel <[hidden email]>
> Reported-by: Markos Chandras <[hidden email]>
> Reported-by: Michal Kubecek <[hidden email]>
> Signed-off-by: Florian Westphal <[hidden email]>
> Reviewed-by: Michal Kubecek <[hidden email]>
> Signed-off-by: Pablo Neira Ayuso <[hidden email]>
> (backported from commit 10568f6c5761db24249c610c94d6e44d5505a0ba)
> [mruffell: minor context adjustment]
> Signed-off-by: Matthew Ruffell <[hidden email]>
The bug report kept the development task incomplete, however this patch is from
4.19 (and released for Bionic with Ubuntu-4.15.0-56.61), so I set the devel task
to fix released.

Acked-by: Stefan Bader <[hidden email]>

> ---
>  net/netfilter/Kconfig       | 12 ++++++------
>  net/netfilter/xt_CHECKSUM.c | 23 ++++++++++++++++++++++-
>  2 files changed, 28 insertions(+), 7 deletions(-)
>
> diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
> index 4692782b5280..e13e2eecbaf4 100644
> --- a/net/netfilter/Kconfig
> +++ b/net/netfilter/Kconfig
> @@ -635,13 +635,13 @@ config NETFILTER_XT_TARGET_CHECKSUM
>   depends on NETFILTER_ADVANCED
>   ---help---
>    This option adds a `CHECKSUM' target, which can be used in the iptables mangle
> -  table.
> +  table to work around buggy DHCP clients in virtualized environments.
>  
> -  You can use this target to compute and fill in the checksum in
> -  a packet that lacks a checksum.  This is particularly useful,
> -  if you need to work around old applications such as dhcp clients,
> -  that do not work well with checksum offloads, but don't want to disable
> -  checksum offload in your device.
> +  Some old DHCP clients drop packets because they are not aware
> +  that the checksum would normally be offloaded to hardware and
> +  thus should be considered valid.
> +  This target can be used to fill in the checksum using iptables
> +  when such packets are sent via a virtual network device.
>  
>    To compile it as a module, choose M here.  If unsure, say N.
>  
> diff --git a/net/netfilter/xt_CHECKSUM.c b/net/netfilter/xt_CHECKSUM.c
> index 0f642ef8cd26..db286fc0bc32 100644
> --- a/net/netfilter/xt_CHECKSUM.c
> +++ b/net/netfilter/xt_CHECKSUM.c
> @@ -16,6 +16,9 @@
>  #include <linux/netfilter/x_tables.h>
>  #include <linux/netfilter/xt_CHECKSUM.h>
>  
> +#include <linux/netfilter_ipv4/ip_tables.h>
> +#include <linux/netfilter_ipv6/ip6_tables.h>
> +
>  MODULE_LICENSE("GPL");
>  MODULE_AUTHOR("Michael S. Tsirkin <[hidden email]>");
>  MODULE_DESCRIPTION("Xtables: checksum modification");
> @@ -25,7 +28,7 @@ MODULE_ALIAS("ip6t_CHECKSUM");
>  static unsigned int
>  checksum_tg(struct sk_buff *skb, const struct xt_action_param *par)
>  {
> - if (skb->ip_summed == CHECKSUM_PARTIAL)
> + if (skb->ip_summed == CHECKSUM_PARTIAL && !skb_is_gso(skb))
>   skb_checksum_help(skb);
>  
>   return XT_CONTINUE;
> @@ -34,6 +37,8 @@ checksum_tg(struct sk_buff *skb, const struct xt_action_param *par)
>  static int checksum_tg_check(const struct xt_tgchk_param *par)
>  {
>   const struct xt_CHECKSUM_info *einfo = par->targinfo;
> + const struct ip6t_ip6 *i6 = par->entryinfo;
> + const struct ipt_ip *i4 = par->entryinfo;
>  
>   if (einfo->operation & ~XT_CHECKSUM_OP_FILL) {
>   pr_info("unsupported CHECKSUM operation %x\n", einfo->operation);
> @@ -43,6 +48,22 @@ static int checksum_tg_check(const struct xt_tgchk_param *par)
>   pr_info("no CHECKSUM operation enabled\n");
>   return -EINVAL;
>   }
> +
> + switch (par->family) {
> + case NFPROTO_IPV4:
> + if (i4->proto == IPPROTO_UDP &&
> +    (i4->invflags & XT_INV_PROTO) == 0)
> + return 0;
> + break;
> + case NFPROTO_IPV6:
> + if ((i6->flags & IP6T_F_PROTO) &&
> +    i6->proto == IPPROTO_UDP &&
> +    (i6->invflags & XT_INV_PROTO) == 0)
> + return 0;
> + break;
> + }
> +
> + pr_warn_once("CHECKSUM should be avoided.  If really needed, restrict with \"-p udp\" and only use in OUTPUT\n");
>   return 0;
>  }
>  
>


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team

signature.asc (849 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

ACK: [SRU][Xenial][PATCH 1/1] netfilter: xt_checksum: ignore gso skbs

Connor Kuehl
In reply to this post by Matthew Ruffell
On 8/20/19 8:20 PM, Matthew Ruffell wrote:

> From: Florian Westphal <[hidden email]>
>
> BugLink: https://bugs.launchpad.net/bugs/1840619
>
> Satish Patel reports a skb_warn_bad_offload() splat caused
> by -j CHECKSUM rules:
>
> -A POSTROUTING -p tcp -m tcp --sport 80 -j CHECKSUM
>
> The CHECKSUM target has never worked with GSO skbs, and the above rule
> makes no sense as kernel will handle checksum updates on transmit.
>
> Unfortunately, there are 3rd party tools that install such rules, so we
> cannot reject this from the config plane without potential breakage.
>
> Amend Kconfig text to clarify that the CHECKSUM target is only useful
> in virtualized environments, where old dhcp clients that use AF_PACKET
> used to discard UDP packets with a 'bad' header checksum and add a
> one-time warning in case such rule isn't restricted to UDP.
>
> v2: check IP6T_F_PROTO flag before cmp (Michal Kubecek)
>
> Reported-by: Satish Patel <[hidden email]>
> Reported-by: Markos Chandras <[hidden email]>
> Reported-by: Michal Kubecek <[hidden email]>
> Signed-off-by: Florian Westphal <[hidden email]>
> Reviewed-by: Michal Kubecek <[hidden email]>
> Signed-off-by: Pablo Neira Ayuso <[hidden email]>
> (backported from commit 10568f6c5761db24249c610c94d6e44d5505a0ba)
> [mruffell: minor context adjustment]
> Signed-off-by: Matthew Ruffell <[hidden email]>

Acked-by: Connor Kuehl <[hidden email]>

> ---
>   net/netfilter/Kconfig       | 12 ++++++------
>   net/netfilter/xt_CHECKSUM.c | 23 ++++++++++++++++++++++-
>   2 files changed, 28 insertions(+), 7 deletions(-)
>
> diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
> index 4692782b5280..e13e2eecbaf4 100644
> --- a/net/netfilter/Kconfig
> +++ b/net/netfilter/Kconfig
> @@ -635,13 +635,13 @@ config NETFILTER_XT_TARGET_CHECKSUM
>   depends on NETFILTER_ADVANCED
>   ---help---
>    This option adds a `CHECKSUM' target, which can be used in the iptables mangle
> -  table.
> +  table to work around buggy DHCP clients in virtualized environments.
>  
> -  You can use this target to compute and fill in the checksum in
> -  a packet that lacks a checksum.  This is particularly useful,
> -  if you need to work around old applications such as dhcp clients,
> -  that do not work well with checksum offloads, but don't want to disable
> -  checksum offload in your device.
> +  Some old DHCP clients drop packets because they are not aware
> +  that the checksum would normally be offloaded to hardware and
> +  thus should be considered valid.
> +  This target can be used to fill in the checksum using iptables
> +  when such packets are sent via a virtual network device.
>  
>    To compile it as a module, choose M here.  If unsure, say N.
>  
> diff --git a/net/netfilter/xt_CHECKSUM.c b/net/netfilter/xt_CHECKSUM.c
> index 0f642ef8cd26..db286fc0bc32 100644
> --- a/net/netfilter/xt_CHECKSUM.c
> +++ b/net/netfilter/xt_CHECKSUM.c
> @@ -16,6 +16,9 @@
>   #include <linux/netfilter/x_tables.h>
>   #include <linux/netfilter/xt_CHECKSUM.h>
>  
> +#include <linux/netfilter_ipv4/ip_tables.h>
> +#include <linux/netfilter_ipv6/ip6_tables.h>
> +
>   MODULE_LICENSE("GPL");
>   MODULE_AUTHOR("Michael S. Tsirkin <[hidden email]>");
>   MODULE_DESCRIPTION("Xtables: checksum modification");
> @@ -25,7 +28,7 @@ MODULE_ALIAS("ip6t_CHECKSUM");
>   static unsigned int
>   checksum_tg(struct sk_buff *skb, const struct xt_action_param *par)
>   {
> - if (skb->ip_summed == CHECKSUM_PARTIAL)
> + if (skb->ip_summed == CHECKSUM_PARTIAL && !skb_is_gso(skb))
>   skb_checksum_help(skb);
>  
>   return XT_CONTINUE;
> @@ -34,6 +37,8 @@ checksum_tg(struct sk_buff *skb, const struct xt_action_param *par)
>   static int checksum_tg_check(const struct xt_tgchk_param *par)
>   {
>   const struct xt_CHECKSUM_info *einfo = par->targinfo;
> + const struct ip6t_ip6 *i6 = par->entryinfo;
> + const struct ipt_ip *i4 = par->entryinfo;
>  
>   if (einfo->operation & ~XT_CHECKSUM_OP_FILL) {
>   pr_info("unsupported CHECKSUM operation %x\n", einfo->operation);
> @@ -43,6 +48,22 @@ static int checksum_tg_check(const struct xt_tgchk_param *par)
>   pr_info("no CHECKSUM operation enabled\n");
>   return -EINVAL;
>   }
> +
> + switch (par->family) {
> + case NFPROTO_IPV4:
> + if (i4->proto == IPPROTO_UDP &&
> +    (i4->invflags & XT_INV_PROTO) == 0)
> + return 0;
> + break;
> + case NFPROTO_IPV6:
> + if ((i6->flags & IP6T_F_PROTO) &&
> +    i6->proto == IPPROTO_UDP &&
> +    (i6->invflags & XT_INV_PROTO) == 0)
> + return 0;
> + break;
> + }
> +
> + pr_warn_once("CHECKSUM should be avoided.  If really needed, restrict with \"-p udp\" and only use in OUTPUT\n");
>   return 0;
>   }
>  
>


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

APPLIED: [SRU][Xenial][PATCH 1/1] netfilter: xt_checksum: ignore gso skbs

Kleber Souza
In reply to this post by Matthew Ruffell
On 8/21/19 5:20 AM, Matthew Ruffell wrote:

> From: Florian Westphal <[hidden email]>
>
> BugLink: https://bugs.launchpad.net/bugs/1840619
>
> Satish Patel reports a skb_warn_bad_offload() splat caused
> by -j CHECKSUM rules:
>
> -A POSTROUTING -p tcp -m tcp --sport 80 -j CHECKSUM
>
> The CHECKSUM target has never worked with GSO skbs, and the above rule
> makes no sense as kernel will handle checksum updates on transmit.
>
> Unfortunately, there are 3rd party tools that install such rules, so we
> cannot reject this from the config plane without potential breakage.
>
> Amend Kconfig text to clarify that the CHECKSUM target is only useful
> in virtualized environments, where old dhcp clients that use AF_PACKET
> used to discard UDP packets with a 'bad' header checksum and add a
> one-time warning in case such rule isn't restricted to UDP.
>
> v2: check IP6T_F_PROTO flag before cmp (Michal Kubecek)
>
> Reported-by: Satish Patel <[hidden email]>
> Reported-by: Markos Chandras <[hidden email]>
> Reported-by: Michal Kubecek <[hidden email]>
> Signed-off-by: Florian Westphal <[hidden email]>
> Reviewed-by: Michal Kubecek <[hidden email]>
> Signed-off-by: Pablo Neira Ayuso <[hidden email]>
> (backported from commit 10568f6c5761db24249c610c94d6e44d5505a0ba)
> [mruffell: minor context adjustment]
> Signed-off-by: Matthew Ruffell <[hidden email]>
> ---
>  net/netfilter/Kconfig       | 12 ++++++------
>  net/netfilter/xt_CHECKSUM.c | 23 ++++++++++++++++++++++-
>  2 files changed, 28 insertions(+), 7 deletions(-)
>
> diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
> index 4692782b5280..e13e2eecbaf4 100644
> --- a/net/netfilter/Kconfig
> +++ b/net/netfilter/Kconfig
> @@ -635,13 +635,13 @@ config NETFILTER_XT_TARGET_CHECKSUM
>   depends on NETFILTER_ADVANCED
>   ---help---
>    This option adds a `CHECKSUM' target, which can be used in the iptables mangle
> -  table.
> +  table to work around buggy DHCP clients in virtualized environments.
>  
> -  You can use this target to compute and fill in the checksum in
> -  a packet that lacks a checksum.  This is particularly useful,
> -  if you need to work around old applications such as dhcp clients,
> -  that do not work well with checksum offloads, but don't want to disable
> -  checksum offload in your device.
> +  Some old DHCP clients drop packets because they are not aware
> +  that the checksum would normally be offloaded to hardware and
> +  thus should be considered valid.
> +  This target can be used to fill in the checksum using iptables
> +  when such packets are sent via a virtual network device.
>  
>    To compile it as a module, choose M here.  If unsure, say N.
>  
> diff --git a/net/netfilter/xt_CHECKSUM.c b/net/netfilter/xt_CHECKSUM.c
> index 0f642ef8cd26..db286fc0bc32 100644
> --- a/net/netfilter/xt_CHECKSUM.c
> +++ b/net/netfilter/xt_CHECKSUM.c
> @@ -16,6 +16,9 @@
>  #include <linux/netfilter/x_tables.h>
>  #include <linux/netfilter/xt_CHECKSUM.h>
>  
> +#include <linux/netfilter_ipv4/ip_tables.h>
> +#include <linux/netfilter_ipv6/ip6_tables.h>
> +
>  MODULE_LICENSE("GPL");
>  MODULE_AUTHOR("Michael S. Tsirkin <[hidden email]>");
>  MODULE_DESCRIPTION("Xtables: checksum modification");
> @@ -25,7 +28,7 @@ MODULE_ALIAS("ip6t_CHECKSUM");
>  static unsigned int
>  checksum_tg(struct sk_buff *skb, const struct xt_action_param *par)
>  {
> - if (skb->ip_summed == CHECKSUM_PARTIAL)
> + if (skb->ip_summed == CHECKSUM_PARTIAL && !skb_is_gso(skb))
>   skb_checksum_help(skb);
>  
>   return XT_CONTINUE;
> @@ -34,6 +37,8 @@ checksum_tg(struct sk_buff *skb, const struct xt_action_param *par)
>  static int checksum_tg_check(const struct xt_tgchk_param *par)
>  {
>   const struct xt_CHECKSUM_info *einfo = par->targinfo;
> + const struct ip6t_ip6 *i6 = par->entryinfo;
> + const struct ipt_ip *i4 = par->entryinfo;
>  
>   if (einfo->operation & ~XT_CHECKSUM_OP_FILL) {
>   pr_info("unsupported CHECKSUM operation %x\n", einfo->operation);
> @@ -43,6 +48,22 @@ static int checksum_tg_check(const struct xt_tgchk_param *par)
>   pr_info("no CHECKSUM operation enabled\n");
>   return -EINVAL;
>   }
> +
> + switch (par->family) {
> + case NFPROTO_IPV4:
> + if (i4->proto == IPPROTO_UDP &&
> +    (i4->invflags & XT_INV_PROTO) == 0)
> + return 0;
> + break;
> + case NFPROTO_IPV6:
> + if ((i6->flags & IP6T_F_PROTO) &&
> +    i6->proto == IPPROTO_UDP &&
> +    (i6->invflags & XT_INV_PROTO) == 0)
> + return 0;
> + break;
> + }
> +
> + pr_warn_once("CHECKSUM should be avoided.  If really needed, restrict with \"-p udp\" and only use in OUTPUT\n");
>   return 0;
>  }
>  
>

Applied to xenial/master-next branch.

Thanks,
Kleber

--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team