[PATCH net v2] octeontx2-pf: fix skb use-after-free with ipsec crypto offload
DORMANTno replies
From: Nicolai Buchwitz <nb@tipi-net.de>
Date: 2026-10-22 09:12:50
Also in:
lkml
Subsystem:
marvell octeontx2 physical function driver, networking drivers, the rest · Maintainers:
Sunil Goutham, Geetha sowjanya, Ratheesh Kannoth, Subbaraya Sundeep, Bharat Bhushan, Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds
otx2_dma_map_skb_frag() calls skb_unshare() on its own copy of the skb
pointer. For a cloned skb, for example with tcpdump running on the
interface, this frees the skb and the new copy is lost on return. The
transmit path then uses the freed skb and the copy leaks.
Make the skb writable in place in otx2_sq_append_skb() instead, so the
pointer stays valid. Also do this for skbs with shared frags, as the
hardware writes the encrypted data back into them.
Fixes: 195c3d463181 ("octeontx2-pf: map skb data as device writeable")
Signed-off-by: Nicolai Buchwitz <nb@tipi-net.de>
---
This was flagged in the clashiko review of my skb_unshare() rename patch [1].
Compile-tested only, I have no octeontx2 hardware.
[1] https://lore.kernel.org/all/20261015-nb-skb-unclone-full-v1-1-0dfbf01f60f2@tipi-net.de/ (local)
---
Changes in v2:
- Also handle skbs with shared frags (Jakub)
- Note: conflicts with "net: rename skb_unshare() to skb_unclone_full()"
in net-next, the resolution is to drop the skb_unclone_full() line
- Link to v1: https://patch.msgid.link/20261019-nb-otx2-xfrm-unshare-net-v1-1-ee9b24f9e673@tipi-net.de (local)
To: Sunil Goutham <sgoutham@marvell.com>
To: Geetha sowjanya <gakula@marvell.com>
To: Ratheesh Kannoth <rkannoth@marvell.com>
To: Subbaraya Sundeep <sbhatta@marvell.com>
To: Bharat Bhushan <bbhushan2@marvell.com>
To: Andrew Lunn <andrew+netdev@lunn.ch>
To: "David S. Miller" <davem@davemloft.net>
To: Eric Dumazet <edumazet@kernel.org>
To: Jakub Kicinski <kuba@kernel.org>
To: Paolo Abeni <pabeni@redhat.com>
Cc: netdev@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
---
drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c | 4 +---
drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c | 8 ++++++++
2 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c
index b11389a841d15..91ebf247f5f90 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c@@ -2121,10 +2121,8 @@ dma_addr_t otx2_dma_map_skb_frag(struct otx2_nic *pfvf, int offset; /* Crypto hardware need write permission for ipsec crypto offload */ - if (unlikely(xfrm_offload(skb))) { + if (unlikely(xfrm_offload(skb))) dir = DMA_BIDIRECTIONAL; - skb = skb_unshare(skb, GFP_ATOMIC); - } /* First segment is always skb->data */ if (!seg) {
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c
index 8d2d607bc92f9..b98842c7e40e0 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c@@ -1205,6 +1205,14 @@ bool otx2_sq_append_skb(void *dev, struct netdev_queue *txq, if (free_desc < otx2_get_sqe_count(pfvf, skb)) return false; + /* Crypto hardware need write permission for ipsec crypto offload */ + if (unlikely(xfrm_offload(skb)) && + (skb_cloned(skb) || skb_has_shared_frag(skb)) && + skb_ensure_writable(skb, skb->len)) { + dev_kfree_skb_any(skb); + return true; + } + num_segs = skb_shinfo(skb)->nr_frags + 1; /* If SKB doesn't fit in a single SQE, linearize it.
--- base-commit: 82e31923c0553fdbfcddcd910ca07952880ca9b9 change-id: 20261019-nb-otx2-xfrm-unshare-net-6b74a96a8d9e Best regards, -- Nicolai Buchwitz [off-list ref]