Skip to contentSkip to conversation

Question about possible misuse checksum in tcf_csum_ipv6_icmp()

net/sched Chenyuan Yang 2 participants 3 messages Mar 18, 2024

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

Dear TC subsystem maintainers,

We are curious whether the function tcf_csum_ipv6_icmp() would have a misuse of csum_partial() leading to an out-of-bounds access.

The function tcf_csum_ipv6_icmp is https://elixir.bootlin.com/linux/v6.8/source/net/sched/act_csum.c#L183 and the relevant code is

```
static int tcf_csum_ipv6_icmp(struct sk_buff *skb, unsigned int ihl,
			      unsigned int ipl)
{
  ...
	ip6h = ipv6_hdr(skb);
	icmp6h->icmp6_cksum = 0;
	skb->csum = csum_partial(icmp6h, ipl - ihl, 0);
	icmp6h->icmp6_cksum = csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr,
					      ipl - ihl, IPPROTO_ICMPV6,
					      skb->csum);
  ...
}
```

Based on this patch: https://lore.kernel.org/netdev/[email protected]/T/, it seems that the skb here for ICMPv6 could be non-linear, and csum_partial is not suitable for non-linear SKBs, which could lead to an out-of-bound access. The correct approach is to use skb_checksum which properly handles non-linear SKBs.

Based on the above information, a possible fix would be

```
-	skb->csum = csum_partial(icmp6h, ipl - ihl, 0);
+	skb->csum = skb_checksum(skb, skb_transport_offset(skb), ipl - ihl, 0);
``` 

Please kindly correct us if we missed any key information. Looking forward to your response!

Best,
Chenyuan

#1 lore raw
Quoted 27 lines · Chenyuan Yang

Dear TC subsystem maintainers,

We are curious whether the function tcf_csum_ipv6_icmp() would have a misuse of csum_partial() leading to an out-of-bounds access.

The function tcf_csum_ipv6_icmp is https://elixir.bootlin.com/linux/v6.8/source/net/sched/act_csum.c#L183 and the relevant code is

```
static int tcf_csum_ipv6_icmp(struct sk_buff *skb, unsigned int ihl,
                              unsigned int ipl)
{
  ...
        ip6h = ipv6_hdr(skb);
        icmp6h->icmp6_cksum = 0;
        skb->csum = csum_partial(icmp6h, ipl - ihl, 0);
        icmp6h->icmp6_cksum = csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr,
                                              ipl - ihl, IPPROTO_ICMPV6,
                                              skb->csum);
  ...
}
```

Based on this patch: https://lore.kernel.org/netdev/[email protected]/T/, it seems that the skb here for ICMPv6 could be non-linear, and csum_partial is not suitable for non-linear SKBs, which could lead to an out-of-bound access. The correct approach is to use skb_checksum which properly handles non-linear SKBs.

Based on the above information, a possible fix would be ```

(quoted diff) +1 -1
-       skb->csum = csum_partial(icmp6h, ipl - ihl, 0);
+       skb->csum = skb_checksum(skb, skb_transport_offset(skb), ipl - ihl, 0);
Quoted 1 line

```

Why would this code be an issue only in tcf_csum_ipv6_icmp(), and not in other functions ?

It seems we have proper pskb_may_pull() calls.

If you have a syzbot/syzkaller trace, please share it.

#2 lore raw

Thank you very much for your swift response.

Quoted 1 line

It seems we have proper pskb_may_pull() calls.

I realized that I had overlooked verifying the suitability of the SKB in this context. Your observation is indeed correct, and I now understand that this should not present any concerns.

Thank you once again for your valuable feedback.

Best,
Chenyuan

Quoted 37 lines · Eric Dumazet
Quoted 27 lines · Chenyuan Yang

Dear TC subsystem maintainers,

We are curious whether the function tcf_csum_ipv6_icmp() would have a misuse of csum_partial() leading to an out-of-bounds access.

The function tcf_csum_ipv6_icmp is https://elixir.bootlin.com/linux/v6.8/source/net/sched/act_csum.c#L183 and the relevant code is

```
static int tcf_csum_ipv6_icmp(struct sk_buff *skb, unsigned int ihl,
                              unsigned int ipl)
{
  ...
        ip6h = ipv6_hdr(skb);
        icmp6h->icmp6_cksum = 0;
        skb->csum = csum_partial(icmp6h, ipl - ihl, 0);
        icmp6h->icmp6_cksum = csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr,
                                              ipl - ihl, IPPROTO_ICMPV6,
                                              skb->csum);
  ...
}
```

Based on this patch: https://lore.kernel.org/netdev/[email protected]/T/, it seems that the skb here for ICMPv6 could be non-linear, and csum_partial is not suitable for non-linear SKBs, which could lead to an out-of-bound access. The correct approach is to use skb_checksum which properly handles non-linear SKBs.

Based on the above information, a possible fix would be ```

(quoted diff) +1 -1
-       skb->csum = csum_partial(icmp6h, ipl - ihl, 0);
+       skb->csum = skb_checksum(skb, skb_transport_offset(skb), ipl - ihl, 0);
Quoted 1 line

```

Why would this code be an issue only in tcf_csum_ipv6_icmp(), and not in other functions ?

It seems we have proper pskb_may_pull() calls.

If you have a syzbot/syzkaller trace, please share it.