* [PATCH net 0/2] net: psp: avoid conflicts with skb->decrypted and sk_validate_xmit_skb()
@ 2026-09-10 23:46 Daniel Zahka
2026-09-10 23:46 ` [PATCH net 1/2] " Daniel Zahka
2026-09-10 23:46 ` [PATCH net 2/2] selftests: drv-net: psp: test PSP and TCP ULP mutual exclusion Daniel Zahka
0 siblings, 2 replies; 7+ messages in thread
From: Daniel Zahka @ 2026-09-10 23:46 UTC (permalink / raw)
To: Eric Dumazet, Neal Cardwell, Kuniyuki Iwashima, David S. Miller,
Jakub Kicinski, Paolo Abeni, Simon Horman, Willem de Bruijn,
Andrew Lunn, Shuah Khan
Cc: Willem de Bruijn, netdev, linux-kernel, linux-kselftest
Sashiko's review of commit da630d1da2b1 ("netdevsim: psp: drop tx key
ops") [1] showed that there is a hazard between psp and offloaded tls,
where both can clobber what the other set in the sk_validate_xmit_skb
callback.
It was discussed further on the mailing list [2], and it was pointed out
that there are conflicts with psp and non-offloaded tls both using the
skb->decrypted bit.
The simplest fix is to make psp and tls mutually exclusive. This series
goes a bit further and makes psp exclusive with all TCP ULPs. The PSP
implementation that we have is not designed to be used with any TCP ULP,
so don't allow a socket to have state for both.
[1]: https://sashiko.dev/#/patchset/20260903-psp-prep-v1-0-d47e9c4c375d%40gmail.com
[2]: https://lore.kernel.org/netdev/20260903-psp-prep-v1-0-d47e9c4c375d@gmail.com/
Signed-off-by: Daniel Zahka <daniel.zahka@gmail.com>
---
Daniel Zahka (2):
net: psp: avoid conflicts with skb->decrypted and sk_validate_xmit_skb()
selftests: drv-net: psp: test PSP and TCP ULP mutual exclusion
include/net/sock.h | 11 +++++++
net/core/sock.c | 7 +++++
net/ipv4/tcp_ulp.c | 4 +++
net/psp/psp_sock.c | 4 +++
tools/testing/selftests/drivers/net/config | 1 +
tools/testing/selftests/drivers/net/psp.py | 46 ++++++++++++++++++++++++++++++
6 files changed, 73 insertions(+)
---
base-commit: 78445023439506ebd83b86d40b1e428a3b309d4a
change-id: 20260909-psp-ktls-fix-47aa27d955f2
Best regards,
--
Daniel Zahka <daniel.zahka@gmail.com>
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH net 1/2] net: psp: avoid conflicts with skb->decrypted and sk_validate_xmit_skb()
2026-09-10 23:46 [PATCH net 0/2] net: psp: avoid conflicts with skb->decrypted and sk_validate_xmit_skb() Daniel Zahka
@ 2026-09-10 23:46 ` Daniel Zahka
2026-09-12 0:29 ` netdev-bot+sashiko
2026-09-12 0:53 ` Daniel Zahka
2026-09-10 23:46 ` [PATCH net 2/2] selftests: drv-net: psp: test PSP and TCP ULP mutual exclusion Daniel Zahka
1 sibling, 2 replies; 7+ messages in thread
From: Daniel Zahka @ 2026-09-10 23:46 UTC (permalink / raw)
To: Eric Dumazet, Neal Cardwell, Kuniyuki Iwashima, David S. Miller,
Jakub Kicinski, Paolo Abeni, Simon Horman, Willem de Bruijn,
Andrew Lunn, Shuah Khan
Cc: Willem de Bruijn, netdev, linux-kernel, linux-kselftest
PSP conflicts with TLS ULP in its usage of both skb->decrypted and
sk->sk_validate_xmit_skb(). Offloaded TLS conflicts on both sides in
both Tx and Rx. SW TLS could mistake skb->decrypted in the Rx path set
by a PSP device as being a decrypted TLS record.
Prevent PSP from being used with other socket features that use
skb->decrypted or sk->sk_validate_xmit_skb().
For now, we include all TCP ULPs in the sk_has_decrypt_user() check,
even though TLS is the only one that conflicts with PSP via the
decrypted bit. This is intentional because PSP was not designed to be
used with ULPs. It is best to close off surface area that may make bugs
reachable, until someone wishes to design and test an actual user of PSP
with ULPs.
Fixes: 6b46ca260e22 ("net: psp: add socket security association code")
Signed-off-by: Daniel Zahka <daniel.zahka@gmail.com>
---
include/net/sock.h | 11 +++++++++++
net/core/sock.c | 7 +++++++
net/ipv4/tcp_ulp.c | 4 ++++
net/psp/psp_sock.c | 4 ++++
4 files changed, 26 insertions(+)
diff --git a/include/net/sock.h b/include/net/sock.h
index 51185222aac2..ba5e5092f192 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -2312,6 +2312,17 @@ static inline void sk_gso_disable(struct sock *sk)
sk->sk_route_caps &= ~NETIF_F_GSO_MASK;
}
+static inline bool sk_has_validate_xmit_skb(const struct sock *sk)
+{
+#ifdef CONFIG_SOCK_VALIDATE_XMIT
+ return !!sk->sk_validate_xmit_skb;
+#else
+ return false;
+#endif
+}
+
+bool sk_has_decrypt_user(const struct sock *sk);
+
static inline int skb_do_copy_data_nocache(struct sock *sk, struct sk_buff *skb,
struct iov_iter *from, char *to,
int copy, int offset)
diff --git a/net/core/sock.c b/net/core/sock.c
index fa60b7494c58..9489d9c47949 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -142,6 +142,7 @@
#include <trace/events/sock.h>
+#include <net/psp.h>
#include <net/tcp.h>
#include <net/busy_poll.h>
#include <net/phonet/phonet.h>
@@ -2670,6 +2671,12 @@ void sk_setup_caps(struct sock *sk, struct dst_entry *dst)
}
EXPORT_SYMBOL_GPL(sk_setup_caps);
+bool sk_has_decrypt_user(const struct sock *sk)
+{
+ return psp_sk_assoc(sk) ||
+ (sk_is_inet(sk) && inet_csk_has_ulp(sk)); /* for tls */
+}
+
/*
* Simple resource managers for sockets.
*/
diff --git a/net/ipv4/tcp_ulp.c b/net/ipv4/tcp_ulp.c
index 2aa442128630..f3e0c9d379bb 100644
--- a/net/ipv4/tcp_ulp.c
+++ b/net/ipv4/tcp_ulp.c
@@ -136,6 +136,10 @@ static int __tcp_set_ulp(struct sock *sk, const struct tcp_ulp_ops *ulp_ops)
if (icsk->icsk_ulp_ops)
goto out_err;
+ err = -EINVAL;
+ if (sk_has_decrypt_user(sk) || sk_has_validate_xmit_skb(sk))
+ goto out_err;
+
if (sk->sk_socket)
clear_bit(SOCK_SUPPORT_ZC, &sk->sk_socket->flags);
diff --git a/net/psp/psp_sock.c b/net/psp/psp_sock.c
index 1a2a6b7516b0..509035617894 100644
--- a/net/psp/psp_sock.c
+++ b/net/psp/psp_sock.c
@@ -143,6 +143,10 @@ int psp_sock_assoc_set_rx(struct sock *sk, struct psp_assoc *pas,
NL_SET_ERR_MSG(extack, "Socket already has PSP state");
err = -EBUSY;
goto exit_unlock;
+ } else if (sk_has_decrypt_user(sk) || sk_has_validate_xmit_skb(sk)) {
+ NL_SET_ERR_MSG(extack, "Socket has incompatible state");
+ err = -EINVAL;
+ goto exit_unlock;
}
refcount_inc(&pas->refcnt);
--
2.52.0
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH net 2/2] selftests: drv-net: psp: test PSP and TCP ULP mutual exclusion
2026-09-10 23:46 [PATCH net 0/2] net: psp: avoid conflicts with skb->decrypted and sk_validate_xmit_skb() Daniel Zahka
2026-09-10 23:46 ` [PATCH net 1/2] " Daniel Zahka
@ 2026-09-10 23:46 ` Daniel Zahka
2026-09-11 10:57 ` Daniel Zahka
1 sibling, 1 reply; 7+ messages in thread
From: Daniel Zahka @ 2026-09-10 23:46 UTC (permalink / raw)
To: Eric Dumazet, Neal Cardwell, Kuniyuki Iwashima, David S. Miller,
Jakub Kicinski, Paolo Abeni, Simon Horman, Willem de Bruijn,
Andrew Lunn, Shuah Khan
Cc: Willem de Bruijn, netdev, linux-kernel, linux-kselftest
Test both setting PSP after TLS ULP, and TLS ULP after PSP.
Add CONFIG_TLS=y to the drivers/net/config.
Signed-off-by: Daniel Zahka <daniel.zahka@gmail.com>
---
tools/testing/selftests/drivers/net/config | 1 +
tools/testing/selftests/drivers/net/psp.py | 46 ++++++++++++++++++++++++++++++
2 files changed, 47 insertions(+)
diff --git a/tools/testing/selftests/drivers/net/config b/tools/testing/selftests/drivers/net/config
index b6989c7d3d9d..4838adf27fa1 100644
--- a/tools/testing/selftests/drivers/net/config
+++ b/tools/testing/selftests/drivers/net/config
@@ -21,5 +21,6 @@ CONFIG_NET_SCH_INGRESS=y
CONFIG_NET_SCH_PRIO=m
CONFIG_PPP=y
CONFIG_PPPOE=y
+CONFIG_TLS=y
CONFIG_VLAN_8021Q=m
CONFIG_XDP_SOCKETS=y
diff --git a/tools/testing/selftests/drivers/net/psp.py b/tools/testing/selftests/drivers/net/psp.py
index 315648a770d0..12b27f2a3fa1 100755
--- a/tools/testing/selftests/drivers/net/psp.py
+++ b/tools/testing/selftests/drivers/net/psp.py
@@ -23,6 +23,8 @@ from lib.py import NetNSEnter
from lib.py import bkg, rand_port, wait_port_listen
from lib.py import ip
+TCP_ULP = 31
+
def _get_outq(s):
one = b'\0' * 4
@@ -333,6 +335,50 @@ def assoc_version_mismatch(cfg):
ksft_eq(the_exception.nl_msg.error, -errno.EINVAL)
+def _require_tls_ulp():
+ with socket.create_server(("localhost", 0)) as srv:
+ with socket.create_connection(srv.getsockname()) as s:
+ try:
+ s.setsockopt(socket.SOL_TCP, TCP_ULP, b"tls")
+ except OSError as exc:
+ raise KsftSkipEx("kTLS not available") from exc
+
+
+def assoc_psp_ulp_exclusive(cfg):
+ """ Test that a TCP ULP cannot be attached to a PSP socket """
+ _init_psp_dev(cfg)
+ _require_tls_ulp()
+
+ with _make_clr_conn(cfg) as s:
+ try:
+ cfg.pspnl.rx_assoc({"version": 0,
+ "dev-id": cfg.psp_dev_id,
+ "sock-fd": s.fileno()})
+ with ksft_raises(OSError) as cm:
+ s.setsockopt(socket.SOL_TCP, TCP_ULP, b"tls")
+ ksft_eq(cm.exception.errno, errno.EINVAL)
+ finally:
+ _close_conn(cfg, s)
+
+
+def assoc_ulp_psp_exclusive(cfg):
+ """ Test that a PSP assoc cannot be added to a socket with a TCP ULP """
+ _init_psp_dev(cfg)
+ _require_tls_ulp()
+
+ with _make_clr_conn(cfg) as s:
+ try:
+ s.setsockopt(socket.SOL_TCP, TCP_ULP, b"tls")
+ with ksft_raises(NlError) as cm:
+ cfg.pspnl.rx_assoc({"version": 0,
+ "dev-id": cfg.psp_dev_id,
+ "sock-fd": s.fileno()})
+ ksft_eq(cm.exception.nl_msg.error, -errno.EINVAL)
+ ksft_eq(cm.exception.nl_msg.extack['bad-attr'], ".sock-fd")
+ finally:
+ _close_conn(cfg, s)
+
+
def assoc_twice(cfg):
""" Test reusing Tx assoc for two sockets """
_init_psp_dev(cfg)
--
2.52.0
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH net 2/2] selftests: drv-net: psp: test PSP and TCP ULP mutual exclusion
2026-09-10 23:46 ` [PATCH net 2/2] selftests: drv-net: psp: test PSP and TCP ULP mutual exclusion Daniel Zahka
@ 2026-09-11 10:57 ` Daniel Zahka
2026-09-11 20:00 ` Matthieu Baerts
0 siblings, 1 reply; 7+ messages in thread
From: Daniel Zahka @ 2026-09-11 10:57 UTC (permalink / raw)
To: Daniel Zahka, Eric Dumazet, Neal Cardwell, Kuniyuki Iwashima,
David S. Miller, Jakub Kicinski, Paolo Abeni, Simon Horman,
Willem de Bruijn, Andrew Lunn, Shuah Khan
Cc: Willem de Bruijn, netdev, linux-kernel, linux-kselftest
On Thu Sep 10, 2026 at 7:46 PM EDT, Daniel Zahka wrote:
> Test both setting PSP after TLS ULP, and TLS ULP after PSP.
>
> Add CONFIG_TLS=y to the drivers/net/config.
>
> Signed-off-by: Daniel Zahka <daniel.zahka@gmail.com>
> ---
> tools/testing/selftests/drivers/net/config | 1 +
> tools/testing/selftests/drivers/net/psp.py | 46 ++++++++++++++++++++++++++++++
> 2 files changed, 47 insertions(+)
>
> diff --git a/tools/testing/selftests/drivers/net/config b/tools/testing/selftests/drivers/net/config
> index b6989c7d3d9d..4838adf27fa1 100644
> --- a/tools/testing/selftests/drivers/net/config
> +++ b/tools/testing/selftests/drivers/net/config
> @@ -21,5 +21,6 @@ CONFIG_NET_SCH_INGRESS=y
> CONFIG_NET_SCH_PRIO=m
> CONFIG_PPP=y
> CONFIG_PPPOE=y
> +CONFIG_TLS=y
> CONFIG_VLAN_8021Q=m
> CONFIG_XDP_SOCKETS=y
> diff --git a/tools/testing/selftests/drivers/net/psp.py b/tools/testing/selftests/drivers/net/psp.py
> index 315648a770d0..12b27f2a3fa1 100755
> --- a/tools/testing/selftests/drivers/net/psp.py
> +++ b/tools/testing/selftests/drivers/net/psp.py
> @@ -23,6 +23,8 @@ from lib.py import NetNSEnter
> from lib.py import bkg, rand_port, wait_port_listen
> from lib.py import ip
>
> +TCP_ULP = 31
> +
>
> def _get_outq(s):
> one = b'\0' * 4
> @@ -333,6 +335,50 @@ def assoc_version_mismatch(cfg):
> ksft_eq(the_exception.nl_msg.error, -errno.EINVAL)
>
>
> +def _require_tls_ulp():
> + with socket.create_server(("localhost", 0)) as srv:
> + with socket.create_connection(srv.getsockname()) as s:
ruff is complaining about the nested 'with' statements. I ran ruff
locally via nipa, but did not get the same result. It seems nipa doesn't
use a ruff config file, and the discrepancy is because I have a
different ruff version. I was able to reproduce by upgrading the
version.
> + try:
> + s.setsockopt(socket.SOL_TCP, TCP_ULP, b"tls")
> + except OSError as exc:
> + raise KsftSkipEx("kTLS not available") from exc
> +
> +
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH net 2/2] selftests: drv-net: psp: test PSP and TCP ULP mutual exclusion
2026-09-11 10:57 ` Daniel Zahka
@ 2026-09-11 20:00 ` Matthieu Baerts
0 siblings, 0 replies; 7+ messages in thread
From: Matthieu Baerts @ 2026-09-11 20:00 UTC (permalink / raw)
To: Daniel Zahka, Eric Dumazet, Neal Cardwell, Kuniyuki Iwashima,
David S. Miller, Jakub Kicinski, Paolo Abeni, Simon Horman,
Willem de Bruijn, Andrew Lunn, Shuah Khan
Cc: Willem de Bruijn, netdev, linux-kernel, linux-kselftest
Hi Daniel,
On 11/09/2026 12:57, Daniel Zahka wrote:
> On Thu Sep 10, 2026 at 7:46 PM EDT, Daniel Zahka wrote:
>> Test both setting PSP after TLS ULP, and TLS ULP after PSP.
>>
>> Add CONFIG_TLS=y to the drivers/net/config.
>>
>> Signed-off-by: Daniel Zahka <daniel.zahka@gmail.com>
>> ---
>> tools/testing/selftests/drivers/net/config | 1 +
>> tools/testing/selftests/drivers/net/psp.py | 46 ++++++++++++++++++++++++++++++
>> 2 files changed, 47 insertions(+)
>>
>> diff --git a/tools/testing/selftests/drivers/net/config b/tools/testing/selftests/drivers/net/config
>> index b6989c7d3d9d..4838adf27fa1 100644
>> --- a/tools/testing/selftests/drivers/net/config
>> +++ b/tools/testing/selftests/drivers/net/config
>> @@ -21,5 +21,6 @@ CONFIG_NET_SCH_INGRESS=y
>> CONFIG_NET_SCH_PRIO=m
>> CONFIG_PPP=y
>> CONFIG_PPPOE=y
>> +CONFIG_TLS=y
>> CONFIG_VLAN_8021Q=m
>> CONFIG_XDP_SOCKETS=y
>> diff --git a/tools/testing/selftests/drivers/net/psp.py b/tools/testing/selftests/drivers/net/psp.py
>> index 315648a770d0..12b27f2a3fa1 100755
>> --- a/tools/testing/selftests/drivers/net/psp.py
>> +++ b/tools/testing/selftests/drivers/net/psp.py
>> @@ -23,6 +23,8 @@ from lib.py import NetNSEnter
>> from lib.py import bkg, rand_port, wait_port_listen
>> from lib.py import ip
>>
>> +TCP_ULP = 31
>> +
>>
>> def _get_outq(s):
>> one = b'\0' * 4
>> @@ -333,6 +335,50 @@ def assoc_version_mismatch(cfg):
>> ksft_eq(the_exception.nl_msg.error, -errno.EINVAL)
>>
>>
>> +def _require_tls_ulp():
>> + with socket.create_server(("localhost", 0)) as srv:
>> + with socket.create_connection(srv.getsockname()) as s:
>
> ruff is complaining about the nested 'with' statements. I ran ruff
> locally via nipa, but did not get the same result. It seems nipa doesn't
> use a ruff config file, and the discrepancy is because I have a
> different ruff version. I was able to reproduce by upgrading the
> version.
FYI, the CI is using the 'ruff' package from the Fedora repo. If it
helps, you can use the NIPA "build" container to have the same environment:
https://github.com/linux-netdev/nipa/wiki/Running-Netdev-CI-tests-locally#static-tests
Cheers,
Matt
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH net 1/2] net: psp: avoid conflicts with skb->decrypted and sk_validate_xmit_skb()
2026-09-10 23:46 ` [PATCH net 1/2] " Daniel Zahka
@ 2026-09-12 0:29 ` netdev-bot+sashiko
2026-09-12 0:53 ` Daniel Zahka
1 sibling, 0 replies; 7+ messages in thread
From: netdev-bot+sashiko @ 2026-09-12 0:29 UTC (permalink / raw)
To: daniel.zahka
Cc: edumazet, ncardwell, kuniyu, davem, kuba, pabeni, horms,
willemdebruijn.kernel, andrew+netdev, shuah, willemb, netdev,
linux-kernel, linux-kselftest
Thank you for your contribution! Sashiko AI review found 1 potential
issue(s) to consider:
Critical: 0 · High: 0 · Medium: 1 · Low: 0
- [Medium] The new mutual-exclusion gate keys off
`sk->sk_validate_xmit_skb`, a function pointer that is inherited…
--
net: psp: avoid conflicts with skb->decrypted and sk_validate_xmit_skb()
This adds a mutual exclusion gate so that a socket cannot carry both PSP
state and a TCP ULP, since the two conflict over skb->decrypted and
sk->sk_validate_xmit_skb(). The gate is applied in __tcp_set_ulp() and in
psp_sock_assoc_set_rx().
> diff --git a/include/net/sock.h b/include/net/sock.h
> index 51185222aac29..ba5e5092f192c 100644
> --- a/include/net/sock.h
> +++ b/include/net/sock.h
> @@ -2312,6 +2312,17 @@ static inline void sk_gso_disable(struct sock *sk)
> sk->sk_route_caps &= ~NETIF_F_GSO_MASK;
> }
>
> +static inline bool sk_has_validate_xmit_skb(const struct sock *sk)
> +{
> +#ifdef CONFIG_SOCK_VALIDATE_XMIT
> + return !!sk->sk_validate_xmit_skb;
> +#else
> + return false;
> +#endif
> +}
[Severity: Medium]
Is sk_validate_xmit_skb a reliable indicator of live per-socket state here?
The field sits after sk_dontcopy_end in struct sock, so sock_copy() copies
it verbatim into a cloned socket, and neither sk_clone() nor
inet_csk_clone_lock() resets it. By contrast, sk_clone() does explicitly
clear the PSP association:
net/core/sock.c:sk_clone() {
sock_copy(newsk, sk);
...
#if IS_ENABLED(CONFIG_INET_PSP)
RCU_INIT_POINTER(newsk->psp_assoc, NULL);
#endif
So a socket accepted from a listener that had PSP Tx state installed ends up
with sk_validate_xmit_skb == psp_validate_xmit while psp_assoc == NULL, and
sk_has_validate_xmit_skb() then reports true for a child that has neither a
PSP association nor a ULP.
Can PSP state be installed on a listening socket in the first place? The only
socket check before installation appears to be in psp_nl.c:
net/psp/psp_nl.c:psp_assoc_device_get_locked() {
...
if (!sk_is_tcp(socket->sk)) {
and neither psp_sock_assoc_set_rx() nor psp_sock_assoc_set_tx() inspects
sk_state, while psp_sock_assoc_set_tx() does:
net/psp/psp_sock.c:psp_sock_assoc_set_tx() {
...
WRITE_ONCE(sk->sk_validate_xmit_skb, psp_validate_xmit);
> +
> +bool sk_has_decrypt_user(const struct sock *sk);
> +
> static inline int skb_do_copy_data_nocache(struct sock *sk, struct sk_buff *skb,
> struct iov_iter *from, char *to,
> int copy, int offset)
> diff --git a/net/core/sock.c b/net/core/sock.c
> index fa60b7494c586..9489d9c479493 100644
> --- a/net/core/sock.c
> +++ b/net/core/sock.c
[ ... ]
> @@ -2670,6 +2671,12 @@ void sk_setup_caps(struct sock *sk, struct dst_entry *dst)
> }
> EXPORT_SYMBOL_GPL(sk_setup_caps);
>
> +bool sk_has_decrypt_user(const struct sock *sk)
> +{
> + return psp_sk_assoc(sk) ||
> + (sk_is_inet(sk) && inet_csk_has_ulp(sk)); /* for tls */
> +}
> +
> /*
> * Simple resource managers for sockets.
> */
> diff --git a/net/ipv4/tcp_ulp.c b/net/ipv4/tcp_ulp.c
> index 2aa442128630e..f3e0c9d379bb6 100644
> --- a/net/ipv4/tcp_ulp.c
> +++ b/net/ipv4/tcp_ulp.c
> @@ -136,6 +136,10 @@ static int __tcp_set_ulp(struct sock *sk, const struct tcp_ulp_ops *ulp_ops)
> if (icsk->icsk_ulp_ops)
> goto out_err;
>
> + err = -EINVAL;
> + if (sk_has_decrypt_user(sk) || sk_has_validate_xmit_skb(sk))
> + goto out_err;
> +
[Severity: Medium]
For such an accepted child, sk_has_decrypt_user() returns false (psp_assoc is
NULL and there is no ULP yet), but sk_has_validate_xmit_skb() returns true
from the inherited pointer, so setsockopt(TCP_ULP) now fails with -EINVAL for
every socket accepted from that listener.
Before this patch the stale pointer was harmless, since psp_validate_xmit()
reads the association from the skb extension and treats a NULL association as
good. Should the check key off live per-socket state via psp_sk_assoc()
instead, or should sk_validate_xmit_skb be cleared in sk_clone() next to the
existing psp_assoc reset?
> if (sk->sk_socket)
> clear_bit(SOCK_SUPPORT_ZC, &sk->sk_socket->flags);
>
> diff --git a/net/psp/psp_sock.c b/net/psp/psp_sock.c
> index 1a2a6b7516b0f..509035617894a 100644
> --- a/net/psp/psp_sock.c
> +++ b/net/psp/psp_sock.c
> @@ -143,6 +143,10 @@ int psp_sock_assoc_set_rx(struct sock *sk, struct psp_assoc *pas,
> NL_SET_ERR_MSG(extack, "Socket already has PSP state");
> err = -EBUSY;
> goto exit_unlock;
> + } else if (sk_has_decrypt_user(sk) || sk_has_validate_xmit_skb(sk)) {
> + NL_SET_ERR_MSG(extack, "Socket has incompatible state");
> + err = -EINVAL;
> + goto exit_unlock;
> }
[Severity: Medium]
The same inherited pointer hits this branch too: the psp_sk_assoc(sk) test
above passes because the child's association was cleared, then this else-if
fires on sk_validate_xmit_skb and returns -EINVAL with "Socket has
incompatible state". Does that mean PSP itself can no longer be set up on any
socket accepted from a listener that had PSP Tx state?
Also worth noting on reachability: PSP_CMD_RX_ASSOC and PSP_CMD_TX_ASSOC carry
only GENL_CMD_CAP_DO in net/psp/psp-nl-gen.c, without GENL_ADMIN_PERM, so a
process with access to the PSP device can install the association on a
TCP_LISTEN fd. On a listener the preconditions in psp_sock_assoc_set_tx()
hold: psp_sock_recv_queue_check() walks empty queues and returns 0,
tcp_write_collapse_fence() is a no-op on the empty write queue, and
icsk_sync_mss is tcp_sync_mss from tcp_init_sock().
The follow-up commit in the series, "selftests: drv-net: psp: test PSP and TCP
ULP mutual exclusion", only touches tools/testing/selftests, so this case does
not appear to be addressed later in the series.
>
> refcount_inc(&pas->refcnt);
--
Sashiko AI review · https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20260910-psp-ktls-fix-v1-0-e3f30aaeca4e%40gmail.com
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH net 1/2] net: psp: avoid conflicts with skb->decrypted and sk_validate_xmit_skb()
2026-09-10 23:46 ` [PATCH net 1/2] " Daniel Zahka
2026-09-12 0:29 ` netdev-bot+sashiko
@ 2026-09-12 0:53 ` Daniel Zahka
1 sibling, 0 replies; 7+ messages in thread
From: Daniel Zahka @ 2026-09-12 0:53 UTC (permalink / raw)
To: Daniel Zahka, Eric Dumazet, Neal Cardwell, Kuniyuki Iwashima,
David S. Miller, Jakub Kicinski, Paolo Abeni, Simon Horman,
Willem de Bruijn, Andrew Lunn, Shuah Khan
Cc: Willem de Bruijn, netdev, linux-kernel, linux-kselftest
On Thu Sep 10, 2026 at 7:46 PM EDT, Daniel Zahka wrote:
> PSP conflicts with TLS ULP in its usage of both skb->decrypted and
> sk->sk_validate_xmit_skb(). Offloaded TLS conflicts on both sides in
> both Tx and Rx. SW TLS could mistake skb->decrypted in the Rx path set
> by a PSP device as being a decrypted TLS record.
>
> Prevent PSP from being used with other socket features that use
> skb->decrypted or sk->sk_validate_xmit_skb().
>
> For now, we include all TCP ULPs in the sk_has_decrypt_user() check,
> even though TLS is the only one that conflicts with PSP via the
> decrypted bit. This is intentional because PSP was not designed to be
> used with ULPs. It is best to close off surface area that may make bugs
> reachable, until someone wishes to design and test an actual user of PSP
> with ULPs.
>
> Fixes: 6b46ca260e22 ("net: psp: add socket security association code")
> Signed-off-by: Daniel Zahka <daniel.zahka@gmail.com>
> ---
sashiko and clashiko both point out that sk_clone() is still broken if
the listener socket has psp assoc tx state. In this case, the
sk->sk_validate_xmit_skb function is not cleared out in the cloned
socket.
In sashiko's eyes, this patch constitutes a regression, because before
the stale validate callback would mostly just be a waste of instructions
on the child socket, whereas after this commit the child, without psp
assoc state, would be ineligible for rx assoc.
I think we should remove the ability to attach psp assoc state to
listener sockets. I don't see a simple path towards making that a useful
feature given the current model we have for psp that is very much geared
towards upgrading from established state.
As a reference, Google's psp repo [1] demonstrates listening sockets
accepting a psp encrypted TCP SYN, and replying with an encrypted SYN
ACK. To make that work requires exchanging keys beforehand, and pre
installing the psp state per connection on the listening socket. That is
a completely different connection model.
[1]: https://github.com/google/psp/tree/linux-v5.15-psp-v1.0
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2026-09-12 0:53 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-10 23:46 [PATCH net 0/2] net: psp: avoid conflicts with skb->decrypted and sk_validate_xmit_skb() Daniel Zahka
2026-09-10 23:46 ` [PATCH net 1/2] " Daniel Zahka
2026-09-12 0:29 ` netdev-bot+sashiko
2026-09-12 0:53 ` Daniel Zahka
2026-09-10 23:46 ` [PATCH net 2/2] selftests: drv-net: psp: test PSP and TCP ULP mutual exclusion Daniel Zahka
2026-09-11 10:57 ` Daniel Zahka
2026-09-11 20:00 ` Matthieu Baerts
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®