diff options
| author | Nicolai Buchwitz <nb@tipi-net.de> | 2026-10-27 19:44:09 +0100 |
|---|---|---|
| committer | Paolo Abeni <pabeni@redhat.com> | 2026-10-29 11:51:04 +0100 |
| commit | 829a09df899dcce860dcf5f70e09c1b2d7d425ab (patch) | |
| tree | 8537c609b873e44a940513b94fd95b93541b4f43 | |
| parent | fb3e026ae548e3dd42ed3ef6420d33258dd91286 (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>
| -rw-r--r-- | drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c | 4 | ||||
| -rw-r--r-- | drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c | 9 |
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. |
