tls: reject the combination of TLS and sockmap
Subsystems (7)
Jakub Kicinski
maintainercover tls: reject the combination of TLS and sockmap
There are no known TLS+sockmap users and it has some known hard to solve bugs. Let's reject this configuration as we discussed a number of times.
Jakub Kicinski (5):
tls: reject the combination of TLS and sockmap
tls: remove dead sockmap (psock) handling from the SW path selftests/bpf: remove sockmap + ktls tests selftests/bpf: drop the unused kTLS program from test_sockmap selftests/bpf: test that TLS crypto is rejected on a sockmap socket
include/linux/skmsg.h | 9 - .../selftests/bpf/progs/test_sockmap_kern.h | 56 --- net/core/skmsg.c | 52 +-- net/tls/tls_main.c | 19 +- net/tls/tls_sw.c | 399 ++--------------- .../selftests/bpf/prog_tests/sockmap_ktls.c | 420 +++--------------- .../selftests/bpf/progs/test_sockmap_ktls.c | 61 --- tools/testing/selftests/bpf/test_sockmap.c | 250 +---------- 8 files changed, 119 insertions(+), 1147 deletions(-) delete mode 100644 tools/testing/selftests/bpf/progs/test_sockmap_ktls.c
Signature · 1 line
2.54.0
Jakub Kicinski
maintainerPATCH 1/5 tls: reject the combination of TLS and sockmap
TLS and sockmap (BPF psock) integration hides a lot of latent bugs. Bugs which may be more or less relevant for real users but they are definitely exploitable.
We could not find anyone actively using this integration so let's reject this config. Adding a TLS socket to a sockmap was already rejected by sk_psock_init() through the inet_csk_has_ulp() check. We need to reject the attempts to configure the TLS keys (rather than adding the ULP itself) because checking prior to the ULP installation is tricky without risking a race with sockmap getting added in parallel (sockmap does not hold the socket lock).
This patch is a minimal rejection of the feature. Subsequent patch in the series will do a light dead code removal. Full cleanup would require a major rewrite of the Tx path, we don't need skmsg any more.
--- net/tls/tls_main.c | 11 +++++++++++ 1 file changed, 11 insertions(+)
net/tls/tls_main.c +11 -0
@@ -643,6 +643,17 @@ static int do_tls_setsockopt_conf(struct sock *sk, sockptr_t optval,int rc =0 ;int conf; +/* TLS and sockmap are mutually exclusive. A socket already in a +* sockmap (i.e. with a psock attached) cannot be upgraded to TLS. +* sockmap rejects TLS sockets already (see sk_psock_init()). +*/ +rcu_read_lock (); +if (sk_psock (sk)) { +rcu_read_unlock (); +return -EINVAL ; + } +rcu_read_unlock (); +if (sockptr_is_null (optval) || (optlen <sizeof (*crypto_info)))return -EINVAL ;
Signature · 1 line
2.54.0
Paolo Abeni
maintainerQuoted 11 lines · Jakub Kicinski
TLS and sockmap (BPF psock) integration hides a lot of latent bugs. Bugs which may be more or less relevant for real users but they are definitely exploitable.
We could not find anyone actively using this integration so let's reject this config. Adding a TLS socket to a sockmap was already rejected by
sk_psock_init()through theinet_csk_has_ulp()check. We need to reject the attempts to configure the TLS keys (rather than adding the ULP itself) because checking prior to the ULP installation is tricky without risking a race with sockmap getting added in parallel (sockmap does not hold the socket lock).
Aren't both tls_ctx_create() and sk_psock_init() under (write) the callback lock? Isn't that enough to avoid races?
/P
Jakub Sitnicki
maintainerQuoted 13 lines · Paolo Abeni
Quoted 11 lines · Jakub Kicinski
TLS and sockmap (BPF psock) integration hides a lot of latent bugs. Bugs which may be more or less relevant for real users but they are definitely exploitable.
We could not find anyone actively using this integration so let's reject this config. Adding a TLS socket to a sockmap was already rejected by
sk_psock_init()through theinet_csk_has_ulp()check. We need to reject the attempts to configure the TLS keys (rather than adding the ULP itself) because checking prior to the ULP installation is tricky without risking a race with sockmap getting added in parallel (sockmap does not hold the socket lock).
Quoted 2 lines
Aren't both
tls_ctx_create()andsk_psock_init()under (write) the callback lock? Isn't that enough to avoid races?
+1, but we would have to tweak inet_csk_has_ulp() to check for icsk_ulp_data in addition to icsk_ulp_ops. Only icsk_ulp_data is set under sk_callback_lock.
espintcp faces the same race...
Jakub Kicinski
maintainerQuoted 14 lines · On Sun, 14 Jun 2026 21:12:05 +0200 Jakub Sitnicki wrote:
Quoted 13 lines · Paolo Abeni
Quoted 11 lines · Jakub Kicinski
TLS and sockmap (BPF psock) integration hides a lot of latent bugs. Bugs which may be more or less relevant for real users but they are definitely exploitable.
We could not find anyone actively using this integration so let's reject this config. Adding a TLS socket to a sockmap was already rejected by
sk_psock_init()through theinet_csk_has_ulp()check. We need to reject the attempts to configure the TLS keys (rather than adding the ULP itself) because checking prior to the ULP installation is tricky without risking a race with sockmap getting added in parallel (sockmap does not hold the socket lock).
Quoted 8 lines
Quoted 2 lines
Aren't both
tls_ctx_create()andsk_psock_init()under (write) the callback lock? Isn't that enough to avoid races?+1, but we would have to tweak
inet_csk_has_ulp()to check foricsk_ulp_datain addition toicsk_ulp_ops. Onlyicsk_ulp_datais set undersk_callback_lock.espintcp faces the same race...
Right, some deeper restructuring is needed for that. Also - I'm aware of the race that Sashiko points out but we need to draw the line somewhere if we want to hit the current merge window.
IOW I decided to keep it simple and focus on removing TLS+sockmap integration, races in ULP vs sockmap init is a separate can of warms.
[email protected]
AI reviewThank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [Critical] The patch attempts to reject the combination of TLS and sockmap during key configuration, but leaves a critical vulnerability where attaching the TLS ULP to a socket already in a sockmap causes global protocol state corruption, infinite loops in unrelated sockets, and silently bypasses BPF sk_msg policies. --
commit 12fd2fff4db720c6f124011a38950efdbcd77414
Author: Jakub Kicinski <[email protected]>
tls: reject the combination of TLS and sockmap
This commit attempts to reject the combination of TLS and sockmap by returning -EINVAL in do_tls_setsockopt_conf() if a psock is attached. The goal is to prevent latent bugs while removing dead code.
Quoted 5 lines
net/tls/tls_main.c +0
-0@@ -643,6 +643,17 @@ static int do_tls_setsockopt_conf(struct sock *sk, sockptr_t optval,
[ ... ]
Quoted 4 lines
net/tls/tls_main.c +1
-0int rc =0 ;int conf; +/* TLS and sockmap are mutually exclusive. A socket already in a
net/tls/tls_main.c static int do_tls_setsockopt_conf(struct sock *sk, sockptr_t optval, · line 656
Quoted 10 lines
net/tls/tls_main.c +10
-0+* sockmap (i.e. with a psock attached) cannot be upgraded to TLS. +* sockmap rejects TLS sockets already (see sk_psock_init()). +*/ +rcu_read_lock (); +if (sk_psock (sk)) { +rcu_read_unlock (); +return -EINVAL ; + } +rcu_read_unlock (); +
[Severity: Critical]
This isn't a bug introduced by this patch, but does this check happen too late to prevent global protocol state corruption?
If an unprivileged user adds an established TCP socket to a sockmap, the socket's sk_prot is changed to tcp_bpf_prots. If they then attach the TLS ULP, tls_init() executes and immediately calls tls_build_proto() before this key configuration check is ever reached:
net/tls/tls_main.c:tls_init() {
...
tls_build_proto(sk);
...
}This function reads the socket's current sk_prot and uses it to rebuild the global tls_prots array:
net/tls/tls_main.c:tls_build_proto() {
...
struct proto *prot = READ_ONCE(sk->sk_prot);
...
build_protos(tls_prots[TLSV4], prot);
...
}Because sk_prot is tcp_bpf_prots, the unhash handler in the tls_prots array is permanently overwritten with sock_map_unhash.
Any subsequent normal TLS socket will inherit this corrupted global array. When the normal TLS socket is closed, sock_map_unhash() is invoked. Since the normal socket has no psock, it attempts to fall back to the original unhash function, leading to an infinite retry loop:
net/core/sock_map.c:sock_map_unhash() {
...
saved_unhash = READ_ONCE(sk->sk_prot)->unhash;
if (unlikely(saved_unhash == sock_map_unhash))
goto retry;
...
}Because sk->sk_prot points to the corrupted tls_prots array, it reads sock_map_unhash again, causing a kernel hard lockup.
Could a check be placed in tls_init() or tcp_set_ulp() instead, to prevent ULP attachment entirely before tls_build_proto() is called?
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=1
Quoted 12 lines · Jakub Kicinski
TLS and sockmap (BPF psock) integration hides a lot of latent bugs. Bugs which may be more or less relevant for real users but they are definitely exploitable.
We could not find anyone actively using this integration so let's reject this config. Adding a TLS socket to a sockmap was already rejected by
sk_psock_init()through theinet_csk_has_ulp()check. We need to reject the attempts to configure the TLS keys (rather than adding the ULP itself) because checking prior to the ULP installation is tricky without risking a race with sockmap getting added in parallel (sockmap does not hold the socket lock).
Quoted 6 lines
This patch is a minimal rejection of the feature. Subsequent patch in the series will do a light dead code removal. Full cleanup would require a major rewrite of the Tx path, we don't need skmsg any more.
Signed-off-by Jakub Kicinski <[email protected]>---
SGTM until we can come up with a generic way to exclude sockmapped sockets from ktls and espintcp.
Quoted 17 lines · Jakub Sitnicki
Quoted 16 lines · Jakub Kicinski
TLS and sockmap (BPF psock) integration hides a lot of latent bugs. Bugs which may be more or less relevant for real users but they are definitely exploitable.
We could not find anyone actively using this integration so let's reject this config. Adding a TLS socket to a sockmap was already rejected by
sk_psock_init()through theinet_csk_has_ulp()check. We need to reject the attempts to configure the TLS keys (rather than adding the ULP itself) because checking prior to the ULP installation is tricky without risking a race with sockmap getting added in parallel (sockmap does not hold the socket lock).This patch is a minimal rejection of the feature. Subsequent patch in the series will do a light dead code removal. Full cleanup would require a major rewrite of the Tx path, we don't need skmsg any more.
Quoted 5 lines
Quoted 2 lines
Signed-off-by Jakub Kicinski <[email protected]>---
SGTM until we can come up with a generic way to exclude sockmapped sockets from ktls and espintcp.
And possibly ovpn too.
Signature · 1 line
Sabrina
Jakub Kicinski
maintainerPATCH 2/5 tls: remove dead sockmap (psock) handling from the SW path
In reply to Jakub KicinskiTLS and sockmap are now mutually exclusive. Try to delete the code from sendmsg and recvmsg path which is now obviously dead.
The main goal is to delete enough code for AI security scanners to no longer bother us with sockmap related bugs. At the same time retain the code in case someone has the cycles to fix all of this and make the integration work, again.
If the integration does not get restored we can wipe the rest of the skmsg code from TLS in two or three releases.
The changes on the Tx side are deeper since that's where most of the bugs are, Rx side simply takes the data from sockmap and gives it to the user. On Tx split record handling and rolling back the iterator were the two problem areas.
--- include/linux/skmsg.h | 9 - net/core/skmsg.c | 52 +----- net/tls/tls_main.c | 8 +- net/tls/tls_sw.c | 399 +++--------------------------------------- 4 files changed, 31 insertions(+), 437 deletions(-)
include/linux/skmsg.h +0 -9
@@ -544,15 +544,6 @@ static inline void psock_progs_drop(struct sk_psock_progs *progs)psock_set_prog (&progs->skb_verdict,NULL ); } -int sk_psock_tls_strp_read (struct sk_psock *psock,struct sk_buff *skb); - -static inline bool sk_psock_strp_enabled (struct sk_psock *psock) -{ -if (!psock) -return false; -return !!psock->saved_data_ready; -} -/* for tcp only, sk is locked */ static inline ssize_t sk_psock_msg_inq (struct sock *sk) {
net/core/skmsg.c +3 -49
76 lines not on this page · raw message
net/tls/tls_main.c +1 -7
@@ -402,7 +402,6 @@ static __poll_t tls_sk_poll(struct file *file, struct socket *sock,struct tls_sw_context_rx *ctx;struct tls_context *tls_ctx;struct sock *sk = sock->sk; -struct sk_psock *psock;__poll_t mask =0 ;u8 shutdown;int state;
@@ -416,17 +415,12 @@ static __poll_t tls_sk_poll(struct file *file, struct socket *sock, tls_ctx =tls_get_ctx (sk); ctx =tls_sw_ctx_rx (tls_ctx); - psock =sk_psock_get (sk);if ((skb_queue_empty_lockless (&ctx->rx_list) && - !tls_strp_msg_ready (ctx) && -sk_psock_queue_empty (psock)) || + !tls_strp_msg_ready (ctx)) ||READ_ONCE (ctx->key_update_pending)) mask &= ~(EPOLLIN |EPOLLRDNORM ); -if (psock) -sk_psock_put (sk, psock); -return mask; }
net/tls/tls_sw.c +27 -372
585 lines not on this page · raw message
Signature · 1 line
2.54.0
Re: [PATCH net-next 2/5] tls: remove dead sockmap (psock) handling from the SW path
Quoted 11 lines · Jakub Kicinski
TLS and sockmap are now mutually exclusive. Try to delete the code from sendmsg and recvmsg path which is now obviously dead.
The main goal is to delete enough code for AI security scanners to no longer bother us with sockmap related bugs. At the same time retain the code in case someone has the cycles to fix all of this and make the integration work, again.
If the integration does not get restored we can wipe the rest of the skmsg code from TLS in two or three releases.
Quoted 7 lines
The changes on the Tx side are deeper since that's where most of the bugs are, Rx side simply takes the data from sockmap and gives it to the user. On Tx split record handling and rolling back the iterator were the two problem areas.
Signed-off-by Jakub Kicinski <[email protected]>---
Nice! This unlocks further cleanup in tcp_bpf and tcp_ulp.
Re: [PATCH net-next 2/5] tls: remove dead sockmap (psock) handling from the SW path
In reply to Jakub KicinskiQuoted 16 lines · Jakub Kicinski
TLS and sockmap are now mutually exclusive. Try to delete the code from sendmsg and recvmsg path which is now obviously dead.
The main goal is to delete enough code for AI security scanners to no longer bother us with sockmap related bugs. At the same time retain the code in case someone has the cycles to fix all of this and make the integration work, again.
If the integration does not get restored we can wipe the rest of the skmsg code from TLS in two or three releases.
The changes on the Tx side are deeper since that's where most of the bugs are, Rx side simply takes the data from sockmap and gives it to the user. On Tx split record handling and rolling back the iterator were the two problem areas.
Quoted 7 lines
Signed-off-by Jakub Kicinski <[email protected]>--- include/linux/skmsg.h | 9 - net/core/skmsg.c | 52 +----- net/tls/tls_main.c | 8 +- net/tls/tls_sw.c | 399 +++--------------------------------------- 4 files changed, 31 insertions(+), 437 deletions(-)
net/tls/tls_sw.c int tls_sw_read_sock(struct sock *sk, read_descriptor_t *desc, · line 2091
Quoted 6 lines
net/tls/tls_sw.c +1
-1@@ -2417,7 +2088,7 @@ int tls_sw_read_sock(struct sock *sk, read_descriptor_t *desc, }else {struct tls_decrypt_arg darg; - err =tls_rx_rec_wait (sk,NULL , true, released, !!copied); + err =tls_rx_rec_wait (sk, true, released, !!copied);
nit: There's also a leftover sk_psock_get in that function. We can clean it up later, let's get this series in.
Signature · 1 line
Sabrina
Jakub Kicinski
maintainerPATCH 3/5 selftests/bpf: remove sockmap + ktls tests
In reply to Jakub KicinskiThe combination of sockmap and TLS is no longer supported - installing the TLS ULP on a sockmap socket (and vice versa) is now rejected. Remove the tests that exercise the combination along with their BPF program; the file covered nothing but sockmap sockets holding kTLS contexts.
--- .../selftests/bpf/prog_tests/sockmap_ktls.c | 355 ------------------ .../selftests/bpf/progs/test_sockmap_ktls.c | 61 --- tools/testing/selftests/bpf/test_sockmap.c | 227 +---------- 3 files changed, 1 insertion(+), 642 deletions(-) delete mode 100644 tools/testing/selftests/bpf/progs/test_sockmap_ktls.c
tools/testing/selftests/bpf/prog_tests/sockmap_ktls.c +0 -355
@@ -9,7 +9,6 @@#include "test_progs.h" #include "sockmap_helpers.h" #include "test_skmsg_load_helpers.skel.h" -#include "test_sockmap_ktls.skel.h" #define MAX_TEST_NAME 80#define TCP_ULP 31
@@ -160,249 +159,6 @@ static void test_sockmap_ktls_offload(int family, int sotype)close (p); } -static void test_sockmap_ktls_tx_cork (int family,int sotype,bool push) -{ -int err, off; -int i, j; -int start_push =0 , push_len =0 ; -int c =0 , p =0 , one =1 , sent, recvd; -int prog_fd, map_fd; -char msg[12 ] ="hello world\0" ; -char rcv[20 ] = {0 }; -struct test_sockmap_ktls *skel; - - skel =test_sockmap_ktls__open_and_load (); -if (!ASSERT_TRUE (skel,"open ktls skel" )) -return ; - - err =create_pair (family, sotype, &c, &p); -if (!ASSERT_OK (err,"create_pair()" )) - goto out; - - prog_fd =bpf_program__fd (skel->progs.prog_sk_policy); - map_fd =bpf_map__fd (skel->maps.sock_map); - - err =bpf_prog_attach (prog_fd, map_fd,BPF_SK_MSG_VERDICT ,0 ); -if (!ASSERT_OK (err,"bpf_prog_attach sk msg" )) - goto out; - - err =bpf_map_update_elem (map_fd, &one, &c,BPF_NOEXIST ); -if (!ASSERT_OK (err,"bpf_map_update_elem(c)" )) - goto out; - - err =init_ktls_pairs (c, p); -if (!ASSERT_OK (err,"init_ktls_pairs(c, p)" )) - goto out; - - skel->bss->cork_byte =sizeof (msg); -if (push) { - start_push =1 ; - push_len =2 ; - } - skel->bss->push_start = start_push; - skel->bss->push_end = push_len; - - off =sizeof (msg) /2 ; - sent =send (c, msg, off,0 ); -if (!ASSERT_EQ (sent, off,"send(msg)" )) - goto out; - - recvd =recv_timeout (p, rcv,sizeof (rcv),MSG_DONTWAIT ,1 ); -if (!ASSERT_EQ (-1 , recvd,"expected no data" )) - goto out; - -/* send remaining msg */ - sent =send (c, msg + off,sizeof (msg) - off,0 ); -if (!ASSERT_EQ (sent,sizeof (msg) - off,"send remaining data" )) - goto out; - - recvd =recv_timeout (p, rcv,sizeof (rcv),MSG_DONTWAIT ,1 ); -if (!ASSERT_OK (err,"recv(msg)" ) || - !ASSERT_EQ (recvd,sizeof (msg) + push_len,"check length mismatch" )) - goto out; - -for (i =0 , j =0 ; i < recvd;) { -/* skip checking the data that has been pushed in */ -if (i >= start_push && i <= start_push + push_len -1 ) { - i++; -continue ; - } -if (!ASSERT_EQ (rcv[i], msg[j],"data mismatch" )) - goto out; - i++; - j++; - } -out: -if (c) -close (c); -if (p) -close (p); -test_sockmap_ktls__destroy (skel); -} - -static void test_sockmap_ktls_tx_no_buf (int family,int sotype,bool push) -{ -int c =-1 , p =-1 , one =1 , two =2 ; -struct test_sockmap_ktls *skel; -unsigned char *data =NULL ; -struct msghdr msg = {0 }; -struct iovec iov[2 ]; -int prog_fd, map_fd; -int txrx_buf =1024 ; -int iov_length =8192 ; -int err; - - skel =test_sockmap_ktls__open_and_load (); -if (!ASSERT_TRUE (skel,"open ktls skel" )) -return ; - - err =create_pair (family, sotype, &c, &p); -if (!ASSERT_OK (err,"create_pair()" )) - goto out; - - err =setsockopt (c,SOL_SOCKET ,SO_RCVBUFFORCE , &txrx_buf,sizeof (int )); - err |=setsockopt (p,SOL_SOCKET ,SO_SNDBUFFORCE , &txrx_buf,sizeof (int )); -if (!ASSERT_OK (err,"set buf limit" )) - goto out; - - prog_fd =bpf_program__fd (skel->progs.prog_sk_policy_redir); - map_fd =bpf_map__fd (skel->maps.sock_map); - - err =bpf_prog_attach (prog_fd, map_fd,BPF_SK_MSG_VERDICT ,0 ); -if (!ASSERT_OK (err,"bpf_prog_attach sk msg" )) - goto out; - - err =bpf_map_update_elem (map_fd, &one, &c,BPF_NOEXIST ); -if (!ASSERT_OK (err,"bpf_map_update_elem(c)" )) - goto out; - - err =bpf_map_update_elem (map_fd, &two, &p,BPF_NOEXIST ); -if (!ASSERT_OK (err,"bpf_map_update_elem(p)" )) - goto out; - - skel->bss->apply_bytes =1024 ; - - err =init_ktls_pairs (c, p); -if (!ASSERT_OK (err,"init_ktls_pairs(c, p)" )) - goto out; - - data =calloc (iov_length,sizeof (char )); -if (!data) - goto out; - - iov[0 ].iov_base = data; - iov[0 ].iov_len = iov_length; - iov[1 ].iov_base = data; - iov[1 ].iov_len = iov_length; - msg.msg_iov = iov; - msg.msg_iovlen =2 ; - -for (;;) { - err =sendmsg (c, &msg,MSG_DONTWAIT ); -if (err <=0 ) -break ; - } - -out: -if (data) -free (data); -if (c !=-1 ) -close (c); -if (p !=-1 ) -close (p); - -test_sockmap_ktls__destroy (skel); -} - -static void test_sockmap_ktls_tx_pop (int family,int sotype) -{ -char msg[37 ] ="0123456789abcdefghijklmnopqrstuvwxyz\0" ; -int c =0 , p =0 , one =1 , sent, recvd; -struct test_sockmap_ktls *skel; -int prog_fd, map_fd; -char rcv[50 ] = {0 }; -int err; -int i, m, r; - - skel =test_sockmap_ktls__open_and_load (); -if (!ASSERT_TRUE (skel,"open ktls skel" )) -return ; - - err =create_pair (family, sotype, &c, &p); -if (!ASSERT_OK (err,"create_pair()" )) - goto out; - - prog_fd =bpf_program__fd (skel->progs.prog_sk_policy); - map_fd =bpf_map__fd (skel->maps.sock_map); - - err =bpf_prog_attach (prog_fd, map_fd,BPF_SK_MSG_VERDICT ,0 ); -if (!ASSERT_OK (err,"bpf_prog_attach sk msg" )) - goto out; - - err =bpf_map_update_elem (map_fd, &one, &c,BPF_NOEXIST ); -if (!ASSERT_OK (err,"bpf_map_update_elem(c)" )) - goto out; - - err =init_ktls_pairs (c, p); -if (!ASSERT_OK (err,"init_ktls_pairs(c, p)" )) - goto out; - -struct { -int pop_start; -int pop_len; - } pop_policy[] = { -/* trim the start */ - {0 ,2 }, - {0 ,10 }, - {1 ,2 }, - {1 ,10 }, -/* trim the end */ - {35 ,2 }, -/* New entries should be added before this line */ - {-1 ,-1 }, - }; - - i =0 ; -while (pop_policy[i].pop_start >=0 ) { - skel->bss->pop_start = pop_policy[i].pop_start; - skel->bss->pop_end = pop_policy[i].pop_len; - - sent =send (c, msg,sizeof (msg),0 ); -if (!ASSERT_EQ (sent,sizeof (msg),"send(msg)" )) - goto out; - - recvd =recv_timeout (p, rcv,sizeof (rcv),MSG_DONTWAIT ,1 ); -if (!ASSERT_EQ (recvd,sizeof (msg) - pop_policy[i].pop_len,"pop len mismatch" )) - goto out; - -/* verify the data -* msg: 0123456789a bcdefghij klmnopqrstuvwxyz -* | | -* popped data -*/ -for (m =0 , r =0 ; m <sizeof (msg);) { -/* skip checking the data that has been popped */ -if (m >= pop_policy[i].pop_start && - m <= pop_policy[i].pop_start + pop_policy[i].pop_len -1 ) { - m++; -continue ; - } - -if (!ASSERT_EQ (msg[m], rcv[r],"data mismatch" )) - goto out; - m++; - r++; - } - i++; - } -out: -if (c) -close (c); -if (p) -close (p); -test_sockmap_ktls__destroy (skel); -} -static void run_tests (int family,enum bpf_map_type map_type) {int map;
@@ -417,121 +173,10 @@ static void run_tests(int family, enum bpf_map_type map_type)close (map); } -/* -* Regression test for the KTLS + sockmap (verdict) reverse-order UAF. -* -* Vulnerable sequence: -* 1. Insert receiver socket into sockmap with BPF_SK_SKB_VERDICT program. -* sk->sk_data_ready becomes sk_psock_verdict_data_ready. -* 2. Configure TLS RX: tls_sw_strparser_arm() saves -* sk_psock_verdict_data_ready as rx_ctx->saved_data_ready. -* -* When data arrives, tls_rx_msg_ready() calls saved_data_ready() = -* sk_psock_verdict_data_ready(), which calls tcp_read_skb() and drains -* sk_receive_queue via __skb_unlink() without advancing copied_seq. -* tls_strp_msg_load() then finds the queue empty while tcp_inq() is still -* non-zero, hits WARN_ON_ONCE(!first), and leaves a dangling frag_list -* pointer that tls_decrypt_sg() walks — a use-after-free. -* -* The fix adds a tls_sw_has_ctx_rx() check to sk_psock_verdict_data_ready(), -* mirroring what sk_psock_strp_data_ready() already does: when a TLS RX -* context is present, defer to psock->saved_data_ready (sock_def_readable) -* instead of calling tcp_read_skb(), so TLS retains sole ownership of the -* receive queue. Data is then decrypted and returned correctly by -* tls_sw_recvmsg(). -*/ -static void test_sockmap_ktls_verdict_with_tls_rx (int family,int sotype) -{ -struct tls12_crypto_info_aes_gcm_128 crypto_info = {}; -char send_buf[] ="hello ktls sockmap reverse order" ; -char recv_buf[sizeof (send_buf)] = {}; -struct test_sockmap_ktls *skel; -int c =-1 , p =-1 , zero =0 ; -int prog_fd, map_fd; -ssize_t n; -int err; - - skel =test_sockmap_ktls__open_and_load (); -if (!ASSERT_TRUE (skel,"open_and_load" )) -return ; - - err =create_pair (family, sotype, &c, &p); -if (!ASSERT_OK (err,"create_pair" )) - goto out; - - prog_fd =bpf_program__fd (skel->progs.prog_skb_verdict_pass); - map_fd =bpf_map__fd (skel->maps.sock_map_verdict); - - err =bpf_prog_attach (prog_fd, map_fd,BPF_SK_SKB_VERDICT ,0 ); -if (!ASSERT_OK (err,"bpf_prog_attach sk_skb verdict" )) - goto out; - -/* Step 1: configure TLS TX on sender (no sockmap involvement) */ - err =setsockopt (c,IPPROTO_TCP ,TCP_ULP ,"tls" ,strlen ("tls" )); -if (!ASSERT_OK (err,"setsockopt(TCP_ULP) client" )) - goto out; - - crypto_info.info.version =TLS_1_2_VERSION ; - crypto_info.info.cipher_type =TLS_CIPHER_AES_GCM_128 ; -memset (crypto_info.key,0x01 ,sizeof (crypto_info.key)); -memset (crypto_info.salt,0x02 ,sizeof (crypto_info.salt)); - - err =setsockopt (c,SOL_TLS ,TLS_TX , &crypto_info,sizeof (crypto_info)); -if (!ASSERT_OK (err,"setsockopt(TLS_TX)" )) - goto out; - -/* Step 2: insert receiver into sockmap BEFORE TLS RX */ - err =bpf_map_update_elem (map_fd, &zero, &p,BPF_NOEXIST ); -if (!ASSERT_OK (err,"bpf_map_update_elem" )) - goto out; - -/* Step 3: configure TLS RX AFTER sockmap insertion */ - err =setsockopt (p,IPPROTO_TCP ,TCP_ULP ,"tls" ,strlen ("tls" )); -if (!ASSERT_OK (err,"setsockopt(TCP_ULP) server" )) - goto out; - - err =setsockopt (p,SOL_TLS ,TLS_RX , &crypto_info,sizeof (crypto_info)); -if (!ASSERT_OK (err,"setsockopt(TLS_RX)" )) - goto out; - -/* -* A buggy kernel hits WARN_ON_ONCE in tls_strp_load_anchor_with_queue -* and may UAF in tls_decrypt_sg here. With the fix, -* sk_psock_verdict_data_ready defers to sock_def_readable and TLS -* decrypts the record normally. -*/ - n =send (c, send_buf,sizeof (send_buf),0 ); -if (!ASSERT_EQ (n, (ssize_t )sizeof (send_buf),"send" )) - goto out; - - n =recv_timeout (p, recv_buf,sizeof (recv_buf),0 ,5 ); -if (!ASSERT_EQ (n, (ssize_t )sizeof (send_buf),"recv" )) - goto out; - -ASSERT_OK (memcmp (send_buf, recv_buf,sizeof (send_buf)),"data integrity" ); - -out: -if (c !=-1 ) -close (c); -if (p !=-1 ) -close (p); -test_sockmap_ktls__destroy (skel); -} -static void run_ktls_test (int family,int sotype) {if (test__start_subtest ("tls simple offload" ))test_sockmap_ktls_offload (family, sotype); -if (test__start_subtest ("tls tx cork" )) -test_sockmap_ktls_tx_cork (family, sotype, false); -if (test__start_subtest ("tls tx cork with push" )) -test_sockmap_ktls_tx_cork (family, sotype, true); -if (test__start_subtest ("tls tx egress with no buf" )) -test_sockmap_ktls_tx_no_buf (family, sotype, true); -if (test__start_subtest ("tls tx with pop" )) -test_sockmap_ktls_tx_pop (family, sotype); -if (test__start_subtest ("tls verdict with tls rx" )) -test_sockmap_ktls_verdict_with_tls_rx (family, sotype); }void test_sockmap_ktls (void )
tools/testing/selftests/bpf/progs/test_sockmap_ktls.c deleted +0 -61
61 lines not on this page · raw message
tools/testing/selftests/bpf/test_sockmap.c +1 -226
333 lines not on this page · raw message
Signature · 1 line
2.54.0
Re: [PATCH net-next 3/5] selftests/bpf: remove sockmap + ktls tests
Quoted 17 lines · Jakub Kicinski
The combination of sockmap and TLS is no longer supported - installing the TLS ULP on a sockmap socket (and vice versa) is now rejected. Remove the tests that exercise the combination along with their BPF program; the file covered nothing but sockmap sockets holding kTLS contexts.
Signed-off-by Jakub Kicinski <[email protected]>--- .../selftests/bpf/prog_tests/sockmap_ktls.c | 355 ------------------ .../selftests/bpf/progs/test_sockmap_ktls.c | 61 --- tools/testing/selftests/bpf/test_sockmap.c | 227 +---------- 3 files changed, 1 insertion(+), 642 deletions(-) delete mode 100644 tools/testing/selftests/bpf/progs/test_sockmap_ktls.ctools/testing/selftests/bpf/prog_tests/sockmap_ktls.c +0
-0
[...]
tools/testing/selftests/bpf/prog_tests/sockmap_ktls.c static void run_tests(int family, enum bpf_map_type map_type) · line 179
Quoted 4 lines
static void
run_ktls_test(int family, int sotype){tools/testing/selftests/bpf/prog_tests/sockmap_ktls.c +0
-0if (test__start_subtest ("tls simple offload" ))test_sockmap_ktls_offload (family, sotype);
Nit: We probably don't need to keep this one test around. It tests pure kTLS and overlaps with selftests/net/tls.c.
tools/testing/selftests/bpf/prog_tests/sockmap_ktls.c static void run_tests(int family, enum bpf_map_type map_type) · line 180
Quoted 11 lines
tools/testing/selftests/bpf/prog_tests/sockmap_ktls.c +0
-10-if (test__start_subtest ("tls tx cork" )) -test_sockmap_ktls_tx_cork (family, sotype, false); -if (test__start_subtest ("tls tx cork with push" )) -test_sockmap_ktls_tx_cork (family, sotype, true); -if (test__start_subtest ("tls tx egress with no buf" )) -test_sockmap_ktls_tx_no_buf (family, sotype, true); -if (test__start_subtest ("tls tx with pop" )) -test_sockmap_ktls_tx_pop (family, sotype); -if (test__start_subtest ("tls verdict with tls rx" )) -test_sockmap_ktls_verdict_with_tls_rx (family, sotype); }
Jakub Kicinski
maintainerPATCH 4/5 selftests/bpf: drop the unused kTLS program from test_sockmap
In reply to Jakub KicinskiWith the sockmap + kTLS tests gone, the BPF-side support in test_sockmap is dead: the tls_sock_map map and bpf_prog3 (which redirected skbs into it) are no longer referenced. Remove them, along with the now-unused bpf_write_pass() helper.
bpf_prog3 was progs[2], so renumber the progs[] users in test_sockmap.c:
the sockops program drops to progs[2] and the sk_msg tx programs to progs[3..7]. Shrink the map/prog arrays from 9 to 8 and drop the tls_sock_map entry (the last one) from map_names[] to match.
--- .../selftests/bpf/progs/test_sockmap_kern.h | 56 ------------------- tools/testing/selftests/bpf/test_sockmap.c | 23 ++++---- 2 files changed, 11 insertions(+), 68 deletions(-)
tools/testing/selftests/bpf/progs/test_sockmap_kern.h +0 -56
@@ -85,13 +85,6 @@ struct {__type (value, int); } sock_skb_opts SEC(".maps"); -struct { - __uint(type, TEST_MAP_TYPE); - __uint(max_entries, 20); - __uint(key_size, sizeof(int)); - __uint(value_size, sizeof(int)); -} tls_sock_map SEC(".maps"); - SEC("sk_skb/stream_parser")int bpf_prog1 (struct __sk_buff *skb) {
@@ -135,55 +128,6 @@ int bpf_prog2(struct __sk_buff *skb) } -static inline void bpf_write_pass (struct __sk_buff *skb,int offset) -{ -int err =bpf_skb_pull_data (skb,6 + offset); -void *data_end; -char *c; - -if (err) -return ; - - c = (char *)(long )skb->data; - data_end = (void *)(long )skb->data_end; - -if (c +5 + offset < data_end) -memcpy (c + offset,"PASS" ,4 ); -} - -SEC("sk_skb/stream_verdict") -int bpf_prog3 (struct __sk_buff *skb) -{ -int err, *f, ret =SK_PASS ; -const int one =1 ; - - f =bpf_map_lookup_elem (&sock_skb_opts, &one); -if (f && *f) { -__u64 flags =0 ; - - ret =0 ; - flags = *f; - - err =bpf_skb_adjust_room (skb,-13 ,0 ,0 ); -if (err) -return SK_DROP ; - err =bpf_skb_adjust_room (skb,4 ,0 ,0 ); -if (err) -return SK_DROP ; -bpf_write_pass (skb,0 ); -#ifdef SOCKMAP -return bpf_sk_redirect_map (skb, &tls_sock_map, ret, flags); -#else -return bpf_sk_redirect_hash (skb, &tls_sock_map, &ret, flags); -#endif - } - err =bpf_skb_adjust_room (skb,4 ,0 ,0 ); -if (err) -return SK_DROP ; -bpf_write_pass (skb,13 ); -return ret; -} - SEC("sockops")int bpf_sockmap (struct bpf_sock_ops *skops) {
tools/testing/selftests/bpf/test_sockmap.c +11 -12
@@ -55,10 +55,10 @@ int s1, s2, c1, c2, p1, p2;int test_cnt;int passed;int failed; -int map_fd[9 ]; -struct bpf_map *maps[9 ]; -struct bpf_program *progs[9 ]; -struct bpf_link *links[9 ]; +int map_fd[8 ]; +struct bpf_map *maps[8 ]; +struct bpf_program *progs[8 ]; +struct bpf_link *links[8 ];int txmsg_pass;int txmsg_redir;
@@ -967,7 +967,7 @@ static int run_options(struct sockmap_options *options, int cg_fd, int test) }/* Attach to cgroups */ - err =bpf_prog_attach (bpf_program__fd (progs[3 ]), cg_fd,BPF_CGROUP_SOCK_OPS ,0 ); + err =bpf_prog_attach (bpf_program__fd (progs[2 ]), cg_fd,BPF_CGROUP_SOCK_OPS ,0 );if (err) {fprintf (stderr,"ERROR: bpf_prog_attach (groups): %d (%s)\n" , err,strerror (errno));
@@ -983,15 +983,15 @@ static int run_options(struct sockmap_options *options, int cg_fd, int test)/* Attach txmsg program to sockmap */ if (txmsg_pass) - tx_prog = progs[4 ]; + tx_prog = progs[3 ];else if (txmsg_redir) - tx_prog = progs[5 ]; + tx_prog = progs[4 ];else if (txmsg_apply) - tx_prog = progs[6 ]; + tx_prog = progs[5 ];else if (txmsg_cork) - tx_prog = progs[7 ]; + tx_prog = progs[6 ];else if (txmsg_drop) - tx_prog = progs[8 ]; + tx_prog = progs[7 ];else tx_prog =NULL ;
@@ -1218,7 +1218,7 @@ static int run_options(struct sockmap_options *options, int cg_fd, int test)fprintf (stderr,"unknown test\n" ); out:/* Detach and zero all the maps */ -bpf_prog_detach2 (bpf_program__fd (progs[3 ]), cg_fd,BPF_CGROUP_SOCK_OPS ); +bpf_prog_detach2 (bpf_program__fd (progs[2 ]), cg_fd,BPF_CGROUP_SOCK_OPS );for (i =0 ; i <ARRAY_SIZE (links); i++) {if (links[i])
@@ -1724,7 +1724,6 @@ char *map_names[] = {"sock_bytes" ,"sock_redir_flags" , "sock_skb_opts", - "tls_sock_map", };static int populate_progs (char *bpf_file)
Signature · 1 line
2.54.0
Jakub Kicinski
maintainerPATCH 5/5 selftests/bpf: test that TLS crypto is rejected on a sockmap socket
In reply to Jakub KicinskiTLS and sockmap are mutually exclusive. We already have a test for the sockmap side rejecting kTLS, add the inverse test matching patch 1 of this series.
--- .../selftests/bpf/prog_tests/sockmap_ktls.c | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+)
tools/testing/selftests/bpf/prog_tests/sockmap_ktls.c +65 -0
@@ -116,6 +116,68 @@ static void test_sockmap_ktls_update_fails_when_sock_has_ulp(int family, int mapclose (s); } +static void test_sockmap_ktls_enable_fails_when_in_sockmap (int family,int map) +{ +struct tls12_crypto_info_aes_gcm_128 crypto = { + .info = { + .version =TLS_1_2_VERSION , + .cipher_type =TLS_CIPHER_AES_GCM_128 , + }, + }; +struct sockaddr_storage addr = {}; +socklen_t len =sizeof (addr); +struct sockaddr_in6 *v6; +struct sockaddr_in *v4; +int err, s, zero =0 ; + +switch (family) { +case AF_INET : + v4 = (struct sockaddr_in *)&addr; + v4->sin_family =AF_INET ; +break ; +case AF_INET6 : + v6 = (struct sockaddr_in6 *)&addr; + v6->sin6_family =AF_INET6 ; +break ; +default : +PRINT_FAIL ("unsupported socket family %d" , family); +return ; + } + + s =socket (family,SOCK_STREAM ,0 ); +if (!ASSERT_GE (s,0 ,"socket" )) +return ; + + err =bind (s, (struct sockaddr *)&addr, len); +if (!ASSERT_OK (err,"bind" )) + goto close; + + err =getsockname (s, (struct sockaddr *)&addr, &len); +if (!ASSERT_OK (err,"getsockname" )) + goto close; + + err =connect (s, (struct sockaddr *)&addr, len); +if (!ASSERT_OK (err,"connect" )) + goto close; + +/* Add the socket to the sockmap, attaching a psock. */ + err =bpf_map_update_elem (map, &zero, &s,BPF_ANY ); +if (!ASSERT_OK (err,"sockmap update elem" )) + goto close; + +/* Installing the TLS ULP is allowed, it does not touch the datapath. */ + err =setsockopt (s,IPPROTO_TCP ,TCP_ULP ,"tls" ,strlen ("tls" )); +if (!ASSERT_OK (err,"setsockopt(TCP_ULP)" )) + goto close; + +/* Enabling the TLS crypto datapath must be rejected. */ + err =setsockopt (s,SOL_TLS ,TLS_TX , &crypto,sizeof (crypto)); +ASSERT_ERR (err,"setsockopt(TLS_TX)" ); + +close: +close (s); +} +static const char *fmt_test_name (const char *subtest_name,int family,enum bpf_map_type map_type) {
@@ -170,6 +232,9 @@ static void run_tests(int family, enum bpf_map_type map_type)if (test__start_subtest (fmt_test_name ("update_fails_when_sock_has_ulp" , family, map_type)))test_sockmap_ktls_update_fails_when_sock_has_ulp (family, map); +if (test__start_subtest (fmt_test_name ("enable_fails_when_in_sockmap" , family, map_type))) +test_sockmap_ktls_enable_fails_when_in_sockmap (family, map); +close (map); }
Signature · 1 line
2.54.0
This series was applied to netdev/net-next.git (main) by Jakub Kicinski <[email protected]>:
Hello:
This series was applied to netdev/net-next.git (main) by Jakub Kicinski <[email protected]>:
Quoted 4 lines · On Sat, 13 Jun 2026 18:40:55 -0700 you wrote:
There are no known TLS+sockmap users and it has some known hard to solve bugs. Let's reject this configuration as we discussed a number of times.
Quoted 8 lines
Jakub Kicinski (5):
tls: reject the combination of TLS and sockmap
tls: remove dead sockmap (psock) handling from the SW path selftests/bpf: remove sockmap + ktls tests selftests/bpf: drop the unused kTLS program fromtest_sockmapselftests/bpf: test that TLS crypto is rejected on a sockmap socket[...]
Here is the summary with links:
- [net-next,1/5] tls: reject the combination of TLS and sockmap
https://git.kernel.org/netdev/net-next/c/460e6486617c - [net-next,2/5] tls: remove dead sockmap (psock) handling from the SW path https://git.kernel.org/netdev/net-next/c/79511603a65b - [net-next,3/5] selftests/bpf: remove sockmap + ktls tests https://git.kernel.org/netdev/net-next/c/faf89584e436 - [net-next,4/5] selftests/bpf: drop the unused kTLS program from test_sockmap https://git.kernel.org/netdev/net-next/c/6af8971d910e - [net-next,5/5] selftests/bpf: test that TLS crypto is rejected on a sockmap socket https://git.kernel.org/netdev/net-next/c/5949a7cf11e6
You are awesome, thank you!
Signature · 2 lines
Deet-doot-dot, I am a bot. https://korg.docs.kernel.org/patchwork/pwbot.html