summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorNicolai Buchwitz <nb@tipi-net.de>2026-10-27 19:44:09 +0100
committerPaolo Abeni <pabeni@redhat.com>2026-10-29 11:51:04 +0100
commit829a09df899dcce860dcf5f70e09c1b2d7d425ab (patch)
tree8537c609b873e44a940513b94fd95b93541b4f43 /drivers
parentfb3e026ae548e3dd42ed3ef6420d33258dd91286 (diff)
octeontx2-pf: fix skb use-after-free with ipsec crypto offload
otx2_dma_map_skb_frag() calls skb_unclone_full() 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 nonlinear skbs, as the hardware writes the encrypted data back into the frags, which may be shared, for example with the TCP retransmit queue. Fixes: 195c3d463181 ("octeontx2-pf: map skb data as device writeable") Signed-off-by: Nicolai Buchwitz <nb@tipi-net.de> Link: https://patch.msgid.link/20261027-nb-otx2-xfrm-unshare-net-v3-1-31dc9d79d11d@tipi-net.de Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c4
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c9
2 files changed, 10 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 16f73797739d..c85436457286 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c
@@ -2115,10 +2115,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_unclone_full(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 66dc8cc15486..90af9b9044aa 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c
@@ -1205,6 +1205,15 @@ 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_is_nonlinear(skb)) &&
+ skb_ensure_writable(skb, skb->len)) {
+ atomic_long_inc(&pfvf->hw.dev_stats.tx_discards);
+ 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.