* [PATCH net v2 1/2] xfrm6: Fix IPv6 payload_len in xfrm6_transport_finish
@ 2017-06-22 8:37 yossiku
2017-06-22 8:37 ` [PATCH net v2 2/2] esp6_offload: Fix IP6CB(skb)->nhoff for ESP GRO yossiku
0 siblings, 1 reply; 3+ messages in thread
From: yossiku @ 2017-06-22 8:37 UTC (permalink / raw)
To: netdev, Herbert Xu, Steffen Klassert
Cc: Yevgeny Kliteynik, Boris Pismenny, Ilan Tayari, Yossi Kuperman
From: Yossi Kuperman <yossiku@mellanox.com>
IPv6 payload length indicates the size of the payload, including any
extension headers.
In xfrm6_transport_finish, ipv6_hdr(skb)->payload_len is set to the
payload size only, regardless of the presence of any extension headers.
After ESP GRO transport mode decapsulation, ipv6_rcv trims the packet
according to the wrong payload_len, thus corrupting the packet.
Set payload_len to account for extension headers as well.
Fixes: 7785bba299a8 ("esp: Add a software GRO codepath")
Signed-off-by: Yossi Kuperman <yossiku@mellanox.com>
---
v1 -> v2:
- Fix the "Fixes" tag
---
net/ipv6/xfrm6_input.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/ipv6/xfrm6_input.c b/net/ipv6/xfrm6_input.c
index 08a807b..3ef5d91 100644
--- a/net/ipv6/xfrm6_input.c
+++ b/net/ipv6/xfrm6_input.c
@@ -43,8 +43,8 @@ int xfrm6_transport_finish(struct sk_buff *skb, int async)
return 1;
#endif
- ipv6_hdr(skb)->payload_len = htons(skb->len);
__skb_push(skb, skb->data - skb_network_header(skb));
+ ipv6_hdr(skb)->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
if (xo && (xo->flags & XFRM_GRO)) {
skb_mac_header_rebuild(skb);
--
2.8.1
^ permalink raw reply related [flat|nested] 3+ messages in thread* [PATCH net v2 2/2] esp6_offload: Fix IP6CB(skb)->nhoff for ESP GRO
2017-06-22 8:37 [PATCH net v2 1/2] xfrm6: Fix IPv6 payload_len in xfrm6_transport_finish yossiku
@ 2017-06-22 8:37 ` yossiku
2017-06-22 10:52 ` Steffen Klassert
0 siblings, 1 reply; 3+ messages in thread
From: yossiku @ 2017-06-22 8:37 UTC (permalink / raw)
To: netdev, Herbert Xu, Steffen Klassert
Cc: Yevgeny Kliteynik, Boris Pismenny, Ilan Tayari, Yossi Kuperman
From: Yossi Kuperman <yossiku@mellanox.com>
IP6CB(skb)->nhoff is the offset of the nexthdr field in an IPv6
header, unless there are extension headers present, in which case
nhoff points to the nexthdr field of the last extension header.
In non-GRO code path, nhoff is set by ipv6_rcv before any XFRM code
is executed. Conversely, in GRO code path (when esp6_offload is loaded),
nhoff is not set. The following functions fail to read the correct value
and eventually the packet is dropped:
xfrm6_transport_finish
xfrm6_tunnel_input
xfrm6_rcv_tnl
Set nhoff to the proper offset of nexthdr in esp6_gro_receive.
Fixes: 7785bba299a8 ("esp: Add a software GRO codepath")
Signed-off-by: Yossi Kuperman <yossiku@mellanox.com>
---
net/ipv6/esp6_offload.c | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)
diff --git a/net/ipv6/esp6_offload.c b/net/ipv6/esp6_offload.c
index d950d43..f02f131 100644
--- a/net/ipv6/esp6_offload.c
+++ b/net/ipv6/esp6_offload.c
@@ -30,6 +30,25 @@
#include <net/ipv6.h>
#include <linux/icmpv6.h>
+static __u16 esp6_nexthdr_esp_offset(struct ipv6hdr *ipv6_hdr, int nhlen)
+{
+ int off = sizeof(struct ipv6hdr);
+ struct ipv6_opt_hdr *exthdr;
+
+ if (likely(ipv6_hdr->nexthdr == NEXTHDR_ESP))
+ return offsetof(struct ipv6hdr, nexthdr);
+
+ while (off < nhlen) {
+ exthdr = (void *)ipv6_hdr + off;
+ if (exthdr->nexthdr == NEXTHDR_ESP)
+ return off;
+
+ off += ipv6_optlen(exthdr);
+ }
+
+ return 0;
+}
+
static struct sk_buff **esp6_gro_receive(struct sk_buff **head,
struct sk_buff *skb)
{
@@ -38,6 +57,7 @@ static struct sk_buff **esp6_gro_receive(struct sk_buff **head,
struct xfrm_state *x;
__be32 seq;
__be32 spi;
+ int nhoff;
int err;
skb_pull(skb, offset);
@@ -72,6 +92,11 @@ static struct sk_buff **esp6_gro_receive(struct sk_buff **head,
xo->flags |= XFRM_GRO;
+ nhoff = esp6_nexthdr_esp_offset(ipv6_hdr(skb), offset);
+ if (!nhoff)
+ goto out;
+
+ IP6CB(skb)->nhoff = nhoff;
XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6 = NULL;
XFRM_SPI_SKB_CB(skb)->family = AF_INET6;
XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct ipv6hdr, daddr);
--
2.8.1
^ permalink raw reply related [flat|nested] 3+ messages in thread* Re: [PATCH net v2 2/2] esp6_offload: Fix IP6CB(skb)->nhoff for ESP GRO
2017-06-22 8:37 ` [PATCH net v2 2/2] esp6_offload: Fix IP6CB(skb)->nhoff for ESP GRO yossiku
@ 2017-06-22 10:52 ` Steffen Klassert
0 siblings, 0 replies; 3+ messages in thread
From: Steffen Klassert @ 2017-06-22 10:52 UTC (permalink / raw)
To: yossiku; +Cc: netdev, Herbert Xu, Yevgeny Kliteynik, Boris Pismenny,
Ilan Tayari
On Thu, Jun 22, 2017 at 11:37:11AM +0300, yossiku@mellanox.com wrote:
> From: Yossi Kuperman <yossiku@mellanox.com>
>
> IP6CB(skb)->nhoff is the offset of the nexthdr field in an IPv6
> header, unless there are extension headers present, in which case
> nhoff points to the nexthdr field of the last extension header.
>
> In non-GRO code path, nhoff is set by ipv6_rcv before any XFRM code
> is executed. Conversely, in GRO code path (when esp6_offload is loaded),
> nhoff is not set. The following functions fail to read the correct value
> and eventually the packet is dropped:
>
> xfrm6_transport_finish
> xfrm6_tunnel_input
> xfrm6_rcv_tnl
>
> Set nhoff to the proper offset of nexthdr in esp6_gro_receive.
>
> Fixes: 7785bba299a8 ("esp: Add a software GRO codepath")
> Signed-off-by: Yossi Kuperman <yossiku@mellanox.com>
Both patches applied, thanks for your work Yossi!
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2017-06-22 10:52 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-06-22 8:37 [PATCH net v2 1/2] xfrm6: Fix IPv6 payload_len in xfrm6_transport_finish yossiku
2017-06-22 8:37 ` [PATCH net v2 2/2] esp6_offload: Fix IP6CB(skb)->nhoff for ESP GRO yossiku
2017-06-22 10:52 ` Steffen Klassert
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).