Skip to content

Commit

Permalink
seg6: fix the iif in the IPv6 socket control block
Browse files Browse the repository at this point in the history
When an IPv4 packet is received, the ip_rcv_core(...) sets the receiving
interface index into the IPv4 socket control block (v5.16-rc4,
net/ipv4/ip_input.c line 510):

    IPCB(skb)->iif = skb->skb_iif;

If that IPv4 packet is meant to be encapsulated in an outer IPv6+SRH
header, the seg6_do_srh_encap(...) performs the required encapsulation.
In this case, the seg6_do_srh_encap function clears the IPv6 socket control
block (v5.16-rc4 net/ipv6/seg6_iptunnel.c line 163):

    memset(IP6CB(skb), 0, sizeof(*IP6CB(skb)));

The memset(...) was introduced in commit ef48974 ("ipv6: sr: clear
IP6CB(skb) on SRH ip4ip6 encapsulation") a long time ago (2019-01-29).

Since the IPv6 socket control block and the IPv4 socket control block share
the same memory area (skb->cb), the receiving interface index info is lost
(IP6CB(skb)->iif is set to zero).

As a side effect, that condition triggers a NULL pointer dereference if
commit 0857d6f ("ipv6: When forwarding count rx stats on the orig
netdev") is applied.

To fix that issue, we set the IP6CB(skb)->iif with the index of the
receiving interface once again.

Fixes: ef48974 ("ipv6: sr: clear IP6CB(skb) on SRH ip4ip6 encapsulation")
Signed-off-by: Andrea Mayer <andrea.mayer@uniroma2.it>
Reviewed-by: David Ahern <dsahern@kernel.org>
Link: https://lore.kernel.org/r/20211208195409.12169-1-andrea.mayer@uniroma2.it
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
  • Loading branch information
Andrea Mayer authored and Jakub Kicinski committed Dec 9, 2021
1 parent c56c963 commit ae68d93
Showing 1 changed file with 8 additions and 0 deletions.
8 changes: 8 additions & 0 deletions net/ipv6/seg6_iptunnel.c
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,14 @@ int seg6_do_srh_encap(struct sk_buff *skb, struct ipv6_sr_hdr *osrh, int proto)
hdr->hop_limit = ip6_dst_hoplimit(skb_dst(skb));

memset(IP6CB(skb), 0, sizeof(*IP6CB(skb)));

/* the control block has been erased, so we have to set the
* iif once again.
* We read the receiving interface index directly from the
* skb->skb_iif as it is done in the IPv4 receiving path (i.e.:
* ip_rcv_core(...)).
*/
IP6CB(skb)->iif = skb->skb_iif;
}

hdr->nexthdr = NEXTHDR_ROUTING;
Expand Down

0 comments on commit ae68d93

Please sign in to comment.