Netdev List
 help / color / mirror / Atom feed
* [PATCH net v2 0/2] tls: fix plaintext sk_msg ring over-fill
@ 2026-08-04  5:28 chanyoung
  2026-08-04  5:28 ` [PATCH net v2 1/2] tls: don't leave a full plaintext sk_msg ring unpushed chanyoung
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: chanyoung @ 2026-08-04  5:28 UTC (permalink / raw)
  To: netdev
  Cc: Sabrina Dubroca, Jakub Kicinski, John Fastabend, David Howells,
	Shuah Khan, linux-kselftest, chanyoung

An unprivileged user can oops the kernel by splicing into a kTLS socket
whose open record already has a full plaintext sk_msg ring.  Reproduced on
net (53658c6f3682) with a stock config, no KASAN.

Patch 2 oopses an unpatched kernel and passes with patch 1 applied.

v2:
  - fix the copy path so a full record is never left unpushed, rather than
    making tls_sw_sendmsg_splice() tolerate a full ring (Sabrina)
  - selftest: drop the comments, one splice instead of four, reuse a single
    pipe, compare the whole blob, sweep 16..44 fragments
v1: https://lore.kernel.org/netdev/20260726105556.2719227-1-ppoo1220@gmail.com/

chanyoung (2):
  tls: don't leave a full plaintext sk_msg ring unpushed
  selftests: tls: add a test for splicing onto a full plaintext record

 net/tls/tls_sw.c                  | 14 ++++++++++++
 tools/testing/selftests/net/tls.c | 37 +++++++++++++++++++++++++++++++
 2 files changed, 51 insertions(+)

-- 
2.43.0


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH net v2 1/2] tls: don't leave a full plaintext sk_msg ring unpushed
  2026-08-04  5:28 [PATCH net v2 0/2] tls: fix plaintext sk_msg ring over-fill chanyoung
@ 2026-08-04  5:28 ` chanyoung
  2026-08-04  5:28 ` [PATCH net v2 2/2] selftests: tls: add a test for splicing onto a full plaintext record chanyoung
  2026-08-06 16:10 ` [PATCH net v2 0/2] tls: fix plaintext sk_msg ring over-fill patchwork-bot+netdevbpf
  2 siblings, 0 replies; 4+ messages in thread
From: chanyoung @ 2026-08-04  5:28 UTC (permalink / raw)
  To: netdev
  Cc: Sabrina Dubroca, Jakub Kicinski, John Fastabend, David Howells,
	Shuah Khan, linux-kselftest, chanyoung, stable

When the copy path in tls_sw_sendmsg_locked() adds the fragment that fills
the plaintext sk_msg ring, it does not set full_record, so the record is
left full and unpushed.  A later splice() then adds to an already full
ring: sk_msg_page_add() has no fullness check of its own, so sg.end wraps
onto sg.start and the ring appears empty.  Fragments added after that
overwrite live entries, and sg.size no longer matches what is reachable
between sg.start and sg.end, so pushing the record runs the scatterwalk off
the end of the scatterlist.

An unprivileged user can trigger this on a loopback TCP socket with the
"tls" ULP attached:

  BUG: kernel NULL pointer dereference, address: 0000000000000008
  RIP: 0010:memcpy_from_scatterwalk+0x32/0xc0
  Call Trace:
   skcipher_walk_next+0x1d1/0x2c0
   gcm_encrypt_aesni_avx+0x1e9/0x220
   bpf_exec_tx_verdict+0x3bb/0x860
   tls_sw_sendmsg+0xa1a/0xca0
   __sys_sendto+0x1da/0x1f0

Set full_record in the copy path when the ring becomes full, and push a
record that is already full on entry to the sendmsg loop.

Suggested-by: Sabrina Dubroca <sd@queasysnail.net>
Fixes: fe1e81d4f73b ("tls/sw: Support MSG_SPLICE_PAGES")
Cc: stable@vger.kernel.org
Signed-off-by: chanyoung <ppoo1220@gmail.com>
---
 net/tls/tls_sw.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c
index d4afc90fd79..d2e399be8ef 100644
--- a/net/tls/tls_sw.c
+++ b/net/tls/tls_sw.c
@@ -832,6 +832,14 @@ static int tls_sw_sendmsg_locked(struct sock *sk, struct msghdr *msg,
 		if (!sk_stream_memory_free(sk))
 			goto wait_for_sndbuf;
 
+		/* open record may be full if we couldn't push it in the last sendmsg call */
+		if (sk_msg_full(msg_pl)) {
+			full_record = true;
+			sk_msg_trim(sk, msg_en,
+				    msg_pl->sg.size + prot->overhead_size);
+			goto copied;
+		}
+
 alloc_encrypted:
 		ret = tls_alloc_encrypted_msg(sk, required_size);
 		if (ret) {
@@ -921,6 +929,12 @@ static int tls_sw_sendmsg_locked(struct sock *sk, struct msghdr *msg,
 						       msg_pl, try_to_copy);
 			if (ret < 0)
 				goto trim_sgl;
+
+			if (sk_msg_full(msg_pl)) {
+				full_record = true;
+				sk_msg_trim(sk, msg_en,
+					    msg_pl->sg.size + prot->overhead_size);
+			}
 		}
 
 		/* Open records defined only if successfully copied, otherwise
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH net v2 2/2] selftests: tls: add a test for splicing onto a full plaintext record
  2026-08-04  5:28 [PATCH net v2 0/2] tls: fix plaintext sk_msg ring over-fill chanyoung
  2026-08-04  5:28 ` [PATCH net v2 1/2] tls: don't leave a full plaintext sk_msg ring unpushed chanyoung
@ 2026-08-04  5:28 ` chanyoung
  2026-08-06 16:10 ` [PATCH net v2 0/2] tls: fix plaintext sk_msg ring over-fill patchwork-bot+netdevbpf
  2 siblings, 0 replies; 4+ messages in thread
From: chanyoung @ 2026-08-04  5:28 UTC (permalink / raw)
  To: netdev
  Cc: Sabrina Dubroca, Jakub Kicinski, John Fastabend, David Howells,
	Shuah Khan, linux-kselftest, chanyoung

Splicing onto a plaintext sk_msg ring that is already full used to wrap the
ring and make the kernel oops in the scatterwalk once the record was
pushed.

Only the copy path leaves the ring full without pushing it, so splice until
the ring is one fragment short, add the last fragment with a one-byte
MSG_MORE send, and splice once more before pushing the record.

CONFIG_MAX_SKB_FRAGS is 17..45, so that last fragment follows between 16
and 44 splices; sweep that range to trigger the bug on any build.

Signed-off-by: chanyoung <ppoo1220@gmail.com>
---
 tools/testing/selftests/net/tls.c | 37 +++++++++++++++++++++++++++++++
 1 file changed, 37 insertions(+)

diff --git a/tools/testing/selftests/net/tls.c b/tools/testing/selftests/net/tls.c
index cbdd3ea28b9..3d6f553eaf9 100644
--- a/tools/testing/selftests/net/tls.c
+++ b/tools/testing/selftests/net/tls.c
@@ -835,6 +835,43 @@ TEST_F(tls, send_and_splice)
 	EXPECT_EQ(memcmp(mem_send, mem_recv, send_len), 0);
 }
 
+TEST_F(tls, splice_onto_full_record)
+{
+	char mem_send[4608];
+	char mem_recv[4608];
+	int frag_len = 100;
+	int nfrags, i, off;
+	int p[2];
+
+	memrnd(mem_send, sizeof(mem_send));
+	ASSERT_GE(pipe(p), 0);
+
+	for (nfrags = 16; nfrags <= 44; nfrags++) {
+		for (i = 0, off = 0; i < nfrags; i++, off += frag_len) {
+			EXPECT_EQ(write(p[1], mem_send + off, frag_len), frag_len);
+			EXPECT_EQ(splice(p[0], NULL, self->fd, NULL, frag_len,
+					 SPLICE_F_MORE), frag_len);
+		}
+
+		EXPECT_EQ(send(self->fd, mem_send + off, 1, MSG_MORE), 1);
+		off++;
+
+		EXPECT_EQ(write(p[1], mem_send + off, frag_len), frag_len);
+		EXPECT_EQ(splice(p[0], NULL, self->fd, NULL, frag_len,
+				 SPLICE_F_MORE), frag_len);
+		off += frag_len;
+
+		EXPECT_EQ(send(self->fd, mem_send + off, 1, 0), 1);
+		off++;
+
+		EXPECT_EQ(recv(self->cfd, mem_recv, off, MSG_WAITALL), off);
+		EXPECT_EQ(memcmp(mem_send, mem_recv, off), 0);
+	}
+
+	close(p[0]);
+	close(p[1]);
+}
+
 TEST_F(tls, splice_to_pipe)
 {
 	int send_len = TLS_PAYLOAD_MAX_LEN;
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH net v2 0/2] tls: fix plaintext sk_msg ring over-fill
  2026-08-04  5:28 [PATCH net v2 0/2] tls: fix plaintext sk_msg ring over-fill chanyoung
  2026-08-04  5:28 ` [PATCH net v2 1/2] tls: don't leave a full plaintext sk_msg ring unpushed chanyoung
  2026-08-04  5:28 ` [PATCH net v2 2/2] selftests: tls: add a test for splicing onto a full plaintext record chanyoung
@ 2026-08-06 16:10 ` patchwork-bot+netdevbpf
  2 siblings, 0 replies; 4+ messages in thread
From: patchwork-bot+netdevbpf @ 2026-08-06 16:10 UTC (permalink / raw)
  To: chanyoung
  Cc: netdev, sd, kuba, john.fastabend, dhowells, shuah,
	linux-kselftest

Hello:

This series was applied to netdev/net.git (main)
by Jakub Kicinski <kuba@kernel.org>:

On Tue,  4 Aug 2026 14:28:34 +0900 you wrote:
> An unprivileged user can oops the kernel by splicing into a kTLS socket
> whose open record already has a full plaintext sk_msg ring.  Reproduced on
> net (53658c6f3682) with a stock config, no KASAN.
> 
> Patch 2 oopses an unpatched kernel and passes with patch 1 applied.
> 
> v2:
>   - fix the copy path so a full record is never left unpushed, rather than
>     making tls_sw_sendmsg_splice() tolerate a full ring (Sabrina)
>   - selftest: drop the comments, one splice instead of four, reuse a single
>     pipe, compare the whole blob, sweep 16..44 fragments
> v1: https://lore.kernel.org/netdev/20260726105556.2719227-1-ppoo1220@gmail.com/
> 
> [...]

Here is the summary with links:
  - [net,v2,1/2] tls: don't leave a full plaintext sk_msg ring unpushed
    https://git.kernel.org/netdev/net/c/7bca91d63341
  - [net,v2,2/2] selftests: tls: add a test for splicing onto a full plaintext record
    https://git.kernel.org/netdev/net/c/3834e079d67f

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html



^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2026-08-06 16:10 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-04  5:28 [PATCH net v2 0/2] tls: fix plaintext sk_msg ring over-fill chanyoung
2026-08-04  5:28 ` [PATCH net v2 1/2] tls: don't leave a full plaintext sk_msg ring unpushed chanyoung
2026-08-04  5:28 ` [PATCH net v2 2/2] selftests: tls: add a test for splicing onto a full plaintext record chanyoung
2026-08-06 16:10 ` [PATCH net v2 0/2] tls: fix plaintext sk_msg ring over-fill patchwork-bot+netdevbpf

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox