* [PATCH mptcp-next 0/2] TLS disconnect support
@ 2026-10-14 8:59 Geliang Tang
2026-10-14 8:59 ` [PATCH mptcp-next 1/2] tls: implement tls_disconnect Geliang Tang
` (3 more replies)
0 siblings, 4 replies; 7+ messages in thread
From: Geliang Tang @ 2026-10-14 8:59 UTC (permalink / raw)
To: mptcp; +Cc: Geliang Tang
From: Geliang Tang <tanggeliang@kylinos.cn>
To verify the correctness of MPTCP KTLS implementation, I added TLS test
support to MPTCP selftests mptcp_connect.c. The test results showed that
the disconnect test group failed with error code EOPNOTSUPP, so I added
this series to support TLS disconnect.
Patch 1 implements tls_disconnect() to support disconnect operation for
TLS sockets via connect(AF_UNSPEC).
Patch 2 updates selftests to verify the full disconnect/reconnect cycle,
including data transfer verification before and after disconnect.
Geliang Tang (2):
tls: implement tls_disconnect
selftests: tls: update disconnect tests
include/net/tls.h | 12 +++-
net/tls/tls_main.c | 112 ++++++++++++++++++++++++++----
tools/testing/selftests/net/tls.c | 57 ++++++++++++++-
3 files changed, 163 insertions(+), 18 deletions(-)
--
2.55.0
^ permalink raw reply [flat|nested] 7+ messages in thread* [PATCH mptcp-next 1/2] tls: implement tls_disconnect 2026-10-14 8:59 [PATCH mptcp-next 0/2] TLS disconnect support Geliang Tang @ 2026-10-14 8:59 ` Geliang Tang 2026-10-14 9:42 ` sashiko-bot 2026-10-15 0:34 ` kernel test robot 2026-10-14 8:59 ` [PATCH mptcp-next 2/2] selftests: tls: update disconnect tests Geliang Tang ` (2 subsequent siblings) 3 siblings, 2 replies; 7+ messages in thread From: Geliang Tang @ 2026-10-14 8:59 UTC (permalink / raw) To: mptcp; +Cc: Geliang Tang From: Geliang Tang <tanggeliang@kylinos.cn> Implement disconnect support for TLS sockets via connect(AF_UNSPEC). The handler invokes the underlying disconnect() first, then on success cancels TX work (for TLS_SW), calls tls_sk_proto_free() to restore original protocol operations and clear TLS state, cleans up RX context and frees the TLS context. RX context uses kfree(), TLS context uses kfree_rcu() for RCU safety. tls_sk_proto_free() restores sk_prot, sk_socket->ops, sk_write_space, and sk_destruct to their original values, clears icsk_ulp_data and icsk_ulp_ops when free_ctx is true, and frees the TX sub-context. The RX context and main TLS context are freed separately by tls_disconnect(). Add sk_proto_ops field to tls_context to save the original sk_socket->ops. Unlike close() where the socket is destroyed, disconnect leaves the socket alive for potential reconnection. sk_prot and sk_socket->ops are restored inside tls_sk_proto_free() to prevent NULL pointer dereference from concurrent poll/read/splice operations that dispatch through sk_socket->ops. After releasing the socket lock to cancel TX work, re-check the context pointer to handle concurrent close(). Clear icsk_ulp_ops when freeing the context to prevent tcp_set_ulp from failing with -EEXIST on reconnection. Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn> --- include/net/tls.h | 12 +++-- net/tls/tls_main.c | 112 +++++++++++++++++++++++++++++++++++++++------ 2 files changed, 108 insertions(+), 16 deletions(-) diff --git a/include/net/tls.h b/include/net/tls.h index e57bef58851e..25ad76df97cb 100644 --- a/include/net/tls.h +++ b/include/net/tls.h @@ -193,6 +193,10 @@ enum tls_context_flags { * tls_dev_del call in tls_device_down if it happens simultaneously. */ TLS_RX_DEV_CLOSED = 2, + /* tls_disconnect() is in progress, prevent concurrent close() from + * freeing resources while disconnect is using them. + */ + TLS_DISCONNECTING = 3, }; struct cipher_context { @@ -259,6 +263,7 @@ struct tls_context { /* cache cold stuff */ struct proto *sk_proto; + const struct proto_ops *sk_proto_ops; struct sock *sk; void (*sk_destruct)(struct sock *sk); @@ -374,10 +379,11 @@ static inline struct tls_context *tls_get_ctx(const struct sock *sk) { const struct inet_connection_sock *icsk = inet_csk(sk); - /* Use RCU on icsk_ulp_data only for sock diag code, - * TLS data path doesn't need rcu_dereference(). + /* Use rcu_access_pointer() to safely read icsk_ulp_data, + * as it can be cleared concurrently by tls_disconnect() + * or tls_sk_proto_close(). */ - return (__force void *)icsk->icsk_ulp_data; + return (__force void *)rcu_access_pointer(icsk->icsk_ulp_data); } static inline struct tls_sw_context_rx *tls_sw_ctx_rx( diff --git a/net/tls/tls_main.c b/net/tls/tls_main.c index 8bdb78718a8d..d00e56af628a 100644 --- a/net/tls/tls_main.c +++ b/net/tls/tls_main.c @@ -358,32 +358,71 @@ static void tls_sk_proto_cleanup(struct sock *sk, } } -static void tls_sk_proto_close(struct sock *sk, long timeout) +static void tls_sk_proto_free(struct sock *sk, + struct tls_context *ctx, + bool free_ctx) { struct inet_connection_sock *icsk = inet_csk(sk); - struct tls_context *ctx = tls_get_ctx(sk); long timeo = sock_sndtimeo(sk, 0); - bool free_ctx; - - if (ctx->tx_conf == TLS_SW) - tls_sw_cancel_work_tx(ctx); - - lock_sock(sk); - free_ctx = ctx->tx_conf != TLS_HW && ctx->rx_conf != TLS_HW; if (ctx->tx_conf != TLS_BASE || ctx->rx_conf != TLS_BASE) tls_sk_proto_cleanup(sk, ctx, timeo); write_lock_bh(&sk->sk_callback_lock); - if (free_ctx) - rcu_assign_pointer(icsk->icsk_ulp_data, NULL); WRITE_ONCE(sk->sk_prot, ctx->sk_proto); + if (sk->sk_socket) + WRITE_ONCE(sk->sk_socket->ops, ctx->sk_proto_ops); if (sk->sk_write_space == tls_write_space) sk->sk_write_space = ctx->sk_write_space; + if (sk->sk_destruct == tls_device_sk_destruct) + sk->sk_destruct = ctx->sk_destruct; + if (free_ctx) { + rcu_assign_pointer(icsk->icsk_ulp_data, NULL); + if (icsk->icsk_ulp_ops) { + /* Balance try_module_get in __tcp_ulp_find_autoload */ + module_put(icsk->icsk_ulp_ops->owner); + icsk->icsk_ulp_ops = NULL; + } + } write_unlock_bh(&sk->sk_callback_lock); - release_sock(sk); if (ctx->tx_conf == TLS_SW) tls_sw_free_ctx_tx(ctx); +} + +static void tls_sk_proto_close(struct sock *sk, long timeout) +{ + struct tls_context *ctx; + bool free_ctx; + + ctx = tls_get_ctx(sk); + if (!ctx) { + sk->sk_prot->close(sk, timeout); + return; + } + + if (ctx->tx_conf == TLS_SW) + tls_sw_cancel_work_tx(ctx); + + lock_sock(sk); + /* Re-read ctx under lock, as it may have been cleared by disconnect */ + ctx = tls_get_ctx(sk); + if (!ctx) { + release_sock(sk); + sk->sk_prot->close(sk, timeout); + return; + } + + /* Check if disconnect is in progress after acquiring lock */ + if (test_bit(TLS_DISCONNECTING, &ctx->flags)) { + release_sock(sk); + ctx->sk_proto->close(sk, timeout); + return; + } + + free_ctx = ctx->tx_conf != TLS_HW && ctx->rx_conf != TLS_HW; + tls_sk_proto_free(sk, ctx, free_ctx); + release_sock(sk); + if (ctx->rx_conf == TLS_SW || ctx->rx_conf == TLS_HW) tls_sw_strparser_done(ctx); if (ctx->rx_conf == TLS_SW) @@ -904,7 +943,52 @@ static int tls_setsockopt(struct sock *sk, int level, int optname, static int tls_disconnect(struct sock *sk, int flags) { - return -EOPNOTSUPP; + struct tls_context *ctx; + bool free_ctx; + int rc; + + ctx = tls_get_ctx(sk); + if (!ctx) + return 0; + + if (!ctx->sk_proto->disconnect) + return -EOPNOTSUPP; + + set_bit(TLS_DISCONNECTING, &ctx->flags); + + rc = ctx->sk_proto->disconnect(sk, flags); + if (rc) { + clear_bit(TLS_DISCONNECTING, &ctx->flags); + return rc; + } + + if (ctx->tx_conf == TLS_SW) { + struct tls_sw_context_tx *sw_ctx_tx = tls_sw_ctx_tx(ctx); + + set_bit(BIT_TX_CLOSING, &sw_ctx_tx->tx_bitmask); + set_bit(BIT_TX_SCHEDULED, &sw_ctx_tx->tx_bitmask); + + release_sock(sk); + disable_delayed_work_sync(&sw_ctx_tx->tx_work.work); + lock_sock(sk); + } + + free_ctx = ctx->tx_conf != TLS_HW && ctx->rx_conf != TLS_HW; + tls_sk_proto_free(sk, ctx, free_ctx); + + if (ctx->rx_conf == TLS_SW) { + struct tls_sw_context_rx *sw_ctx = tls_sw_ctx_rx(ctx); + + release_sock(sk); + tls_strp_done(&sw_ctx->strp); + tls_sw_free_ctx_rx(ctx); + lock_sock(sk); + } + + if (free_ctx) + tls_ctx_free(sk, ctx); + + return 0; } struct tls_context *tls_ctx_create(struct sock *sk) @@ -918,6 +1002,8 @@ struct tls_context *tls_ctx_create(struct sock *sk) mutex_init(&ctx->tx_lock); ctx->sk_proto = READ_ONCE(sk->sk_prot); + if (sk->sk_socket) + ctx->sk_proto_ops = READ_ONCE(sk->sk_socket->ops); ctx->sk = sk; /* Release semantic of rcu_assign_pointer() ensures that * ctx->sk_proto is visible before changing sk->sk_prot in -- 2.55.0 ^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH mptcp-next 1/2] tls: implement tls_disconnect 2026-10-14 8:59 ` [PATCH mptcp-next 1/2] tls: implement tls_disconnect Geliang Tang @ 2026-10-14 9:42 ` sashiko-bot 2026-10-15 0:34 ` kernel test robot 1 sibling, 0 replies; 7+ messages in thread From: sashiko-bot @ 2026-10-14 9:42 UTC (permalink / raw) To: Geliang Tang, mptcp Thank you for your contribution! Sashiko AI review found 5 potential issue(s) to consider: - [High] net/tls: double free of tls_context on concurrent connect(AF_UNSPEC) - [High] net/tls: memory leak of TLS_HW contexts due to unconditional sk_destruct overwrite - [High] net/tls: NULL pointer dereference in lockless socket ops on concurrent disconnect - [High] tls: UAF in recvmsg/sendmsg due to concurrent tls_disconnect - [High] tls: memory leak of HW offload context due to unconditional sk_destruct restore -- commit c85d98242c0f64ea4b94701ff52f11b27b61f2a3 Author: Geliang Tang <geliang@kernel.org> tls: implement tls_disconnect Implement disconnect support for TLS sockets via connect(AF_UNSPEC). The handler invokes the underlying disconnect() first, then on success cancels TX work (for TLS_SW), calls tls_sk_proto_free() to restore original protocol operations and clear TLS state, cleans up RX context and frees the TLS context. > diff --git a/net/tls/tls_main.c b/net/tls/tls_main.c > index 8bdb78718a8d4..d00e56af628a0 100644 > --- a/net/tls/tls_main.c > +++ b/net/tls/tls_main.c [ ... ] > -static void tls_sk_proto_close(struct sock *sk, long timeout) > +static void tls_sk_proto_free(struct sock *sk, > + struct tls_context *ctx, > + bool free_ctx) > { > struct inet_connection_sock *icsk = inet_csk(sk); > - struct tls_context *ctx = tls_get_ctx(sk); > long timeo = sock_sndtimeo(sk, 0); > - bool free_ctx; > - > - if (ctx->tx_conf == TLS_SW) > - tls_sw_cancel_work_tx(ctx); > - > - lock_sock(sk); > - free_ctx = ctx->tx_conf != TLS_HW && ctx->rx_conf != TLS_HW; > > if (ctx->tx_conf != TLS_BASE || ctx->rx_conf != TLS_BASE) > tls_sk_proto_cleanup(sk, ctx, timeo); > > write_lock_bh(&sk->sk_callback_lock); > - if (free_ctx) > - rcu_assign_pointer(icsk->icsk_ulp_data, NULL); > WRITE_ONCE(sk->sk_prot, ctx->sk_proto); > + if (sk->sk_socket) > + WRITE_ONCE(sk->sk_socket->ops, ctx->sk_proto_ops); > if (sk->sk_write_space == tls_write_space) > sk->sk_write_space = ctx->sk_write_space; > + if (sk->sk_destruct == tls_device_sk_destruct) > + sk->sk_destruct = ctx->sk_destruct; [Severity: High] For hardware-offloaded TLS sockets (TLS_HW), free_ctx evaluates to false. This means tls_ctx_free() is intentionally skipped so the context can be cleaned up asynchronously later. However, this code unconditionally unhooks tls_device_sk_destruct and restores the original socket destructor. Does this completely bypass the hardware offload cleanup and permanently leak the tls_context and associated NIC hardware state when the socket is ultimately destroyed? > + if (free_ctx) { > + rcu_assign_pointer(icsk->icsk_ulp_data, NULL); [Severity: High] When tls_disconnect() is called, it can run concurrently with lockless operations like setsockopt() or poll() on the same file descriptor. If tls_disconnect() sets icsk_ulp_data to NULL here while tls_setsockopt() or tls_sk_poll() are fetching it locklessly via tls_get_ctx(), won't those functions dereference a NULL pointer since they don't validate the pointer before dereferencing ctx? > + if (icsk->icsk_ulp_ops) { > + /* Balance try_module_get in __tcp_ulp_find_autoload */ > + module_put(icsk->icsk_ulp_ops->owner); > + icsk->icsk_ulp_ops = NULL; > + } > + } > write_unlock_bh(&sk->sk_callback_lock); > - release_sock(sk); > if (ctx->tx_conf == TLS_SW) > tls_sw_free_ctx_tx(ctx); > +} [ ... ] > @@ -904,7 +943,52 @@ static int tls_setsockopt(struct sock *sk, int level, int optname, > > static int tls_disconnect(struct sock *sk, int flags) > { > - return -EOPNOTSUPP; > + struct tls_context *ctx; > + bool free_ctx; > + int rc; > + > + ctx = tls_get_ctx(sk); > + if (!ctx) > + return 0; > + > + if (!ctx->sk_proto->disconnect) > + return -EOPNOTSUPP; > + > + set_bit(TLS_DISCONNECTING, &ctx->flags); [Severity: High] Two threads can concurrently call connect() with AF_UNSPEC on the same socket file descriptor. If thread 1 enters tls_disconnect(), sets the TLS_DISCONNECTING bit, and temporarily drops the socket lock to wait for disable_delayed_work_sync(), thread 2 can acquire the lock and enter tls_disconnect() as well. Since set_bit() is used instead of test_and_set_bit() to abort, thread 2 will resolve the same ctx pointer and proceed. Will this result in both threads sequentially executing tls_sk_proto_free() and tls_ctx_free(), causing a double free of the contexts? > + > + rc = ctx->sk_proto->disconnect(sk, flags); > + if (rc) { > + clear_bit(TLS_DISCONNECTING, &ctx->flags); > + return rc; > + } [ ... ] > + if (ctx->rx_conf == TLS_SW) { > + struct tls_sw_context_rx *sw_ctx = tls_sw_ctx_rx(ctx); > + > + release_sock(sk); > + tls_strp_done(&sw_ctx->strp); > + tls_sw_free_ctx_rx(ctx); > + lock_sock(sk); > + } > + > + if (free_ctx) > + tls_ctx_free(sk, ctx); [Severity: High] Threads calling tls_sw_recvmsg() or tls_sw_sendmsg() cache pointers to the RX/TX contexts and then temporarily drop the socket lock to wait for data or memory via sk_wait_event() or sk_stream_wait_memory(). If a concurrent disconnect triggers tls_disconnect(), it acquires the socket lock and synchronously frees the RX and TX contexts here. When the waiting recvmsg or sendmsg thread wakes up, won't it re-acquire the socket lock and use its locally cached context pointer, leading to a use-after-free read or write? > + > + return 0; > } -- Sashiko AI review · https://sashiko.dev/#/patchset/cover.1791967771.git.tanggeliang@kylinos.cn?part=1 ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH mptcp-next 1/2] tls: implement tls_disconnect 2026-10-14 8:59 ` [PATCH mptcp-next 1/2] tls: implement tls_disconnect Geliang Tang 2026-10-14 9:42 ` sashiko-bot @ 2026-10-15 0:34 ` kernel test robot 1 sibling, 0 replies; 7+ messages in thread From: kernel test robot @ 2026-10-15 0:34 UTC (permalink / raw) To: Geliang Tang, mptcp; +Cc: oe-kbuild-all, Geliang Tang Hi Geliang, kernel test robot noticed the following build errors: [auto build test ERROR on mptcp/export] [also build test ERROR on mptcp/export-net shuah-kselftest/next shuah-kselftest/fixes linus/master v7.3-rc7 next-20261012] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/Geliang-Tang/tls-implement-tls_disconnect/20261014-165935 base: https://github.com/multipath-tcp/mptcp_net-next.git export patch link: https://lore.kernel.org/r/6ffac9e36dab9b4f5fdb6e55a744b35f0d51ffb4.1791967771.git.tanggeliang%40kylinos.cn patch subject: [PATCH mptcp-next 1/2] tls: implement tls_disconnect config: m68k-defconfig (https://download.01.org/0day-ci/archive/20261015/202610150856.tk1Ryxlc-lkp@intel.com/config) compiler: m68k-linux-gcc (GCC) 16.1.0 reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20261015/202610150856.tk1Ryxlc-lkp@intel.com/reproduce) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp@intel.com> | Closes: https://lore.kernel.org/oe-kbuild-all/202610150856.tk1Ryxlc-lkp@intel.com/ All errors (new ones prefixed by >>): net/tls/tls_main.c: In function 'tls_sk_proto_free': >> net/tls/tls_main.c:377:32: error: 'tls_device_sk_destruct' undeclared (first use in this function); did you mean 'tls_device_sendmsg'? 377 | if (sk->sk_destruct == tls_device_sk_destruct) | ^~~~~~~~~~~~~~~~~~~~~~ | tls_device_sendmsg net/tls/tls_main.c:377:32: note: each undeclared identifier is reported only once for each function it appears in vim +377 net/tls/tls_main.c 360 361 static void tls_sk_proto_free(struct sock *sk, 362 struct tls_context *ctx, 363 bool free_ctx) 364 { 365 struct inet_connection_sock *icsk = inet_csk(sk); 366 long timeo = sock_sndtimeo(sk, 0); 367 368 if (ctx->tx_conf != TLS_BASE || ctx->rx_conf != TLS_BASE) 369 tls_sk_proto_cleanup(sk, ctx, timeo); 370 371 write_lock_bh(&sk->sk_callback_lock); 372 WRITE_ONCE(sk->sk_prot, ctx->sk_proto); 373 if (sk->sk_socket) 374 WRITE_ONCE(sk->sk_socket->ops, ctx->sk_proto_ops); 375 if (sk->sk_write_space == tls_write_space) 376 sk->sk_write_space = ctx->sk_write_space; > 377 if (sk->sk_destruct == tls_device_sk_destruct) 378 sk->sk_destruct = ctx->sk_destruct; 379 if (free_ctx) { 380 rcu_assign_pointer(icsk->icsk_ulp_data, NULL); 381 if (icsk->icsk_ulp_ops) { 382 /* Balance try_module_get in __tcp_ulp_find_autoload */ 383 module_put(icsk->icsk_ulp_ops->owner); 384 icsk->icsk_ulp_ops = NULL; 385 } 386 } 387 write_unlock_bh(&sk->sk_callback_lock); 388 if (ctx->tx_conf == TLS_SW) 389 tls_sw_free_ctx_tx(ctx); 390 } 391 -- 0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests/wiki ^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH mptcp-next 2/2] selftests: tls: update disconnect tests 2026-10-14 8:59 [PATCH mptcp-next 0/2] TLS disconnect support Geliang Tang 2026-10-14 8:59 ` [PATCH mptcp-next 1/2] tls: implement tls_disconnect Geliang Tang @ 2026-10-14 8:59 ` Geliang Tang 2026-10-14 10:06 ` [PATCH mptcp-next 0/2] TLS disconnect support MPTCP CI 2026-10-14 13:19 ` Matthieu Baerts 3 siblings, 0 replies; 7+ messages in thread From: Geliang Tang @ 2026-10-14 8:59 UTC (permalink / raw) To: mptcp; +Cc: Geliang Tang From: Geliang Tang <tanggeliang@kylinos.cn> Update the TLS disconnect test to verify the full disconnect/reconnect cycle. The test first establishes a TLS connection and verifies data transfer works. It then disconnects both ends of the connection using connect(AF_UNSPEC) and verifies that send/recv operations fail with appropriate error codes (EPIPE/ECONNRESET for send, ENOTCONN for recv). The client socket is then reconnected to a new server, TLS is re-established, and data transfer is verified to work again. This ensures TLS sockets can be properly disconnected and reconnected without state corruption. Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn> --- tools/testing/selftests/net/tls.c | 57 +++++++++++++++++++++++++++++-- 1 file changed, 55 insertions(+), 2 deletions(-) diff --git a/tools/testing/selftests/net/tls.c b/tools/testing/selftests/net/tls.c index 9d3cd4fff062..ada2f43d05d3 100644 --- a/tools/testing/selftests/net/tls.c +++ b/tools/testing/selftests/net/tls.c @@ -1985,8 +1985,10 @@ TEST_F(tls_basic, disconnect) int send_len = strlen(test_str) + 1; struct tls_crypto_info_keys key; struct sockaddr_in addr; + socklen_t len; char buf[20]; int ret; + int sfd; if (self->notls) return; @@ -2005,14 +2007,65 @@ TEST_F(tls_basic, disconnect) ret = setsockopt(self->cfd, SOL_TLS, TLS_RX, &key, key.len); ASSERT_EQ(ret, 0); + bzero(buf, sizeof(buf)); + EXPECT_EQ(recv(self->cfd, buf, send_len, 0), send_len); + EXPECT_EQ(memcmp(buf, test_str, send_len), 0); + addr.sin_family = AF_UNSPEC; addr.sin_addr.s_addr = htonl(INADDR_ANY); addr.sin_port = 0; ret = connect(self->cfd, &addr, sizeof(addr)); - EXPECT_EQ(ret, -1); - EXPECT_EQ(errno, EOPNOTSUPP); + EXPECT_EQ(ret, 0); + + /* Verify send/recv fail after disconnect. */ + EXPECT_EQ(send(self->cfd, buf, sizeof(buf), + MSG_DONTWAIT | MSG_NOSIGNAL), -1); + EXPECT_TRUE(errno == EPIPE || errno == ECONNRESET); + EXPECT_EQ(recv(self->cfd, buf, sizeof(buf), MSG_DONTWAIT), -1); + EXPECT_EQ(errno, ENOTCONN); + + /* Disconnect fd as well. */ + ret = connect(self->fd, &addr, sizeof(addr)); + ASSERT_EQ(ret, 0); + EXPECT_EQ(send(self->fd, buf, sizeof(buf), + MSG_DONTWAIT | MSG_NOSIGNAL), -1); + EXPECT_TRUE(errno == EPIPE || errno == ECONNRESET); + EXPECT_EQ(recv(self->fd, buf, sizeof(buf), MSG_DONTWAIT), -1); + EXPECT_EQ(errno, ENOTCONN); + + /* Reconnect fd to a new server and re-setup TLS. */ + addr.sin_family = AF_INET; + addr.sin_port = 0; + sfd = socket(AF_INET, SOCK_STREAM, 0); + EXPECT_GE(sfd, 0); + if (sfd < 0) + return; + + /* sfd not closed on ASSERT failure, kernel cleans up on test abort */ + ASSERT_EQ(bind(sfd, &addr, sizeof(addr)), 0); + ASSERT_EQ(listen(sfd, 10), 0); + len = sizeof(addr); + ASSERT_EQ(getsockname(sfd, &addr, &len), 0); + ASSERT_EQ(connect(self->fd, (struct sockaddr *)&addr, sizeof(addr)), 0); + ret = accept(sfd, &addr, &len); + close(sfd); + ASSERT_GE(ret, 0); + close(self->cfd); + self->cfd = ret; + + ASSERT_EQ(setsockopt(self->fd, IPPROTO_TCP, TCP_ULP, "tls", + sizeof("tls")), 0); + ASSERT_EQ(setsockopt(self->cfd, IPPROTO_TCP, TCP_ULP, "tls", + sizeof("tls")), 0); + ASSERT_EQ(setsockopt(self->fd, SOL_TLS, TLS_TX, &key, key.len), 0); + ASSERT_EQ(setsockopt(self->cfd, SOL_TLS, TLS_RX, &key, key.len), 0); + + /* Verify data transfer works after reconnect. */ + EXPECT_EQ(send(self->fd, test_str, send_len, 0), send_len); + bzero(buf, sizeof(buf)); EXPECT_EQ(recv(self->cfd, buf, send_len, 0), send_len); + EXPECT_EQ(memcmp(buf, test_str, send_len), 0); } TEST_F(tls, rekey) -- 2.55.0 ^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH mptcp-next 0/2] TLS disconnect support 2026-10-14 8:59 [PATCH mptcp-next 0/2] TLS disconnect support Geliang Tang 2026-10-14 8:59 ` [PATCH mptcp-next 1/2] tls: implement tls_disconnect Geliang Tang 2026-10-14 8:59 ` [PATCH mptcp-next 2/2] selftests: tls: update disconnect tests Geliang Tang @ 2026-10-14 10:06 ` MPTCP CI 2026-10-14 13:19 ` Matthieu Baerts 3 siblings, 0 replies; 7+ messages in thread From: MPTCP CI @ 2026-10-14 10:06 UTC (permalink / raw) To: Geliang Tang; +Cc: mptcp Hi Geliang, Thank you for your modifications, that's great! Our CI did some validations and here is its report: - KVM Validation: normal (except selftest_mptcp_join): Success! ✅ - KVM Validation: normal (only selftest_mptcp_join): Success! ✅ - KVM Validation: debug (except selftest_mptcp_join): Success! ✅ - KVM Validation: debug (only selftest_mptcp_join): Success! ✅ - KVM Validation: btf-normal (only bpftest_all): Success! ✅ - KVM Validation: btf-debug (only bpftest_all): Success! ✅ - Perf: Success! ✅ - Task: https://github.com/multipath-tcp/mptcp_net-next/actions/runs/38541308008 Initiator: Patchew Applier Commits: https://github.com/multipath-tcp/mptcp_net-next/commits/cab552cd4a4d Patchwork: https://patchwork.kernel.org/project/mptcp/list/?series=1185404 If there are some issues, you can reproduce them using the same environment as the one used by the CI thanks to a docker image, e.g.: $ cd [kernel source code] $ docker run -v "${PWD}:${PWD}:rw" -w "${PWD}" --privileged --rm -it \ --pull always mptcp/mptcp-upstream-virtme-docker:latest \ auto-normal For more details: https://github.com/multipath-tcp/mptcp-upstream-virtme-docker Please note that despite all the efforts that have been already done to have a stable tests suite when executed on a public CI like here, it is possible some reported issues are not due to your modifications. Still, do not hesitate to help us improve that ;-) Cheers, MPTCP GH Action bot Bot operated by Matthieu Baerts (NGI0 Core) ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH mptcp-next 0/2] TLS disconnect support 2026-10-14 8:59 [PATCH mptcp-next 0/2] TLS disconnect support Geliang Tang ` (2 preceding siblings ...) 2026-10-14 10:06 ` [PATCH mptcp-next 0/2] TLS disconnect support MPTCP CI @ 2026-10-14 13:19 ` Matthieu Baerts 3 siblings, 0 replies; 7+ messages in thread From: Matthieu Baerts @ 2026-10-14 13:19 UTC (permalink / raw) To: Geliang Tang, mptcp; +Cc: Geliang Tang Hi Geliang, On 14/10/2026 10:59, Geliang Tang wrote: > From: Geliang Tang <tanggeliang@kylinos.cn> > > To verify the correctness of MPTCP KTLS implementation, I added TLS test > support to MPTCP selftests mptcp_connect.c. The test results showed that > the disconnect test group failed with error code EOPNOTSUPP, so I added > this series to support TLS disconnect. I guess that's more a question for the KTLS maintainers, but my feeling is that the disconnect is not supported on purpose because that's probably not used in production, and source of many errors: see all the bugs found around that for TCP and MPTCP (and others). In fact, I just did a git blame, and found this: 5071a1e606b3 ("net: tls: explicitly disallow disconnect"). Cheers, Matt -- Sponsored by the NGI0 Core fund. ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2026-10-15 0:34 UTC | newest] Thread overview: 7+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-10-14 8:59 [PATCH mptcp-next 0/2] TLS disconnect support Geliang Tang 2026-10-14 8:59 ` [PATCH mptcp-next 1/2] tls: implement tls_disconnect Geliang Tang 2026-10-14 9:42 ` sashiko-bot 2026-10-15 0:34 ` kernel test robot 2026-10-14 8:59 ` [PATCH mptcp-next 2/2] selftests: tls: update disconnect tests Geliang Tang 2026-10-14 10:06 ` [PATCH mptcp-next 0/2] TLS disconnect support MPTCP CI 2026-10-14 13:19 ` Matthieu Baerts
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.