diff --git a/kernel/build/patches/README.md b/kernel/build/patches/README.md index 3d0212dd3..b2033d978 100644 --- a/kernel/build/patches/README.md +++ b/kernel/build/patches/README.md @@ -1,3 +1,3 @@ | Patch file | Description | Upstream status | Link | |----------------------------------------------------------------------------|--------------------------------------------|-----------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| mpt3sas-ubsan.patch | Backport fixes for UBSAN reporting | in 6.8 | Commit fd7090e384725edb1910a4b0a9c51007858f2c81 | +| blackhole.patch | Backport fixes for blackhole device sending packets without Ethernet header | in 6.14 | Commit 0e4427f8f587c4b603475468bb3aee9418574893 | diff --git a/kernel/build/patches/blackhole.patch b/kernel/build/patches/blackhole.patch new file mode 100644 index 000000000..5823f90c1 --- /dev/null +++ b/kernel/build/patches/blackhole.patch @@ -0,0 +1,89 @@ +From 0e4427f8f587c4b603475468bb3aee9418574893 Mon Sep 17 00:00:00 2001 +From: Ido Schimmel +Date: Thu, 20 Feb 2025 09:25:59 +0200 +Subject: net: loopback: Avoid sending IP packets without an Ethernet header + +After commit 22600596b675 ("ipv4: give an IPv4 dev to blackhole_netdev") +IPv4 neighbors can be constructed on the blackhole net device, but they +are constructed with an output function (neigh_direct_output()) that +simply calls dev_queue_xmit(). The latter will transmit packets via +'skb->dev' which might not be the blackhole net device if dst_dev_put() +switched 'dst->dev' to the blackhole net device while another CPU was +using the dst entry in ip_output(), but after it already initialized +'skb->dev' from 'dst->dev'. + +Specifically, the following can happen: + + CPU1 CPU2 + +udp_sendmsg(sk1) udp_sendmsg(sk2) +udp_send_skb() [...] +ip_output() + skb->dev = skb_dst(skb)->dev + dst_dev_put() + dst->dev = blackhole_netdev +ip_finish_output2() + resolves neigh on dst->dev +neigh_output() +neigh_direct_output() +dev_queue_xmit() + +This will result in IPv4 packets being sent without an Ethernet header +via a valid net device: + +tcpdump: verbose output suppressed, use -v[v]... for full protocol decode +listening on enp9s0, link-type EN10MB (Ethernet), snapshot length 262144 bytes +22:07:02.329668 20:00:40:11:18:fb > 45:00:00:44:f4:94, ethertype Unknown +(0x58c6), length 68: + 0x0000: 8dda 74ca f1ae ca6c ca6c 0098 969c 0400 ..t....l.l...... + 0x0010: 0000 4730 3f18 6800 0000 0000 0000 9971 ..G0?.h........q + 0x0020: c4c9 9055 a157 0a70 9ead bf83 38ca ab38 ...U.W.p....8..8 + 0x0030: 8add ab96 e052 .....R + +Fix by making sure that neighbors are constructed on top of the +blackhole net device with an output function that simply consumes the +packets, in a similar fashion to dst_discard_out() and +blackhole_netdev_xmit(). + +Fixes: 8d7017fd621d ("blackhole_netdev: use blackhole_netdev to invalidate dst entries") +Fixes: 22600596b675 ("ipv4: give an IPv4 dev to blackhole_netdev") +Reported-by: Florian Meister +Closes: https://lore.kernel.org/netdev/20250210084931.23a5c2e4@hermes.local/ +Signed-off-by: Ido Schimmel +Reviewed-by: Eric Dumazet +Link: https://patch.msgid.link/20250220072559.782296-1-idosch@nvidia.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/loopback.c | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c +index c8840c3b9a1bc7..f1d68153987e1b 100644 +--- a/drivers/net/loopback.c ++++ b/drivers/net/loopback.c +@@ -244,8 +244,22 @@ static netdev_tx_t blackhole_netdev_xmit(struct sk_buff *skb, + return NETDEV_TX_OK; + } + ++static int blackhole_neigh_output(struct neighbour *n, struct sk_buff *skb) ++{ ++ kfree_skb(skb); ++ return 0; ++} ++ ++static int blackhole_neigh_construct(struct net_device *dev, ++ struct neighbour *n) ++{ ++ n->output = blackhole_neigh_output; ++ return 0; ++} ++ + static const struct net_device_ops blackhole_netdev_ops = { + .ndo_start_xmit = blackhole_netdev_xmit, ++ .ndo_neigh_construct = blackhole_neigh_construct, + }; + + /* This is a dst-dummy device used specifically for invalidated +-- +cgit 1.2.3-korg + diff --git a/kernel/build/pkg.yaml b/kernel/build/pkg.yaml index d8e213999..3af3fd9d2 100644 --- a/kernel/build/pkg.yaml +++ b/kernel/build/pkg.yaml @@ -16,6 +16,7 @@ steps: cd /src for patch in $(find /pkg/patches -type f -name "*.patch" | sort); do patch -p1 < $patch || (echo "Failed to apply patch $patch" && exit 1) + echo "Applied patch $patch" done build: {{ if .BUILD_ARG_KERNEL_TARGET }}