linux/net/core
Paul Chaignon 2536810df1 bpf: Fix L4 csum update on IPv6 in CHECKSUM_COMPLETE
commit ead7f9b8de upstream.

In Cilium, we use bpf_csum_diff + bpf_l4_csum_replace to, among other
things, update the L4 checksum after reverse SNATing IPv6 packets. That
use case is however not currently supported and leads to invalid
skb->csum values in some cases. This patch adds support for IPv6 address
changes in bpf_l4_csum_update via a new flag.

When calling bpf_l4_csum_replace in Cilium, it ends up calling
inet_proto_csum_replace_by_diff:

    1:  void inet_proto_csum_replace_by_diff(__sum16 *sum, struct sk_buff *skb,
    2:                                       __wsum diff, bool pseudohdr)
    3:  {
    4:      if (skb->ip_summed != CHECKSUM_PARTIAL) {
    5:          csum_replace_by_diff(sum, diff);
    6:          if (skb->ip_summed == CHECKSUM_COMPLETE && pseudohdr)
    7:              skb->csum = ~csum_sub(diff, skb->csum);
    8:      } else if (pseudohdr) {
    9:          *sum = ~csum_fold(csum_add(diff, csum_unfold(*sum)));
    10:     }
    11: }

The bug happens when we're in the CHECKSUM_COMPLETE state. We've just
updated one of the IPv6 addresses. The helper now updates the L4 header
checksum on line 5. Next, it updates skb->csum on line 7. It shouldn't.

For an IPv6 packet, the updates of the IPv6 address and of the L4
checksum will cancel each other. The checksums are set such that
computing a checksum over the packet including its checksum will result
in a sum of 0. So the same is true here when we update the L4 checksum
on line 5. We'll update it as to cancel the previous IPv6 address
update. Hence skb->csum should remain untouched in this case.

The same bug doesn't affect IPv4 packets because, in that case, three
fields are updated: the IPv4 address, the IP checksum, and the L4
checksum. The change to the IPv4 address and one of the checksums still
cancel each other in skb->csum, but we're left with one checksum update
and should therefore update skb->csum accordingly. That's exactly what
inet_proto_csum_replace_by_diff does.

This special case for IPv6 L4 checksums is also described atop
inet_proto_csum_replace16, the function we should be using in this case.

This patch introduces a new bpf_l4_csum_replace flag, BPF_F_IPV6,
to indicate that we're updating the L4 checksum of an IPv6 packet. When
the flag is set, inet_proto_csum_replace_by_diff will skip the
skb->csum update.

Fixes: 7d672345ed ("bpf: add generic bpf_csum_diff helper")
Signed-off-by: Paul Chaignon <paul.chaignon@gmail.com>
Acked-by: Daniel Borkmann <daniel@iogearbox.net>
Link: https://patch.msgid.link/96a6bc3a443e6f0b21ff7b7834000e17fb549e05.1748509484.git.paul.chaignon@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Paul Chaignon <paul.chaignon@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
History 2025-06-27 11:09:00 +01:00
..
bpf_sk_storage.c bpf: Add length check for SK_DIAG_BPF_STORAGE_REQ_MAP_FD parsing 2023-07-27 10:07:56 -07:00
datagram.c net: fix rc7's __skb_datagram_iter() 2024-07-18 13:21:13 +02:00
dev.c net: Rename mono_delivery_time to tstamp_type for scalabilty 2025-05-09 09:43:57 +02:00
dev.h net: fix removing a namespace with conflicting altnames 2024-01-31 16:19:01 -08:00
dev_addr_lists.c net: extract a few internals from netdevice.h 2022-04-07 20:32:09 -07:00
dev_addr_lists_test.c kunit: Use KUNIT_EXPECT_MEMEQ macro 2022-10-27 02:40:14 -06:00
dev_ioctl.c net: omit ndo_hwtstamp_get() call when possible in dev_set_hwtstamp_phylib() 2023-08-06 13:25:10 +01:00
drop_monitor.c drop_monitor: fix incorrect initialization order 2025-02-27 04:10:51 -08:00
dst.c net: decrease cached dst counters in dst_release 2025-04-10 14:37:40 +02:00
dst_cache.c ipv6: introduce dst_rt6_info() helper 2024-12-14 19:59:35 +01:00
failover.c net: failover: use IFF_NO_ADDRCONF flag to prevent ipv6 addrconf 2022-12-12 15:18:25 -08:00
fib_notifier.c net: fib_notifier: propagate extack down to the notifier block callback 2019-10-04 11:10:56 -07:00
fib_rules.c fib: expand fib_rule_policy 2021-12-16 07:18:35 -08:00
filter.c bpf: Fix L4 csum update on IPv6 in CHECKSUM_COMPLETE 2025-06-27 11:09:00 +01:00
flow_dissector.c flow_dissector: Fix port range key handling in BPF conversion 2025-02-27 04:10:49 -08:00
flow_offload.c tc: flower: Enable offload support IPSEC SPI field. 2023-08-02 10:09:32 +01:00
gen_estimator.c net: use unrcu_pointer() helper 2024-12-09 10:32:10 +01:00
gen_stats.c net: Remove the obsolte u64_stats_fetch_*_irq() users (net). 2022-10-28 20:13:54 -07:00
gro.c net: Clear old fragment checksum value in napi_reuse_skb 2025-03-07 16:45:41 +01:00
gro_cells.c net: drop the weight argument from netif_napi_add 2022-09-28 18:57:14 -07:00
gso.c net: move gso declarations and functions to their own files 2023-06-10 00:11:41 -07:00
hwbm.c net: hwbm: Make the hwbm_pool lock a mutex 2019-06-09 19:40:10 -07:00
link_watch.c ipvlan: Fix use-after-free in ipvlan_get_iflink(). 2025-01-17 13:36:13 +01:00
lwt_bpf.c lwt: Fix return values of BPF xmit ops 2023-08-18 16:05:26 +02:00
lwtunnel.c net: lwtunnel: disable BHs when required 2025-05-02 07:50:43 +02:00
Makefile net: move gso declarations and functions to their own files 2023-06-10 00:11:41 -07:00
neighbour.c net/neighbor: add missing policy for NDTPA_QUEUE_LENBYTES 2025-03-28 21:59:53 +01:00
net-procfs.c net-sysfs: display two backlog queue len separately 2023-03-22 12:03:52 +01:00
net-sysfs.c ethtool: check device is present when getting link settings 2024-09-04 13:28:26 +02:00
net-sysfs.h net-sysfs: add netdev_change_owner() 2020-02-26 20:07:25 -08:00
net-traces.c udp6: add a missing call into udp_fail_queue_rcv_skb tracepoint 2023-07-07 09:16:52 +01:00
net_namespace.c net: add exit_batch_rtnl() method 2025-01-23 17:21:10 +01:00
netclassid_cgroup.c core: Variable type completion 2022-08-31 09:40:34 +01:00
netdev-genl-gen.c net: ynl: prefix uAPI header include with uapi/ 2023-05-26 10:30:14 +01:00
netdev-genl-gen.h net: ynl: prefix uAPI header include with uapi/ 2023-05-26 10:30:14 +01:00
netdev-genl.c netdev-genl: use struct genl_info for reply construction 2023-08-15 15:01:03 -07:00
netevent.c net: core: Correct function name netevent_unregister_notifier() in the kerneldoc 2021-03-28 17:56:56 -07:00
netpoll.c netpoll: hold rcu read lock in __netpoll_send_skb() 2025-03-22 12:50:38 -07:00
netprio_cgroup.c bpf, cgroups: Fix cgroup v2 fallback on v1/v2 mixed mode 2021-09-13 16:35:58 -07:00
of_net.c net: Explicitly include correct DT includes 2023-07-27 20:33:16 -07:00
page_pool.c page_pool: avoid infinite loop to schedule delayed worker 2025-04-25 10:45:14 +02:00
pktgen.c net: pktgen: fix access outside of user given buffer in pktgen_thread_write() 2025-06-04 14:42:07 +02:00
ptp_classifier.c ptp: Add generic PTP is_sync() function 2022-03-07 11:31:34 +00:00
request_sock.c tcp: make sure init the accept_queue's spinlocks once 2024-01-31 16:19:00 -08:00
rtnetlink.c rtnetlink: Allocate vfinfo size for VF GUIDs when supported 2025-04-10 14:37:35 +02:00
scm.c af_unix: Add dead flag to struct scm_fp_list. 2025-06-04 14:42:24 +02:00
secure_seq.c tcp: Fix data-races around sysctl knobs related to SYN option. 2022-07-20 10:14:49 +01:00
selftests.c net: selftests: initialize TCP header and skb payload with zero 2025-05-02 07:50:46 +02:00
skbuff.c ipvs: Always clear ipvs_property flag in skb_scrub_packet() 2025-03-07 16:45:40 +01:00
skmsg.c bpf, sockmap: Fix data lost during EAGAIN retries 2025-06-27 11:08:56 +01:00
sock.c sock: Correct error checking condition for (assign|release)_proto_idx() 2025-06-27 11:08:56 +01:00
sock_destructor.h skb_expand_head() adjust skb->truesize incorrectly 2021-10-22 12:35:51 -07:00
sock_diag.c net: use unrcu_pointer() helper 2024-12-09 10:32:10 +01:00
sock_map.c bpf: Disable non stream socket for strparser 2025-02-27 04:10:50 -08:00
sock_reuseport.c soreuseport: Fix socket selection for SO_INCOMING_CPU. 2022-10-25 11:35:16 +02:00
stream.c net: Return error from sk_stream_wait_connect() if sk_wait_event() fails 2024-01-01 12:42:30 +00:00
sysctl_net_core.c net: set the minimum for net_hotdata.netdev_budget_usecs 2025-03-07 16:45:38 +01:00
timestamping.c net: Introduce a new MII time stamping interface. 2019-12-25 19:51:33 -08:00
tso.c net: tso: inline tso_count_descs() 2022-12-12 15:04:39 -08:00
utils.c net: Fix checksum update for ILA adj-transport 2025-06-27 11:09:00 +01:00
xdp.c xdp: fix invalid wait context of page_pool_destroy() 2024-08-03 08:53:44 +02:00