2022-07-12 18:09:55

by Andrea Mayer

[permalink] [raw]
Subject: [net 0/3] seg6: fix skb checksum for SRH encapsulation/insertion

The Linux kernel supports Segment Routing Header (SRH)
encapsulation/insertion operations by providing the capability to: i)
encapsulate a packet in an outer IPv6 header with a specified SRH; ii)
insert a specified SRH directly after the IPv6 header of the packet.
Note that the insertion operation is also referred to as 'injection'.

The two operations are respectively supported by seg6_do_srh_encap() and
seg6_do_srh_inline(), which operate on the skb associated to the packet as
needed (e.g. adding the necessary headers and initializing them, while
taking care to recalculate the skb checksum).

seg6_do_srh_encap() and seg6_do_srh_inline() do not initialize the payload
length of the IPv6 header, which is carried out by the caller functions.
However, this approach causes the corruption of the skb checksum which
needs to be updated only after initialization of headers is completed
(thanks to Paolo Abeni for detecting this issue).

The patchset fixes the skb checksum corruption by moving the IPv6 header
payload length initialization from the callers of seg6_do_srh_encap() and
seg6_do_srh_inline() directly into these functions.

This patchset is organized as follows:
- patch 1/3, seg6: fix skb checksum evaluation in SRH
encapsulation/insertion;
(* SRH encapsulation/insertion available since v4.10)

- patch 2/3, seg6: fix skb checksum in SRv6 End.B6 and End.B6.Encaps
behaviors;
(* SRv6 End.B6 and End.B6.Encaps behaviors available since v4.14)

- patch 3/3, seg6: bpf: fix skb checksum in bpf_push_seg6_encap();
(* bpf IPv6 Segment Routing helpers available since v4.18)

Thank you all,
Andrea

Andrea Mayer (3):
seg6: fix skb checksum evaluation in SRH encapsulation/insertion
seg6: fix skb checksum in SRv6 End.B6 and End.B6.Encaps behaviors
seg6: bpf: fix skb checksum in bpf_push_seg6_encap()

net/core/filter.c | 1 -
net/ipv6/seg6_iptunnel.c | 5 ++++-
net/ipv6/seg6_local.c | 2 --
3 files changed, 4 insertions(+), 4 deletions(-)

--
2.20.1


2022-07-12 18:09:55

by Andrea Mayer

[permalink] [raw]
Subject: [net 1/3] seg6: fix skb checksum evaluation in SRH encapsulation/insertion

Support for SRH encapsulation and insertion was introduced with
commit 6c8702c60b88 ("ipv6: sr: add support for SRH encapsulation and
injection with lwtunnels"), through the seg6_do_srh_encap() and
seg6_do_srh_inline() functions, respectively.
The former encapsulates the packet in an outer IPv6 header along with
the SRH, while the latter inserts the SRH between the IPv6 header and
the payload. Then, the headers are initialized/updated according to the
operating mode (i.e., encap/inline).
Finally, the skb checksum is calculated to reflect the changes applied
to the headers.

The IPv6 payload length ('payload_len') is not initialized
within seg6_do_srh_{inline,encap}() but is deferred in seg6_do_srh(), i.e.
the caller of seg6_do_srh_{inline,encap}().
However, this operation invalidates the skb checksum, since the
'payload_len' is updated only after the checksum is evaluated.

To solve this issue, the initialization of the IPv6 payload length is
moved from seg6_do_srh() directly into the seg6_do_srh_{inline,encap}()
functions and before the skb checksum update takes place.

Fixes: 6c8702c60b88 ("ipv6: sr: add support for SRH encapsulation and injection with lwtunnels")
Reported-by: Paolo Abeni <[email protected]>
Link: https://lore.kernel.org/all/[email protected]
Signed-off-by: Andrea Mayer <[email protected]>
---
net/ipv6/seg6_iptunnel.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/net/ipv6/seg6_iptunnel.c b/net/ipv6/seg6_iptunnel.c
index d64855010948..e756ba705fd9 100644
--- a/net/ipv6/seg6_iptunnel.c
+++ b/net/ipv6/seg6_iptunnel.c
@@ -189,6 +189,8 @@ int seg6_do_srh_encap(struct sk_buff *skb, struct ipv6_sr_hdr *osrh, int proto)
}
#endif

+ hdr->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
+
skb_postpush_rcsum(skb, hdr, tot_len);

return 0;
@@ -241,6 +243,8 @@ int seg6_do_srh_inline(struct sk_buff *skb, struct ipv6_sr_hdr *osrh)
}
#endif

+ hdr->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
+
skb_postpush_rcsum(skb, hdr, sizeof(struct ipv6hdr) + hdrlen);

return 0;
@@ -302,7 +306,6 @@ static int seg6_do_srh(struct sk_buff *skb)
break;
}

- ipv6_hdr(skb)->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
skb_set_transport_header(skb, sizeof(struct ipv6hdr));
nf_reset_ct(skb);

--
2.20.1

2022-07-12 18:29:37

by Andrea Mayer

[permalink] [raw]
Subject: [net 2/3] seg6: fix skb checksum in SRv6 End.B6 and End.B6.Encaps behaviors

The SRv6 End.B6 and End.B6.Encaps behaviors rely on functions
seg6_do_srh_{encap,inline}() to, respectively: i) encapsulate the
packet within an outer IPv6 header with the specified Segment Routing
Header (SRH); ii) insert the specified SRH directly after the IPv6
header of the packet.

This patch removes the initialization of the IPv6 header payload length
from the input_action_end_b6{_encap}() functions, as it is now handled
properly by seg6_do_srh_{encap,inline}() to avoid corruption of the skb
checksum.

Fixes: 140f04c33bbc ("ipv6: sr: implement several seg6local actions")
Signed-off-by: Andrea Mayer <[email protected]>
---
net/ipv6/seg6_local.c | 2 --
1 file changed, 2 deletions(-)

diff --git a/net/ipv6/seg6_local.c b/net/ipv6/seg6_local.c
index 98a34287439c..2cd4a8d3b30a 100644
--- a/net/ipv6/seg6_local.c
+++ b/net/ipv6/seg6_local.c
@@ -826,7 +826,6 @@ static int input_action_end_b6(struct sk_buff *skb, struct seg6_local_lwt *slwt)
if (err)
goto drop;

- ipv6_hdr(skb)->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
skb_set_transport_header(skb, sizeof(struct ipv6hdr));

seg6_lookup_nexthop(skb, NULL, 0);
@@ -858,7 +857,6 @@ static int input_action_end_b6_encap(struct sk_buff *skb,
if (err)
goto drop;

- ipv6_hdr(skb)->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
skb_set_transport_header(skb, sizeof(struct ipv6hdr));

seg6_lookup_nexthop(skb, NULL, 0);
--
2.20.1

2022-07-12 22:42:46

by Stanislav Fomichev

[permalink] [raw]
Subject: Re: [net 0/3] seg6: fix skb checksum for SRH encapsulation/insertion

On 07/12, Andrea Mayer wrote:
> The Linux kernel supports Segment Routing Header (SRH)
> encapsulation/insertion operations by providing the capability to: i)
> encapsulate a packet in an outer IPv6 header with a specified SRH; ii)
> insert a specified SRH directly after the IPv6 header of the packet.
> Note that the insertion operation is also referred to as 'injection'.

> The two operations are respectively supported by seg6_do_srh_encap() and
> seg6_do_srh_inline(), which operate on the skb associated to the packet as
> needed (e.g. adding the necessary headers and initializing them, while
> taking care to recalculate the skb checksum).

> seg6_do_srh_encap() and seg6_do_srh_inline() do not initialize the payload
> length of the IPv6 header, which is carried out by the caller functions.
> However, this approach causes the corruption of the skb checksum which
> needs to be updated only after initialization of headers is completed
> (thanks to Paolo Abeni for detecting this issue).

> The patchset fixes the skb checksum corruption by moving the IPv6 header
> payload length initialization from the callers of seg6_do_srh_encap() and
> seg6_do_srh_inline() directly into these functions.

> This patchset is organized as follows:
> - patch 1/3, seg6: fix skb checksum evaluation in SRH
> encapsulation/insertion;
> (* SRH encapsulation/insertion available since v4.10)

> - patch 2/3, seg6: fix skb checksum in SRv6 End.B6 and End.B6.Encaps
> behaviors;
> (* SRv6 End.B6 and End.B6.Encaps behaviors available since v4.14)

> - patch 3/3, seg6: bpf: fix skb checksum in bpf_push_seg6_encap();
> (* bpf IPv6 Segment Routing helpers available since v4.18)

BPF changes make sense. I've tested them by applying the whole series and
running test_lwt_seg6local.sh.

Reviewed-by: Stanislav Fomichev <[email protected]>
Tested-by: Stanislav Fomichev <[email protected]>


> Thank you all,
> Andrea

> Andrea Mayer (3):
> seg6: fix skb checksum evaluation in SRH encapsulation/insertion
> seg6: fix skb checksum in SRv6 End.B6 and End.B6.Encaps behaviors
> seg6: bpf: fix skb checksum in bpf_push_seg6_encap()

> net/core/filter.c | 1 -
> net/ipv6/seg6_iptunnel.c | 5 ++++-
> net/ipv6/seg6_local.c | 2 --
> 3 files changed, 4 insertions(+), 4 deletions(-)

> --
> 2.20.1

2022-07-14 08:38:24

by patchwork-bot+netdevbpf

[permalink] [raw]
Subject: Re: [net 0/3] seg6: fix skb checksum for SRH encapsulation/insertion

Hello:

This series was applied to netdev/net.git (master)
by Paolo Abeni <[email protected]>:

On Tue, 12 Jul 2022 19:58:34 +0200 you wrote:
> The Linux kernel supports Segment Routing Header (SRH)
> encapsulation/insertion operations by providing the capability to: i)
> encapsulate a packet in an outer IPv6 header with a specified SRH; ii)
> insert a specified SRH directly after the IPv6 header of the packet.
> Note that the insertion operation is also referred to as 'injection'.
>
> The two operations are respectively supported by seg6_do_srh_encap() and
> seg6_do_srh_inline(), which operate on the skb associated to the packet as
> needed (e.g. adding the necessary headers and initializing them, while
> taking care to recalculate the skb checksum).
>
> [...]

Here is the summary with links:
- [net,1/3] seg6: fix skb checksum evaluation in SRH encapsulation/insertion
https://git.kernel.org/netdev/net/c/df8386d13ea2
- [net,2/3] seg6: fix skb checksum in SRv6 End.B6 and End.B6.Encaps behaviors
https://git.kernel.org/netdev/net/c/f048880fc770
- [net,3/3] seg6: bpf: fix skb checksum in bpf_push_seg6_encap()
https://git.kernel.org/netdev/net/c/4889fbd98dea

You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html