* [PATCH net] net/iucv: filter frames in afiucv_hs_rcv() by ingress device
@ 2026-08-21 12:55 Alexandra Winter
2026-08-22 12:55 ` sashiko-bot
` (2 more replies)
0 siblings, 3 replies; 4+ messages in thread
From: Alexandra Winter @ 2026-08-21 12:55 UTC (permalink / raw)
To: Bryam Vargas, David Miller, Jakub Kicinski, Paolo Abeni,
Eric Dumazet, Andrew Lunn
Cc: Hidayath Khan, Aswin Karuvally, Thorsten Winkler,
Hendrik Brueckner, netdev, linux-s390, linux-kernel,
Heiko Carstens, Vasily Gorbik, Alexander Gordeev,
Christian Borntraeger, Sven Schnelle, Simon Horman, stable
afiucv_hs_rcv() selects a socket from iucv_sk_list by matching four 8-byte
name fields in the transport header alone. No check is made against the
net_device the frame arrived on.
This can cause a frame arriving on any netdev to be delivered to an AF_IUCV
socket. Three problems follow.
First, a frame arriving over HiperSockets can be delivered to a socket
bound to the classic z/VM IUCV transport, which has iucv->hs_dev == NULL.
iucv_sock_bind() takes the classic path whenever the requested userid
matches iucv_userid, even on a guest that also has a HiperSockets device
carrying the same identifier. The child socket created by
afiucv_hs_callback_syn() for such a match inherits hs_dev = NULL and
transport = AF_IUCV_TRANS_HIPER, so the first send() on it returns -ENODEV.
The socket delivered to accept() is unusable.
Second, a frame arriving on one netdev can be delivered to a socket bound
to a different IQD device. Which can lead to
- Accept-queue exhaustion (DoS)
- Attacker-controlled peer identity in the child socket
- Data injection into existing sockets
- Fabric noise on the IQD fabric, where bogus replies are sent
- killing established connections
Third, all AF_IUCV sockets live in init_net, as iucv_sock_alloc() calls
sk_alloc(&init_net, ...). But even frames arriving on netdev devices in a
namespace can be delivered to an IUCV socket. So a process in an
unprivileged user and network namespace holding only the CAP_NET_RAW
capability valid within that namespace can send a raw ETH_P_AF_IUCV frame
on its own lo device and have it matched against init_net sockets.
Fix all three by skipping any socket whose hs_dev does not match the
ingress device. A classic z/VM IUCV socket has hs_dev == NULL; the ingress
dev is never NULL, so classic sockets are skipped automatically. An unbound
HIPER socket also has hs_dev == NULL and is skipped. A bound HIPER socket
is only reachable from the exact IQD device it was bound to. Because hs_dev
is always a device in init_net (iucv_sock_bind() scans
for_each_netdev_rcu(&init_net, ...) exclusively), a frame whose ingress
device belongs to another namespace never matches any socket.
Note that AF_IUCV over HiperSockets provides no per-connection
authentication: no sequence numbers, no TLS, no nonce. The four name fields
identifying a connection are exchanged in plaintext on the shared
HiperSockets segment (VCHID). Any host on the same HiperSockets segment
could spoof any frame type against an existing connection. That is a
protocol-level property unchanged by this patch. The fix reduces the attack
surface to peers present on the same HiperSockets segment.
Fixes: 3881ac441f64 ("af_iucv: add HiperSockets transport")
Cc: stable@vger.kernel.org
Co-developed-by: Bryam Vargas <hexlabsecurity@proton.me>
Signed-off-by: Alexandra Winter <wintera@linux.ibm.com>
---
I think this fix covers the issues adressed by [1] and [2], and
further reduces the attack surface.
Bryam, would you accept a Co-developed-by, as you did the analysis
and you proposed to add checks in afiucv_hs_rcv()?
[1] [PATCH net] net/iucv: only deliver HiperSockets frames to HiperSockets sockets
Link: https://lore.kernel.org/netdev/20260813-b4-disp-60433a46-v1-1-509e1200533e@proton.me/ [1]
[2] [PATCH net 1/2] net/iucv: drop HiperSockets frames from other network namespaces
Link: https://lore.kernel.org/netdev/20260815-b4-disp-dc82fde4-v1-1-e83b10b22ce9@proton.me/ [2]
---
net/iucv/af_iucv.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c
index ea047bab65e7..4e5cc9da6e06 100644
--- a/net/iucv/af_iucv.c
+++ b/net/iucv/af_iucv.c
@@ -2079,6 +2079,8 @@ static int afiucv_hs_rcv(struct sk_buff *skb, struct net_device *dev,
sk = NULL;
read_lock(&iucv_sk_list.lock);
sk_for_each(sk, &iucv_sk_list.head) {
+ if (iucv_sk(sk)->hs_dev != dev)
+ continue;
if (trans_hdr->flags == AF_IUCV_FLAG_SYN) {
if ((!memcmp(&iucv_sk(sk)->src_name,
trans_hdr->destAppName, 8)) &&
--
2.53.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH net] net/iucv: filter frames in afiucv_hs_rcv() by ingress device
2026-08-21 12:55 [PATCH net] net/iucv: filter frames in afiucv_hs_rcv() by ingress device Alexandra Winter
@ 2026-08-22 12:55 ` sashiko-bot
2026-08-24 19:10 ` patchwork-bot+netdevbpf
2026-08-28 17:58 ` Bryam Vargas
2 siblings, 0 replies; 4+ messages in thread
From: sashiko-bot @ 2026-08-22 12:55 UTC (permalink / raw)
To: Alexandra Winter
Cc: Christian Borntraeger, linux-s390, Heiko Carstens, Vasily Gorbik,
Alexander Gordeev
Thank you for your contribution! Sashiko AI review found 6 potential issue(s) to consider:
Pre-existing issues:
- [High] In-place modification of a potentially shared or cloned SKB without unsharing corrupts memory for concurrent readers.
- [High] Blind reuse of RX SKB for TX without verifying headroom causes skb_under_panic (DoS) and malformed frames.
- [High] Unprotected list traversal in afiucv_netdev_event() risks list corruption and use-after-free.
- [High] Socket and netdev reference leak during incoming connection errors causes unbounded memory consumption and device unregister hangs.
- [High] AF_IUCV RX handlers modify socket state from SoftIRQ context without checking if the socket is currently owned by the user.
- [High] Unprivileged processes in restricted network namespaces can create AF_IUCV sockets bound to host interfaces, bypassing network isolation.
--
--- Patch [1]: [PATCH net] net/iucv: filter frames in afiucv_hs_rcv() by ingress device ---
commit c0a4d18765a00aae7fc517041e61031313bfee8c
Author: Alexandra Winter <wintera@linux.ibm.com>
net/iucv: filter frames in afiucv_hs_rcv() by ingress device
This commit fixes several issues in afiucv_hs_rcv() where frames arriving
on any net_device could be delivered to an AF_IUCV socket purely based on
transport header fields. It resolves problems with delivering HiperSockets
frames to classic z/VM IUCV sockets, cross-device injection, and network
namespace isolation bypass by strictly checking the ingress device against
the socket's bound device.
Link: https://lore.kernel.org/netdev/20260813-b4-disp-60433a46-v1-1-509e1200533e@proton.me/ [1]
Link: https://lore.kernel.org/netdev/20260815-b4-disp-dc82fde4-v1-1-e83b10b22ce9@proton.me/ [2]
> Third, all AF_IUCV sockets live in init_net, as iucv_sock_alloc() calls
> sk_alloc(&init_net, ...). But even frames arriving on netdev devices in a
> namespace can be delivered to an IUCV socket. So a process in an
> unprivileged user and network namespace holding only the CAP_NET_RAW
> capability valid within that namespace can send a raw ETH_P_AF_IUCV frame
> on its own lo device and have it matched against init_net sockets.
[Severity: High]
This is a pre-existing issue, but does creating the socket directly in
init_net without validating the caller's namespace allow unprivileged
processes to escape isolation?
In iucv_sock_create(), the socket is allocated unconditionally in init_net:
sk = iucv_sock_alloc(sock, protocol, GFP_KERNEL, kern);
Then in iucv_sock_bind(), it scans and allows binding to devices in
init_net regardless of the caller's actual namespace:
for_each_netdev_rcu(&init_net, dev) {
Could this allow an unprivileged container to create an AF_IUCV socket
and bind it to a physical host device?
> diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c
> index ea047bab65e7c..4e5cc9da6e068 100644
> --- a/net/iucv/af_iucv.c
> +++ b/net/iucv/af_iucv.c
> @@ -2079,6 +2079,8 @@ static int afiucv_hs_rcv(struct sk_buff *skb, struct net_device *dev,
> sk = NULL;
> read_lock(&iucv_sk_list.lock);
> sk_for_each(sk, &iucv_sk_list.head) {
> + if (iucv_sk(sk)->hs_dev != dev)
> + continue;
> if (trans_hdr->flags == AF_IUCV_FLAG_SYN) {
> if ((!memcmp(&iucv_sk(sk)->src_name,
> trans_hdr->destAppName, 8)) &&
[Severity: High]
This is a pre-existing issue, but does afiucv_hs_rcv() modify a potentially
shared or cloned SKB in-place without unsharing it?
Earlier in afiucv_hs_rcv(), the payload is modified directly:
net/iucv/af_iucv.c:afiucv_hs_rcv() {
...
trans_hdr = iucv_trans_hdr(skb);
EBCASC(trans_hdr->destAppName, sizeof(trans_hdr->destAppName));
...
}
Since this SKB is received from packet_type delivery, could modifying it
without calling skb_unshare() or skb_cow() corrupt data for concurrent
readers like packet sniffers?
Furthermore, afiucv_swap_src_dest() also prepends data using skb_push()
and memset() on this same SKB.
[Severity: High]
This is another pre-existing issue, but is there a risk of an
skb_under_panic when rejecting a connection?
When an incoming SYN frame is rejected, the unmodified RX SKB is passed
to afiucv_swap_src_dest() via afiucv_hs_callback_syn():
net/iucv/af_iucv.c:afiucv_swap_src_dest() {
...
skb_push(skb, ETH_HLEN);
...
}
If the incoming frame was crafted with zero or limited headroom, could
this skb_push() without checking skb_headroom() cause a kernel panic?
The SKB is then handed directly to dev_queue_xmit() without further
scrubbing.
[Severity: High]
This isn't a bug introduced by this patch, but does afiucv_netdev_event()
traverse the socket list safely?
When a netdev event occurs, the list is traversed without a lock:
net/iucv/af_iucv.c:afiucv_netdev_event() {
...
sk_for_each(sk, &iucv_sk_list.head) {
...
}
Since other threads can concurrently modify this list during socket
creation or destruction, could this unprotected traversal lead to a
use-after-free or list corruption?
[Severity: High]
This is a pre-existing issue, but does rejecting an incoming connection
result in a socket and netdev reference leak?
If afiucv_hs_callback_syn() rejects a connection, it attempts to clean up:
net/iucv/af_iucv.c:afiucv_hs_callback_syn() {
...
if (nsk)
iucv_sock_kill(nsk);
...
}
However, the new socket was initialized with the SOCK_ZAPPED flag cleared,
which causes iucv_sock_kill() to exit early:
net/iucv/af_iucv.c:iucv_sock_kill() {
...
if (!sock_flag(sk, SOCK_ZAPPED) || sk->sk_socket)
return;
...
}
Could this early return skip unlinking the socket and dropping references,
leading to unbounded memory consumption and preventing device
unregistration?
[Severity: High]
This is a pre-existing issue, but do the AF_IUCV RX handlers safely
mutate socket state from SoftIRQ context?
Callbacks like afiucv_hs_callback_synack() acquire the bottom-half lock
and change the state directly:
net/iucv/af_iucv.c:afiucv_hs_callback_synack() {
...
bh_lock_sock(sk);
...
sk->sk_state = IUCV_CONNECTED;
sk->sk_state_change(sk);
bh_unlock_sock(sk);
...
}
If a user process is concurrently calling close() and holding lock_sock(),
could mutating the state here without checking sock_owned_by_user()
corrupt the state machine?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260821125501.3718748-1-wintera@linux.ibm.com?part=1
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH net] net/iucv: filter frames in afiucv_hs_rcv() by ingress device
2026-08-21 12:55 [PATCH net] net/iucv: filter frames in afiucv_hs_rcv() by ingress device Alexandra Winter
2026-08-22 12:55 ` sashiko-bot
@ 2026-08-24 19:10 ` patchwork-bot+netdevbpf
2026-08-28 17:58 ` Bryam Vargas
2 siblings, 0 replies; 4+ messages in thread
From: patchwork-bot+netdevbpf @ 2026-08-24 19:10 UTC (permalink / raw)
To: Alexandra Winter
Cc: hexlabsecurity, davem, kuba, pabeni, edumazet, andrew+netdev,
hidayath, aswin, twinkler, brueckner, netdev, linux-s390,
linux-kernel, hca, gor, agordeev, borntraeger, svens, horms,
stable
Hello:
This patch was applied to netdev/net.git (main)
by Jakub Kicinski <kuba@kernel.org>:
On Fri, 21 Aug 2026 14:55:01 +0200 you wrote:
> afiucv_hs_rcv() selects a socket from iucv_sk_list by matching four 8-byte
> name fields in the transport header alone. No check is made against the
> net_device the frame arrived on.
>
> This can cause a frame arriving on any netdev to be delivered to an AF_IUCV
> socket. Three problems follow.
>
> [...]
Here is the summary with links:
- [net] net/iucv: filter frames in afiucv_hs_rcv() by ingress device
https://git.kernel.org/netdev/net/c/80230a18c164
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
* Re: [PATCH net] net/iucv: filter frames in afiucv_hs_rcv() by ingress device
2026-08-21 12:55 [PATCH net] net/iucv: filter frames in afiucv_hs_rcv() by ingress device Alexandra Winter
2026-08-22 12:55 ` sashiko-bot
2026-08-24 19:10 ` patchwork-bot+netdevbpf
@ 2026-08-28 17:58 ` Bryam Vargas
2 siblings, 0 replies; 4+ messages in thread
From: Bryam Vargas @ 2026-08-28 17:58 UTC (permalink / raw)
To: Alexandra Winter, David Miller, Jakub Kicinski, Paolo Abeni,
Eric Dumazet, Andrew Lunn
Cc: Hidayath Khan, Aswin Karuvally, Thorsten Winkler,
Hendrik Brueckner, Heiko Carstens, Vasily Gorbik,
Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
Simon Horman, netdev, linux-s390, linux-kernel
Alexandra,
> Bryam, would you accept a Co-developed-by, as you did the analysis
> and you proposed to add checks in afiucv_hs_rcv()?
Yes.
Signed-off-by: Bryam Vargas <hexlabsecurity@proton.me>
Late for the commit itself: 80230a18c164 went up in the 27 Aug pull request and
is in mainline carrying the Co-developed-by without a matching sign-off, and
submitting-patches.rst pairs the two. Nothing to do about it there. Putting the
sign-off on the list is the record that the consent existed.
I'm dropping 1/2, as I said I would, and I'm not respinning the
transport-filter patch either: yours closes it, and it answers what Jakub
asked for on that thread -- the device test in the same loop. He was right
there. The changelog argued a reach the two-line check did not close.
2/2 is unaffected.
On timing: I'm in the middle of a larger project and have only a few hours a
week for this at the moment. I'd rather say so than go quiet on the thread.
Thanks,
Bryam
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-08-28 17:58 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-21 12:55 [PATCH net] net/iucv: filter frames in afiucv_hs_rcv() by ingress device Alexandra Winter
2026-08-22 12:55 ` sashiko-bot
2026-08-24 19:10 ` patchwork-bot+netdevbpf
2026-08-28 17:58 ` Bryam Vargas
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox