Merge branch 'net-psp-avoid-conflicts-with-skb-decrypted-and-sk_validate_xmit_skb'

Daniel Zahka says:

====================
net: psp: avoid conflicts with skb->decrypted and sk_validate_xmit_skb()

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 TLS ULP 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.

I will send a subsequent series to net-next which will remove the
ability to perform the rx-assoc and tx-assoc psp netlink calls on
sockets that are not in the TCP_ESTABLISHED state. This will close the
remaining quirk that a sk_clone() on a listen socket with psp tx-assoc
state will leave a stale sk->sk_validate_xmit_skb call back on a new,
non-psp socket. I do not believe that change needs to be regarded as a
fix, because it only stands to add unecessary validation code in the tx
path.

[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/
====================

Link: https://patch.msgid.link/20260915-psp-ktls-fix-v2-0-0eedc3b148ec@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Jakub Kicinski 2026-09-16 19:18:26 -07:00
commit c9151088f1
6 changed files with 64 additions and 0 deletions

View File

@ -2312,6 +2312,8 @@ static inline void sk_gso_disable(struct sock *sk)
sk->sk_route_caps &= ~NETIF_F_GSO_MASK;
}
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)

View File

@ -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.
*/

View File

@ -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))
goto out_err;
if (sk->sk_socket)
clear_bit(SOCK_SUPPORT_ZC, &sk->sk_socket->flags);

View File

@ -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)) {
NL_SET_ERR_MSG(extack, "Socket has incompatible state");
err = -EINVAL;
goto exit_unlock;
}
refcount_inc(&pas->refcnt);

View File

@ -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

View File

@ -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, \
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)