* [PATCH net v2 0/2] kcm: don't sleep in softirq when the lower socket uses kTLS
@ 2026-10-16 2:44 Rishikesh Jethwani
2026-10-16 2:44 ` [PATCH net v2 1/2] kcm: defer receive parsing when the lower socket's read_sock may sleep Rishikesh Jethwani
` (3 more replies)
0 siblings, 4 replies; 6+ messages in thread
From: Rishikesh Jethwani @ 2026-10-16 2:44 UTC (permalink / raw)
To: netdev
Cc: David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Rishikesh Jethwani
When a TCP socket with software kTLS RX is attached to a KCM mux,
psock_data_ready() calls strp_data_ready() from softirq, which calls the
socket's read_sock(). For kTLS that is tls_sw_read_sock(), which can
sleep, and CONFIG_DEBUG_ATOMIC_SLEEP reports it on every run of a
loopback reproducer.
Patch 1 is the fix: KCM parses inline only when read_sock is
tcp_read_sock() and otherwise defers to the strparser work, which runs
under lock_sock(). It applies and builds on its own, including on
stable kernels.
Patch 2 addresses review feedback on v1 and is needed by patch 1.
kstrp, the workqueue that deferred work runs on, is an ordered
workqueue shared by every strparser user (KCM, sockmap, espintcp,
ovpn). With patch 1 alone, a KCM psock decrypting kTLS records in
software on kstrp would delay parsing and message timeouts for every
other strparser socket on the system. Patch 2 makes kstrp per-CPU. It
has no Fixes tag: the ordered workqueue is as old as strparser, and it
only becomes a real problem for KCM over kTLS with patch 1.
Other strparser users are not affected by the bug fixed in patch 1:
espintcp is itself a TCP ULP and cannot be combined with kTLS, ovpn
installs its own ops built from inet_stream_ops, and sockmap reads
through tcp_bpf_strp_read_sock() and is mutually exclusive with kTLS
RX (do_tls_setsockopt_conf() rejects sockets with a psock).
Testing: with patch 1, 5/5 runs of the reproducer produce no splat and
full datagram delivery; without it every run hits "BUG: sleeping
function called from invalid context" in strp_data_ready ->
tls_sw_read_sock. Multi-record messages (>16 KiB each) also deliver
completely with kTLS RX installed before the KCM attach and the whole
stream queued before the reader starts. With patch 2, test_sockmap and the ovpn TCP selftests
pass, strparser work runs concurrently across sockets, and dmesg shows
no warnings.
v2:
- add patch 2 (kstrp per-CPU), per review
- read sock->ops with READ_ONCE(), pairing with update_sk_prot()
v1: https://lore.kernel.org/netdev/20261013033920.2069285-1-rjethwani@purestorage.com/
Rishikesh Jethwani (2):
kcm: defer receive parsing when the lower socket's read_sock may sleep
strparser: don't serialize all parser work on one ordered workqueue
net/kcm/kcmsock.c | 33 +++++++++++++++++++++++++++++++--
net/strparser/strparser.c | 2 +-
2 files changed, 32 insertions(+), 3 deletions(-)
--
2.50.1
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH net v2 1/2] kcm: defer receive parsing when the lower socket's read_sock may sleep
2026-10-16 2:44 [PATCH net v2 0/2] kcm: don't sleep in softirq when the lower socket uses kTLS Rishikesh Jethwani
@ 2026-10-16 2:44 ` Rishikesh Jethwani
2026-10-16 2:44 ` [PATCH net v2 2/2] strparser: don't serialize all parser work on one ordered workqueue Rishikesh Jethwani
` (2 subsequent siblings)
3 siblings, 0 replies; 6+ messages in thread
From: Rishikesh Jethwani @ 2026-10-16 2:44 UTC (permalink / raw)
To: netdev
Cc: David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Rishikesh Jethwani
psock_data_ready() is the lower socket's data_ready callback and can
run in softirq context, under read_lock_bh(&sk->sk_callback_lock). It calls
strp_data_ready(), which, when the socket is not owned by a user,
invokes sock->ops->read_sock() inline to pull records out of the
receive queue. For a plain TCP socket that is tcp_read_sock(), which
does not block.
A ULP may install a different read_sock. kTLS installs
tls_sw_read_sock(), which can sleep: it waits for an asynchronous
AEAD to complete via crypto_wait_req(), flushes the socket backlog
through __sk_flush_backlog(), allocates with sk->sk_allocation, and,
on reader contention in tls_rx_reader_acquire(), enters
sk_wait_event()'s socket release/reacquire path despite the zero
timeout. It passes nonblock, so it does not wait for data, but these
paths can require sleepable context, which softirq and a BH read lock
do not provide. Attaching a kTLS socket to a KCM multiplexor can
therefore sleep in atomic context.
With CONFIG_DEBUG_ATOMIC_SLEEP, a loopback TCP connection using software
kTLS RX, with the receiving socket attached to a KCM mux, reports:
BUG: sleeping function called from invalid context at include/linux/sched/mm.h:321
in_atomic(): 1, irqs_disabled(): 0, non_block: 0, pid: 189, name: ksoftirqd/34
Call Trace:
__might_resched
kmem_cache_alloc_node_noprof
__alloc_skb
alloc_skb_with_frags
tls_rx_one_record
tls_sw_read_sock
strp_read_sock
strp_data_ready
psock_data_ready [kcm]
Keep the inline fast path for tcp_read_sock() and hand any other
read_sock to the parser work via strp_check_rcv(). The work runs
do_strp_work() under lock_sock(), where a sleeping read_sock is fine.
sk->sk_socket should not be NULL here, since KCM holds the lower
socket's file reference while a psock is attached; if it is,
defer as well, as strp_read_sock() would not read without a socket.
The deferred path also skips strp_data_ready()'s need_bytes early
return. That check counts bytes in the TCP receive queue, which for
kTLS is ciphertext rather than parsed records, so it would not be
meaningful there. Without it, a data_ready event can queue work that
finds no complete record and returns; queue_work() does nothing if the
work is already pending.
kTLS installs tls_sw_read_sock() by replacing sk_socket->ops with
WRITE_ONCE() in update_sk_prot() when TLS_RX is configured. That happens
under lock_sock() only, and can happen after the socket is attached to
KCM, so read it with READ_ONCE().
The deferred work runs on kstrp, which is currently an ordered workqueue
shared by all strparser users. The next patch makes it per-CPU, so a
psock whose read_sock does software decryption does not hold up parsing
for other strparser users.
Tested with the reproducer above: 5/5 runs produce no splat and full
datagram delivery; without this change every run hits "BUG: sleeping
function called from invalid context" in strp_data_ready ->
tls_sw_read_sock.
Multi-record messages (>16 KiB each) also deliver completely when kTLS
RX is installed before the KCM attach and the entire stream is queued
before the reader starts: the parser correctly pauses on KCM flow
control (psock RxPause/RdyRx) and resumes on read, with no strparser
need_bytes stall.
Fixes: 662fbcec32f4 ("net/tls: implement ->read_sock()")
Signed-off-by: Rishikesh Jethwani <rjethwani@purestorage.com>
---
net/kcm/kcmsock.c | 33 +++++++++++++++++++++++++++++++--
1 file changed, 31 insertions(+), 2 deletions(-)
diff --git a/net/kcm/kcmsock.c b/net/kcm/kcmsock.c
index 71af69d442f2..ec7aaba17fe6 100644
--- a/net/kcm/kcmsock.c
+++ b/net/kcm/kcmsock.c
@@ -30,6 +30,7 @@
#include <net/kcm.h>
#include <net/netns/generic.h>
#include <net/sock.h>
+#include <net/tcp.h>
#include <uapi/linux/kcm.h>
#include <trace/events/sock.h>
@@ -348,6 +349,30 @@ static void unreserve_rx_kcm(struct kcm_psock *psock,
spin_unlock_bh(&mux->rx_lock);
}
+/* strp_data_ready() calls the lower socket's read_sock() inline, from
+ * softirq and under sk_callback_lock. That is only safe for TCP's own
+ * tcp_read_sock(); anything else goes to the parser work, which runs
+ * under lock_sock(). Called with sk_callback_lock held.
+ */
+static bool psock_can_parse_inline(struct sock *sk)
+{
+ struct socket *sock = sk->sk_socket;
+ const struct proto_ops *ops;
+
+ /* KCM holds the lower socket's file reference while a psock is
+ * attached, so sk_socket should not be NULL here. Defer if it is,
+ * as strp_read_sock() would not read without a socket anyway.
+ */
+ if (!sock)
+ return false;
+
+ /* A ULP's read_sock, such as kTLS's tls_sw_read_sock(), may sleep.
+ * READ_ONCE() pairs with the WRITE_ONCE() in kTLS's update_sk_prot().
+ */
+ ops = READ_ONCE(sock->ops);
+ return ops->read_sock == tcp_read_sock;
+}
+
/* Lower sock lock held */
static void psock_data_ready(struct sock *sk)
{
@@ -358,8 +383,12 @@ static void psock_data_ready(struct sock *sk)
read_lock_bh(&sk->sk_callback_lock);
psock = (struct kcm_psock *)sk->sk_user_data;
- if (likely(psock))
- strp_data_ready(&psock->strp);
+ if (likely(psock)) {
+ if (psock_can_parse_inline(sk))
+ strp_data_ready(&psock->strp);
+ else
+ strp_check_rcv(&psock->strp);
+ }
read_unlock_bh(&sk->sk_callback_lock);
}
--
2.50.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH net v2 2/2] strparser: don't serialize all parser work on one ordered workqueue
2026-10-16 2:44 [PATCH net v2 0/2] kcm: don't sleep in softirq when the lower socket uses kTLS Rishikesh Jethwani
2026-10-16 2:44 ` [PATCH net v2 1/2] kcm: defer receive parsing when the lower socket's read_sock may sleep Rishikesh Jethwani
@ 2026-10-16 2:44 ` Rishikesh Jethwani
2026-10-16 2:54 ` [PATCH net v2 0/2] kcm: don't sleep in softirq when the lower socket uses kTLS netdev-bot+sinfo
2026-10-16 10:13 ` Jiayuan Chen
3 siblings, 0 replies; 6+ messages in thread
From: Rishikesh Jethwani @ 2026-10-16 2:44 UTC (permalink / raw)
To: netdev
Cc: David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Rishikesh Jethwani
strp_wq has been created with create_singlethread_workqueue() since
strparser was introduced, which makes it an ordered workqueue: at most
one strparser work item runs at a time, system-wide. Every strparser
user shares it: KCM, sockmap, espintcp and ovpn's TCP transport, and
every instance's msg_timer_work.
strp_work() takes cb.lock before reading, and every in-tree user leaves
cb.lock at its default, lock_sock(). The single kstrp worker therefore
already stalls for as long as any process holds the socket lock of any
strparser-attached socket, delaying parsing and message timeouts for
every other socket using strparser. The same applies to work that is
slow for other reasons, such as a lower socket's read_sock() doing
software decryption, which is what KCM over kTLS does now that the
previous patch moves its parsing to kstrp.
Nothing relies on the ordering:
- The workqueue core never runs one work item on two workers at
once, so a given strparser's work stays serialized with itself.
- strp_work() and strp_msg_timeout() both run under cb.lock, so they
are serialized against each other per socket by the socket lock,
and strp_abort_strp() is idempotent through strp->stopped.
- strp_done() cancels both with the _sync variants, which work on any
workqueue.
- Different strparsers were never ordered against each other: the
common strp_data_ready() path runs inline in softirq on whichever
CPU received the data, bypassing the workqueue entirely.
Allocate kstrp as a per-CPU, WQ_MEM_RECLAIM workqueue instead. kTLS's
tls-strp workqueue has the same flags, via create_workqueue(), but
caps max_active at 1 per CPU; kstrp uses the default limit (1024 per
CPU), so a work item blocked on a socket lock does not hold up others
queued on the same CPU. A per-CPU workqueue keeps the work local to
the CPU that received the data, like tls-strp; work that stays
CPU-bound for long is excluded from concurrency management by the
workqueue core's CPU-intensive detection.
This lets strparser work for different sockets run concurrently for
every user of strparser, not only KCM. Without it, the previous patch
would let one KCM psock doing software kTLS decryption on kstrp delay
parsing and message timeouts for every other strparser socket.
Tested with test_sockmap and the ovpn TCP selftests; strparser work now
runs concurrently across sockets with no dmesg warnings.
Signed-off-by: Rishikesh Jethwani <rjethwani@purestorage.com>
---
net/strparser/strparser.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/strparser/strparser.c b/net/strparser/strparser.c
index d5b17d099a0e..32fe96ba10d6 100644
--- a/net/strparser/strparser.c
+++ b/net/strparser/strparser.c
@@ -542,7 +542,7 @@ static int __init strp_dev_init(void)
BUILD_BUG_ON(sizeof(struct sk_skb_cb) >
sizeof_field(struct sk_buff, cb));
- strp_wq = create_singlethread_workqueue("kstrp");
+ strp_wq = alloc_workqueue("kstrp", WQ_PERCPU | WQ_MEM_RECLAIM, 0);
if (unlikely(!strp_wq))
return -ENOMEM;
--
2.50.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH net v2 0/2] kcm: don't sleep in softirq when the lower socket uses kTLS
2026-10-16 2:44 [PATCH net v2 0/2] kcm: don't sleep in softirq when the lower socket uses kTLS Rishikesh Jethwani
2026-10-16 2:44 ` [PATCH net v2 1/2] kcm: defer receive parsing when the lower socket's read_sock may sleep Rishikesh Jethwani
2026-10-16 2:44 ` [PATCH net v2 2/2] strparser: don't serialize all parser work on one ordered workqueue Rishikesh Jethwani
@ 2026-10-16 2:54 ` netdev-bot+sinfo
2026-10-16 4:29 ` Rishikesh Jethwani
2026-10-16 10:13 ` Jiayuan Chen
3 siblings, 1 reply; 6+ messages in thread
From: netdev-bot+sinfo @ 2026-10-16 2:54 UTC (permalink / raw)
To: Rishikesh Jethwani
Cc: netdev, David S . Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Simon Horman
Hi!
This is an automated message. This series looks like a fix, but its
commit messages seem to be missing some information:
- How the issue was discovered, e.g. hit in production, hit during
development, syzbot report, manual code inspection, LLM or static
analysis tool scan.
Please do not repost the series just to address the above. Instead,
reply to this email with the missing information, so that reviewers
can take it into account. If the series needs another revision for
other reasons, please include the information in the commit messages
then.
The evaluation is done by an LLM so it may be wrong, if you think
that is the case please reply and explain.
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH net v2 0/2] kcm: don't sleep in softirq when the lower socket uses kTLS
2026-10-16 2:54 ` [PATCH net v2 0/2] kcm: don't sleep in softirq when the lower socket uses kTLS netdev-bot+sinfo
@ 2026-10-16 4:29 ` Rishikesh Jethwani
0 siblings, 0 replies; 6+ messages in thread
From: Rishikesh Jethwani @ 2026-10-16 4:29 UTC (permalink / raw)
To: netdev-bot+sinfo
Cc: netdev, David S . Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Simon Horman
On Thu, Oct 15, 2026 at 7:54 PM <netdev-bot+sinfo@kernel.org> wrote:
>
> Hi!
>
> This is an automated message. This series looks like a fix, but its
> commit messages seem to be missing some information:
>
> - How the issue was discovered, e.g. hit in production, hit during
> development, syzbot report, manual code inspection, LLM or static
> analysis tool scan.
>
> Please do not repost the series just to address the above. Instead,
> reply to this email with the missing information, so that reviewers
> can take it into account. If the series needs another revision for
> other reasons, please include the information in the commit messages
> then.
>
> The evaluation is done by an LLM so it may be wrong, if you think
> that is the case please reply and explain.
The issue fixed in patch 1 was found by manual code inspection: reading
the kTLS ->read_sock() path, I noticed that tls_sw_read_sock() can sleep
while KCM's psock_data_ready() reaches it from softirq through
strp_data_ready(). I then confirmed it with the CONFIG_DEBUG_ATOMIC_SLEEP
loopback reproducer described in the commit message, which hits the
splat on every run without the patch.
Patch 2 comes from review feedback on v1, which pointed out that kstrp
is an ordered workqueue shared by every strparser user.
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH net v2 0/2] kcm: don't sleep in softirq when the lower socket uses kTLS
2026-10-16 2:44 [PATCH net v2 0/2] kcm: don't sleep in softirq when the lower socket uses kTLS Rishikesh Jethwani
` (2 preceding siblings ...)
2026-10-16 2:54 ` [PATCH net v2 0/2] kcm: don't sleep in softirq when the lower socket uses kTLS netdev-bot+sinfo
@ 2026-10-16 10:13 ` Jiayuan Chen
3 siblings, 0 replies; 6+ messages in thread
From: Jiayuan Chen @ 2026-10-16 10:13 UTC (permalink / raw)
To: Rishikesh Jethwani, netdev
Cc: David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman
On 10/16/26 10:44 AM, Rishikesh Jethwani wrote:
> When a TCP socket with software kTLS RX is attached to a KCM mux,
Can we just reject such combo ?
> psock_data_ready() calls strp_data_ready() from softirq, which calls the
> socket's read_sock(). For kTLS that is tls_sw_read_sock(), which can
> sleep, and CONFIG_DEBUG_ATOMIC_SLEEP reports it on every run of a
> loopback reproducer.
>
> Patch 1 is the fix: KCM parses inline only when read_sock is
> tcp_read_sock() and otherwise defers to the strparser work, which runs
> under lock_sock(). It applies and builds on its own, including on
> stable kernels.
>
> Patch 2 addresses review feedback on v1 and is needed by patch 1.
> kstrp, the workqueue that deferred work runs on, is an ordered
> workqueue shared by every strparser user (KCM, sockmap, espintcp,
> ovpn). With patch 1 alone, a KCM psock decrypting kTLS records in
> software on kstrp would delay parsing and message timeouts for every
> other strparser socket on the system. Patch 2 makes kstrp per-CPU. It
> has no Fixes tag: the ordered workqueue is as old as strparser, and it
> only becomes a real problem for KCM over kTLS with patch 1.
>
> Other strparser users are not affected by the bug fixed in patch 1:
> espintcp is itself a TCP ULP and cannot be combined with kTLS, ovpn
> installs its own ops built from inet_stream_ops, and sockmap reads
> through tcp_bpf_strp_read_sock() and is mutually exclusive with kTLS
> RX (do_tls_setsockopt_conf() rejects sockets with a psock).
>
> Testing: with patch 1, 5/5 runs of the reproducer produce no splat and
> full datagram delivery; without it every run hits "BUG: sleeping
> function called from invalid context" in strp_data_ready ->
> tls_sw_read_sock. Multi-record messages (>16 KiB each) also deliver
> completely with kTLS RX installed before the KCM attach and the whole
> stream queued before the reader starts. With patch 2, test_sockmap and the ovpn TCP selftests
> pass, strparser work runs concurrently across sockets, and dmesg shows
> no warnings.
>
> v2:
> - add patch 2 (kstrp per-CPU), per review
> - read sock->ops with READ_ONCE(), pairing with update_sk_prot()
>
> v1: https://lore.kernel.org/netdev/20261013033920.2069285-1-rjethwani@purestorage.com/
>
> Rishikesh Jethwani (2):
> kcm: defer receive parsing when the lower socket's read_sock may sleep
> strparser: don't serialize all parser work on one ordered workqueue
>
> net/kcm/kcmsock.c | 33 +++++++++++++++++++++++++++++++--
> net/strparser/strparser.c | 2 +-
> 2 files changed, 32 insertions(+), 3 deletions(-)
>
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-10-16 10:13 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-16 2:44 [PATCH net v2 0/2] kcm: don't sleep in softirq when the lower socket uses kTLS Rishikesh Jethwani
2026-10-16 2:44 ` [PATCH net v2 1/2] kcm: defer receive parsing when the lower socket's read_sock may sleep Rishikesh Jethwani
2026-10-16 2:44 ` [PATCH net v2 2/2] strparser: don't serialize all parser work on one ordered workqueue Rishikesh Jethwani
2026-10-16 2:54 ` [PATCH net v2 0/2] kcm: don't sleep in softirq when the lower socket uses kTLS netdev-bot+sinfo
2026-10-16 4:29 ` Rishikesh Jethwani
2026-10-16 10:13 ` Jiayuan Chen
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.