[PATCH net 2/2] net/iucv: take a private, writable frame before rewriting it in place

From: Bryam Vargas via B4 Relay

Date: Sat Aug 15 2026 - 12:07:38 EST


From: Bryam Vargas <hexlabsecurity@xxxxxxxxx>

afiucv_hs_rcv() rewrites the frame in place -- EBCASC() converts four name
fields in the transport header, afiucv_swap_src_dest() swaps them and
pushes an Ethernet header back on -- without taking a private, writable
copy. It sits on the global ptype_base[], so a packet socket (tcpdump is
enough) has packet_rcv() clone every frame first, and net/core/dev.c has
warned since 1998 that such a handler "is not able to sense, that packet
is cloned and should be copied-on-write".

Unshare, then cow the head, in that order: skb_cow_head() can reach
pskb_expand_head(), which has BUG_ON(skb_shared()). Asking for ETH_HLEN
also covers the unchecked push in afiucv_swap_src_dest() --
eth_type_trans() has already pulled that much on the ordinary path, so the
call compares and returns.

Fixes: 3881ac441f64 ("af_iucv: add HiperSockets transport")
Closes: https://sashiko.dev/#/patchset/20260813-b4-disp-60433a46-v1-1-509e1200533e@xxxxxxxxx?part=1
Signed-off-by: Bryam Vargas <hexlabsecurity@xxxxxxxxx>
---
net/iucv/af_iucv.c | 9 +++++++++
1 file changed, 9 insertions(+)

diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c
index e3ec965d96ca..10cfc5e82f04 100644
--- a/net/iucv/af_iucv.c
+++ b/net/iucv/af_iucv.c
@@ -2069,11 +2069,20 @@ static int afiucv_hs_rcv(struct sk_buff *skb, struct net_device *dev,
return NET_RX_SUCCESS;
}

+ skb = skb_share_check(skb, GFP_ATOMIC);
+ if (!skb)
+ return NET_RX_SUCCESS;
+
if (!pskb_may_pull(skb, sizeof(*trans_hdr))) {
kfree_skb(skb);
return NET_RX_SUCCESS;
}

+ if (skb_cow_head(skb, ETH_HLEN)) {
+ kfree_skb(skb);
+ return NET_RX_SUCCESS;
+ }
+
trans_hdr = iucv_trans_hdr(skb);
EBCASC(trans_hdr->destAppName, sizeof(trans_hdr->destAppName));
EBCASC(trans_hdr->destUserID, sizeof(trans_hdr->destUserID));

--
2.55.0