* [PATCH net v2 0/2] net: psp: preserve SKB_EXT_PSP across packet scrubbing @ 2026-10-30 4:31 Wei Wang 2026-10-30 4:31 ` [PATCH net v2 1/2] net: Make PSP skb extension survive " Wei Wang 2026-10-30 4:31 ` [PATCH net v2 2/2] selftests/net: psp: test bidirectional data transfer Wei Wang 0 siblings, 2 replies; 4+ messages in thread From: Wei Wang @ 2026-10-30 4:31 UTC (permalink / raw) To: David S . Miller, Jakub Kicinski, Paolo Abeni, Andrew Lunn, Shuah Khan Cc: Simon Horman, Jakub Sitnicki, Daniel Zahka, Willem de Bruijn, netdev, linux-kselftest, linux-kernel, bpf, Wei Wang When a virtual interface such as netkit is associated with a PSP device in another network namespace via PSP_CMD_DEV_ASSOC, incoming PSP packets decapsulated on the physical device lose their SKB_EXT_PSP extension when scrubbed during redirection (e.g. skb_do_redirect() or netkit_xmit() calling skb_scrub_packet()). As a result, __psp_sk_rx_policy_check() rejects incoming PSP-encrypted TCP data segments at the socket layer. This gap slipped through the existing psp.py selftests because both _data_basic_send() and _data_basic_send_netkit_psp_assoc() only sent a unidirectional data stream from the test socket to psp_responder; the returning pure TCP ACKs had SKB_EXT_PSP stripped by skb_scrub_packet(), but were still accepted by __psp_sk_rx_policy_check() while peer_tx was unset. Patch 1 (originally from Jakub Sitnicki's BPF skb extension series [1]) introduces skb_ext_scrub() to selectively preserve SKB_EXT_PSP during skb_scrub_packet(). Patch 2 updates the psp.py selftests to exercise bidirectional PSP data transfer using psp_responder's "data echo" command in both direct and netkit dev-assoc test cases. Changes in v2: - Patch 1: Replace the skb_ext_del() loop in skb_ext_scrub() with skb_ext_reset() + skb_ext_add() (and a fast path when SKB_EXT_PSP is the only extension in the skb_ext buffer) so shared skb_ext buffers with refcounted extensions (SKB_EXT_SEC_PATH / SKB_EXT_MCTP) are not left half-deleted; clear skb->decrypted if skb_ext_add() fails. - Patch 1: Make skb_ext_scrub() static in net/core/skbuff.c and drop EXPORT_SYMBOL() / public header prototype. Link: https://lore.kernel.org/netdev/20260910-bpf-meta-inside-skb-ext-v2-3-0b21e42180b0@cloudflare.com/ [1] Wei Wang (2): net: Make PSP skb extension survive packet scrubbing selftests/net: psp: test bidirectional data transfer net/core/skbuff.c | 31 ++++++++++++++++++++-- tools/testing/selftests/drivers/net/psp.py | 8 ++++++ 2 files changed, 37 insertions(+), 2 deletions(-) -- 2.56.0.317.g454f8302e1-goog ^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH net v2 1/2] net: Make PSP skb extension survive packet scrubbing 2026-10-30 4:31 [PATCH net v2 0/2] net: psp: preserve SKB_EXT_PSP across packet scrubbing Wei Wang @ 2026-10-30 4:31 ` Wei Wang 2026-11-03 5:31 ` netdev-bot+sashiko 2026-10-30 4:31 ` [PATCH net v2 2/2] selftests/net: psp: test bidirectional data transfer Wei Wang 1 sibling, 1 reply; 4+ messages in thread From: Wei Wang @ 2026-10-30 4:31 UTC (permalink / raw) To: David S . Miller, Jakub Kicinski, Paolo Abeni, Andrew Lunn, Shuah Khan Cc: Simon Horman, Jakub Sitnicki, Daniel Zahka, Willem de Bruijn, netdev, linux-kselftest, linux-kernel, bpf, Wei Wang skb_scrub_packet() drops all skb extensions unconditionally via skb_ext_reset(). It runs on tunnel encap/decap (ip_tunnel_rcv, vxlan_rcv, etc.) and virtual device forwarding/redirection (dev_forward_skb, netkit_xmit, skb_do_redirect). When a virtual device such as netkit is associated with a PSP device in another network namespace via PSP_CMD_DEV_ASSOC, incoming PSP packets decapsulated by psp_dev_rcv() lose their SKB_EXT_PSP extension when scrubbed during redirection into the peer netns. Without SKB_EXT_PSP, __psp_sk_rx_policy_check() rejects incoming TCP data segments at the socket layer with SKB_DROP_REASON_PSP_INPUT. Introduce a static skb_ext_scrub() helper in net/core/skbuff.c to preserve SKB_EXT_PSP across skb_scrub_packet() while dropping all other extensions. If SKB_EXT_PSP is not active, skb_ext_scrub() simply calls skb_ext_reset(). If SKB_EXT_PSP is the only extension in the skb_ext buffer, nothing needs to be scrubbed. Otherwise, save the PSP metadata, reset the extension block, and re-add a fresh SKB_EXT_PSP extension (or clear skb->decrypted if the allocation fails). Fixes: 06c2dce2d0f6 ("psp: add new netlink cmd for dev-assoc and dev-disassoc") Link: https://lore.kernel.org/r/20260910-bpf-meta-inside-skb-ext-v2-3-0b21e42180b0@cloudflare.com Reported-by: Daniel Zahka <daniel.zahka@gmail.com> Closes: https://lore.kernel.org/netdev/DLODSKPY6ON6.1G6SP3CFFLCPJ@gmail.com/ Co-developed-by: Jakub Sitnicki <jakub@cloudflare.com> Signed-off-by: Jakub Sitnicki <jakub@cloudflare.com> Signed-off-by: Wei Wang <weiwan@google.com> --- net/core/skbuff.c | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 93c2f440b9ec..5c4a2e982ebc 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -6369,6 +6369,32 @@ bool skb_try_coalesce(struct sk_buff *to, struct sk_buff *from, } EXPORT_SYMBOL(skb_try_coalesce); +static void skb_ext_scrub(struct sk_buff *skb) +{ +#if IS_ENABLED(CONFIG_INET_PSP) + struct psp_skb_ext *pse = skb_ext_find(skb, SKB_EXT_PSP); + + if (pse) { + struct skb_ext *ext = skb->extensions; + struct psp_skb_ext tmp = *pse; + + /* Nothing else to scrub if PSP is the only extension in ext. */ + if (ext->chunks == SKB_EXT_CHUNKSIZEOF(*ext) + + skb_ext_type_len[SKB_EXT_PSP]) + return; + + skb_ext_reset(skb); + pse = skb_ext_add(skb, SKB_EXT_PSP); + if (pse) + memcpy(pse, &tmp, sizeof(*pse)); + else + skb->decrypted = 0; + return; + } +#endif + skb_ext_reset(skb); +} + /** * skb_scrub_packet - scrub an skb * @@ -6380,7 +6406,8 @@ EXPORT_SYMBOL(skb_try_coalesce); * operations. * skb_scrub_packet can also be used to clean a skb before injecting it in * another namespace (@xnet == true). We have to clear all information in the - * skb that could impact namespace isolation. + * skb that could impact namespace isolation. Note that PSP skb extension is + * preserved across packet scrubbing by design. */ void skb_scrub_packet(struct sk_buff *skb, bool xnet) { @@ -6388,7 +6415,7 @@ void skb_scrub_packet(struct sk_buff *skb, bool xnet) skb->skb_iif = 0; skb->ignore_df = 0; skb_dst_drop(skb); - skb_ext_reset(skb); + skb_ext_scrub(skb); nf_reset_ct(skb); nf_reset_trace(skb); -- 2.56.0.317.g454f8302e1-goog ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH net v2 1/2] net: Make PSP skb extension survive packet scrubbing 2026-10-30 4:31 ` [PATCH net v2 1/2] net: Make PSP skb extension survive " Wei Wang @ 2026-11-03 5:31 ` netdev-bot+sashiko 0 siblings, 0 replies; 4+ messages in thread From: netdev-bot+sashiko @ 2026-11-03 5:31 UTC (permalink / raw) To: weiwan Cc: davem, kuba, pabeni, andrew+netdev, shuah, horms, jakub, daniel.zahka, willemb, netdev, linux-kselftest, linux-kernel, bpf Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider. Critical: 0 · High: 0 · Medium: 1 · Low: 0 If you believe none of the issues are legitimate, please reply to each issue of Medium severity or higher and explain why the AI is wrong. If any of them are legitimate and you plan to respin, please let patchwork know by including "pw-bot: cr" as a separate line at the end of your reply (one such reply per series is enough). - [Medium] When re-adding SKB_EXT_PSP fails in skb_ext_scrub() (net/core/skbuff.c:6401), the code clears skb->decrypted and lets the… -- net: Make PSP skb extension survive packet scrubbing This commit adds a static skb_ext_scrub() helper, used by skb_scrub_packet() in place of skb_ext_reset(). The helper keeps SKB_EXT_PSP and drops every other extension. If re-adding the PSP extension fails, it clears skb->decrypted. Link: https://lore.kernel.org/r/20260910-bpf-meta-inside-skb-ext-v2-3-0b21e42180b0@cloudflare.com > diff --git a/net/core/skbuff.c b/net/core/skbuff.c > index 48f6764117243..6adb54674f1c9 100644 > --- a/net/core/skbuff.c > +++ b/net/core/skbuff.c > @@ -6379,6 +6379,32 @@ bool skb_try_coalesce(struct sk_buff *to, struct sk_buff *from, > } > EXPORT_SYMBOL(skb_try_coalesce); > > +static void skb_ext_scrub(struct sk_buff *skb) > +{ > +#if IS_ENABLED(CONFIG_INET_PSP) > + struct psp_skb_ext *pse = skb_ext_find(skb, SKB_EXT_PSP); > + > + if (pse) { > + struct skb_ext *ext = skb->extensions; > + struct psp_skb_ext tmp = *pse; > + > + /* Nothing else to scrub if PSP is the only extension in ext. */ > + if (ext->chunks == SKB_EXT_CHUNKSIZEOF(*ext) + > + skb_ext_type_len[SKB_EXT_PSP]) > + return; > + > + skb_ext_reset(skb); > + pse = skb_ext_add(skb, SKB_EXT_PSP); > + if (pse) > + memcpy(pse, &tmp, sizeof(*pse)); > + else > + skb->decrypted = 0; ^^^^ [Severity: Medium] If the GFP_ATOMIC allocation in skb_ext_add() fails, can a packet whose payload is already decrypted lose its decrypted mark and be sent out as plaintext? Before this patch, skb_scrub_packet() only called skb_ext_reset(), which leaves skb->decrypted alone. A HW-decrypted PSP RX packet, for example from mlx5e_psp_offload_handle_rx_skb(), keeps skb->decrypted = 1. If it is later forwarded, it is dropped in sk_validate_xmit_skb() in net/core/dev.c, because forwarded packets have no skb->sk: if (sk_validate) { skb = sk_validate(sk, dev, skb); } else if (unlikely(skb_is_decrypted(skb))) { pr_warn_ratelimited("unencrypted skb with no associated socket - dropping\n"); kfree_skb(skb); skb = NULL; } This branch is the path taken when the extension buffer holds something besides PSP, e.g. a TC_SKB_EXT or nf_bridge extension. On this path, if __skb_ext_alloc(GFP_ATOMIC) fails, skb->decrypted is cleared but the payload stays decrypted. The packet could then reach an egress device by either route: skb_do_redirect() (BPF_F_PEER) -> skb_scrub_packet() -> forwarded in the peer netns ip_tunnel_rcv() -> skb_scrub_packet() -> forwarded In both cases skb_is_decrypted() would return false, so the drop above is skipped. On the success path the same packet is still dropped. The check fails closed today, but on this failure path it would fail open. Would it be safer to drop the packet, or keep skb->decrypted set, when the PSP extension cannot be re-added? > + return; > + } > +#endif > + skb_ext_reset(skb); > +} > + [ ... ] -- Sashiko AI review · https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20261030043145.2185700-1-weiwan%40google.com ^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH net v2 2/2] selftests/net: psp: test bidirectional data transfer 2026-10-30 4:31 [PATCH net v2 0/2] net: psp: preserve SKB_EXT_PSP across packet scrubbing Wei Wang 2026-10-30 4:31 ` [PATCH net v2 1/2] net: Make PSP skb extension survive " Wei Wang @ 2026-10-30 4:31 ` Wei Wang 1 sibling, 0 replies; 4+ messages in thread From: Wei Wang @ 2026-10-30 4:31 UTC (permalink / raw) To: David S . Miller, Jakub Kicinski, Paolo Abeni, Andrew Lunn, Shuah Khan Cc: Simon Horman, Jakub Sitnicki, Daniel Zahka, Willem de Bruijn, netdev, linux-kselftest, linux-kernel, bpf, Wei Wang _data_basic_send() and _data_basic_send_netkit_psp_assoc() currently only verify unidirectional data transmission from the test socket to psp_responder. As a result, they do not exercise the receive path for PSP-encrypted TCP data segments arriving at the test socket (such as packets redirected across a netkit interface associated via dev-assoc, which relies on SKB_EXT_PSP surviving packet scrubbing). Use the existing "data echo" command in psp_responder to verify that the test socket can also receive PSP-encrypted data from the peer in both _data_basic_send() and _data_basic_send_netkit_psp_assoc(). Signed-off-by: Wei Wang <weiwan@google.com> --- tools/testing/selftests/drivers/net/psp.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tools/testing/selftests/drivers/net/psp.py b/tools/testing/selftests/drivers/net/psp.py index 473500901879..e507951b440b 100755 --- a/tools/testing/selftests/drivers/net/psp.py +++ b/tools/testing/selftests/drivers/net/psp.py @@ -120,6 +120,12 @@ def _check_data_rx(cfg, exp_len): ksft_eq(read_len, exp_len) +def _check_data_echo(cfg, s): + _send_with_ack(cfg, b'data echo\0') + s.settimeout(1.0) + ksft_eq(s.recv(5), b'echo\0') + + def _check_data_outq(s, exp_len, force_wait=False): outq = 0 for _ in range(10): @@ -478,6 +484,7 @@ def _data_basic_send(cfg, version, ipver): data_len = _send_careful(cfg, s, 100) _check_data_rx(cfg, data_len) + _check_data_echo(cfg, s) _close_psp_conn(cfg, s) @@ -726,6 +733,7 @@ def _data_basic_send_netkit_psp_assoc(cfg, version, ipver): data_len = _send_careful(cfg, sock, 100) _check_data_rx(cfg, data_len) + _check_data_echo(cfg, sock) _close_psp_conn(cfg, sock) -- 2.56.0.317.g454f8302e1-goog ^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-11-03 5:31 UTC | newest] Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2026-10-30 4:31 [PATCH net v2 0/2] net: psp: preserve SKB_EXT_PSP across packet scrubbing Wei Wang 2026-10-30 4:31 ` [PATCH net v2 1/2] net: Make PSP skb extension survive " Wei Wang 2026-11-03 5:31 ` netdev-bot+sashiko 2026-10-30 4:31 ` [PATCH net v2 2/2] selftests/net: psp: test bidirectional data transfer Wei Wang
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®