From: Hidayath Khan <hidayath@linux.ibm.com>
To: hexlabsecurity@proton.me, Paolo Abeni <pabeni@redhat.com>,
Jakub Kicinski <kuba@kernel.org>,
Thorsten Winkler <twinkler@linux.ibm.com>,
Eric Dumazet <edumazet@kernel.org>,
Alexandra Winter <wintera@linux.ibm.com>,
"David S. Miller" <davem@davemloft.net>
Cc: Nagamani PV <nagamani@linux.ibm.com>,
netdev@vger.kernel.org, Simon Horman <horms@kernel.org>,
linux-s390@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH net-next] net/iucv: serialize HiperSockets receive with the socket lock
Date: Sun, 18 Oct 2026 00:08:20 +0530 [thread overview]
Message-ID: <b3fea2ca-25ff-42c0-812c-f8cc6bb6667e@linux.ibm.com> (raw)
In-Reply-To: <82691101-92d7-4838-b16e-2e41a83f65d0@linux.ibm.com>
On 14/10/26 4:42 am, Hidayath Khan wrote:
> Hi Bryam,
>
> Below are the test results for this stage 1 patch on z/VM.
>
> Setup: one z/VM guest, two HiperSockets hsuids, two CPUs, af_iucv as a
> module, and an AF_IUCV socket-locking reproducer. Both kernels have
> the same
> config - CONFIG_KASAN=y, CONFIG_PROVE_LOCKING=y and
> CONFIG_DEBUG_ATOMIC_SLEEP=y - so the only variable is the patch.
>
> scenario net-next, patch
> sk_shutdown fail, 271-299 misses pass, 0 in 9058 cycles
> shut_rd fail, fail, pass pass, 0 in 29 cycles
> recvrecv fail, 3658-4139 back. pass, 0 out-of-order in 4194304
> words
> backlog pass pass
> rxclose fail, 16-17 of 35-38 fail, 14 of 57
> spin fail, 2020-2190 ms CPU fail, 2070 ms CPU
>
> No KASAN, lockdep or DEBUG_ATOMIC_SLEEP report on either kernel, in
> dmesg or
> the journal - so nothing reports here either way, and the patch
> introduces
> nothing. Since this patch adds local_bh_disable() around the backlog
> replay,
> moves __iucv_sock_close() into recvmsg() under lock_sock() and holds
> the socket
> lock across copy_to_user(), that was the result I was most interested in.
>
> backlog passed on both - it is a guard rather than a reproducer, and 0
> frames lost over roughly 1.1 million ownership windows on net-next
> confirms
> it has no discriminating power here, so it says nothing either way.
>
> shut_rd is too flaky to lean on: on net-next it failed with 2 misses
> in 43
> cycles and 3 in 35, then passed with 0 in 45. So its single pass with the
> patch is not evidence. Its window is now narrow enough that 30 s under
> KASAN
> is not enough cycles; I will re-run it much longer.
>
> sk_shutdown and recvrecv are the solid ones. recvrecv is what I would
> point
> at: two readers interleaving inside an unlocked iucv_sock_recvmsg() went
> backwards 3658, 3896 and 4139 times across the three net-next runs and
> not
> once with your patch.
>
> rxclose fails on both, on the -ENOTCONN that Sashiko flags as Low: 17
> of 37,
> 17 of 38 and 16 of 35 on net-next against 14 of 57 with your patch. Lower
> with the patch, but that is one patched run against three, so I would not
> read much into the difference. 0 lost tails in every run - though the
> lost-tail check only runs on cycles that reached EOF, so the failing
> cycles
> are not data-checked. The test counts any errno other than EINTR and
> EAGAIN
> as a wrong termination, which is why -ENOTCONN shows as a failure.
>
> The asymmetry is that recvmsg()'s shortcut gives EOF on IUCV_DISCONN with
> the queues empty, while iucv_sock_recv_skb() gives -ENOTCONN on
> sk_state != IUCV_CONNECTED. Either the loop returns EOF for IUCV_DISCONN
> with nothing queued, or afiucv_hs_callback_fin() sets RCV_SHUTDOWN as
> well -
> that one is a single line but also changes what callback_rx() drops
> and what
> iucv_sock_poll() reports. I have tried neither. Which behaviour do you
> want?
>
> spin fails on both, and by the same margin: 2020, 2150 and 2190 ms of CPU
> while blocked about 3000 ms on net-next, 2070 ms with your patch.
> __iucv_sock_wait() still calls prepare_to_wait() once, outside its
> loop, so
> after the first schedule_timeout() the task is TASK_RUNNING. Outside your
> diff, and a different bug from the missed wakeup you fix at the same call
> site. One-liner; I will send it separately.
>
> On KASAN specifically, so an empty result is not read as a gap: there
> will
> be no KASAN report from these scenarios even on a KASAN kernel. The
> reproducer does scan /dev/kmsg for KASAN and KCSAN reports and fails a
> scenario on any hit, but stage 1's defects are missing locks - they
> surface
> as lost data, a lost sk_shutdown bit, a wrong errno or a leaked
> socket, none
> of which touch freed or out-of-bounds memory. KASAN is a clean-run
> control
> here. KCSAN is what can witness the accesses still left unlocked; note
> that
> it generally does not flag volatile accesses, so it may not show sk_state
> races either. A KCSAN run is next.
>
> Sashiko's three budget findings look to me like instances of one
> thing, and
> it says so itself on the SO_MSGLIMIT case: stream data is "lost
> without any
> error". A frame that does not fit is dropped with nothing but
> sk_drops_inc() and kfree_skb_reason(). Resizing a budget per instance
> leaves
> the next one open.
>
> Sashiko's three budget findings look like one thing: a frame that does
> not fit
> is dropped with only sk_drops_inc() and kfree_skb_reason(), so resizing a
> budget per instance leaves the next one open. Would you take a patch
> on top
> that makes the loss visible instead - the softirq sets a bit in
> iucv_sock, and
> iucv_sock_release_cb() turns it into sk_err = ECONNRESET plus
> IUCV_DISCONN once
> the owner lets go? Separately: would it be simpler not to defer
> a pure WIN at all? afiucv_hs_callback_win() is only an atomic_sub() and
> iucv_sock_wake_msglim().
>
> Thanks,
> Hidayath
>
Hi Bryam,
Follow-up to the earlier KASAN + PROVE_LOCKING + DEBUG_ATOMIC_SLEEP results.
I ran the same reproducer on the same z/VM guest with a KCSAN build of your
patch, interrupt watcher on. KCSAN found two af_iucv data races. Both
appeared during the sk_shutdown scenario. The second also appeared once in
rxclose scenario. I have the full KCSAN reports from /dev/kmsg now, so
the fields below are from them rather than from reading the code.
1) sk->sk_shutdown, 1 byte, same address on both sides.
A marked read in afiucv_hs_callback_rx(), inlined into afiucv_hs_dispatch():
if (READ_ONCE(sk->sk_shutdown) & RCV_SHUTDOWN)
by interrupt on one CPU, against the plain read-modify-write in
iucv_sock_shutdown():
sk->sk_shutdown |= how;
by task on the other CPU. The report gives the contexts as interrupt and
task;
that the writer holds lock_sock() is from the source - iucv_sock_shutdown()
takes it on entry and that line is on every path to it.
The receive side must have come through the !afiucv_hs_defer() bypass rather
than the !sock_owned_by_user() arm. The writer holds lock_sock(), so
sk_lock.owned is set and slock is free; the reader runs inside
bh_lock_sock(),
which is slock. For the two to overlap, the task must have finished
lock_sock() before the softirq took slock - so sock_owned_by_user() was
true
when the softirq checked it. On the other arm the softirq holds slock while
nobody owns the socket, and a task entering lock_sock() blocks on slock
until
the callback returns, so it cannot reach the write.
That is the window I asked you about in the previous comment, where a frame
can also be queued after shutdown(SHUT_RD)'s skb_queue_purge(), and which I
could not get to fire functionally. It has a KCSAN report behind it now.
Making the write a WRITE_ONCE() would silence KCSAN and fix nothing. The
frame-after-purge behaviour looks like an ordering problem.
2) iucv->hs_dev, 8 bytes, same address on both sides.
A plain read in afiucv_hs_rcv()'s socket-lookup loop:
if (iucv_sk(sk)->hs_dev != dev)
by interrupt, with only read_lock(&iucv_sk_list.lock) held, against the
plain
write in __iucv_sock_close():
iucv->hs_dev = NULL;
by task, from an ordinary close() - the stack is iucv_sock_release ->
sock_close -> __fput -> sys_close, so the socket lock is held there.
The read is the ingress check added by Alexandra's 80230a18c164 and the
write was already there, so neither line is from your patches.
I do not think it needs locking: the lookup is inherently racy with close,
since the socket can be closed between the match and the dispatch however
well hs_dev is synchronised. I think both outcomes are harmless - observing
NULL early drops a frame that was about to be dropped anyway, and
observing a
stale pointer gets the frame as far as the callbacks, which drop it on
sk_state. So I think the right treatment is READ_ONCE()/WRITE_ONCE() on the
two accesses with a comment saying the lookup read is deliberately
unsynchronised, rather than anything structural. Tell me if you see it
differently.
One more thing in the same function. __iucv_sock_close() does
dev_put(iucv->hs_dev);
iucv->hs_dev = NULL;
so between those two statements hs_dev names a device this socket no longer
holds a reference to, and the lookup loop can match on it. Clearing before
the put removes that window - via a local, since swapping the lines as they
stand would dev_put(NULL) and leak the reference:
struct net_device *dev = iucv->hs_dev;
if (dev) {
iucv->hs_dev = NULL;
sk->sk_bound_dev_if = 0;
dev_put(dev);
}
The test run also has 500+ KCSAN reports with skb_copy_bits /
__might_fault.
All of them have
afiucv_hs_rcv() -> pskb_may_pull() -> __pskb_pull_tail() in the stack.
The conflict is on current->pagefault_disabled not skb data, so I don't
think
either of your patches is involved.
Functionally the KCSAN kernel showed nothing new - the same rxclose and spin
failures as previous comment, everything else is clean.
Thanks,
Hidayath
prev parent reply other threads:[~2026-10-17 18:38 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-11 19:08 [PATCH net-next] net/iucv: serialize HiperSockets receive with the socket lock Bryam Vargas via B4 Relay
2026-10-12 19:45 ` netdev-bot+sashiko
2026-10-13 23:12 ` Hidayath Khan
2026-10-17 18:38 ` Hidayath Khan [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=b3fea2ca-25ff-42c0-812c-f8cc6bb6667e@linux.ibm.com \
--to=hidayath@linux.ibm.com \
--cc=davem@davemloft.net \
--cc=edumazet@kernel.org \
--cc=hexlabsecurity@proton.me \
--cc=horms@kernel.org \
--cc=kuba@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-s390@vger.kernel.org \
--cc=nagamani@linux.ibm.com \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=twinkler@linux.ibm.com \
--cc=wintera@linux.ibm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox