* [PATCH 0/2] Fix use after free, and refactor af_xdp_tx_zc()
@ 2025-01-16 19:56 Ariel Otilibili
2025-01-16 19:56 ` [PATCH 1/2] net/af_xdp: fix use after free in af_xdp_tx_zc() Ariel Otilibili
` (2 more replies)
0 siblings, 3 replies; 10+ messages in thread
From: Ariel Otilibili @ 2025-01-16 19:56 UTC (permalink / raw)
To: dev
Cc: stable, Stephen Hemminger, Thomas Monjalon, David Marchand,
Ciara Loftus, Maryam Tahhan, Ariel Otilibili
Hello,
The series addresses Bugzilla ID 1440 in two steps;
1. Fix use after free.
2. Refactor af_xdp_tx_zc().
Thank you,
Ariel Otilibili (2):
net/af_xdp: fix use after free in af_xdp_tx_zc()
net/af_xdp: Refactor af_xdp_tx_zc()
drivers/net/af_xdp/rte_eth_af_xdp.c | 53 ++++++++++++++---------------
1 file changed, 25 insertions(+), 28 deletions(-)
--
2.30.2
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 1/2] net/af_xdp: fix use after free in af_xdp_tx_zc()
2025-01-16 19:56 [PATCH 0/2] Fix use after free, and refactor af_xdp_tx_zc() Ariel Otilibili
@ 2025-01-16 19:56 ` Ariel Otilibili
2025-01-16 19:56 ` [PATCH 2/2] net/af_xdp: Refactor af_xdp_tx_zc() Ariel Otilibili
2025-01-16 22:51 ` [PATCH v2 0/2] Fix use after free, and refactor af_xdp_tx_zc() Ariel Otilibili
2 siblings, 0 replies; 10+ messages in thread
From: Ariel Otilibili @ 2025-01-16 19:56 UTC (permalink / raw)
To: dev
Cc: stable, Stephen Hemminger, Thomas Monjalon, David Marchand,
Ariel Otilibili, Ciara Loftus, Maryam Tahhan
tx_bytes is computed after both branches are tested. This might
produce a use after memory free.
The computation is now moved into both branches.
Bugzilla ID: 1440
Fixes: d8a210774e1d ("net/af_xdp: support unaligned umem chunks")
Signed-off-by: Ariel Otilibili <ariel.otilibili@6wind.com>
---
drivers/net/af_xdp/rte_eth_af_xdp.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/af_xdp/rte_eth_af_xdp.c b/drivers/net/af_xdp/rte_eth_af_xdp.c
index 814398ba4b44..4326a29f7042 100644
--- a/drivers/net/af_xdp/rte_eth_af_xdp.c
+++ b/drivers/net/af_xdp/rte_eth_af_xdp.c
@@ -574,6 +574,7 @@ af_xdp_tx_zc(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
umem->mb_pool->header_size;
offset = offset << XSK_UNALIGNED_BUF_OFFSET_SHIFT;
desc->addr = addr | offset;
+ tx_bytes += mbuf->pkt_len;
count++;
} else {
struct rte_mbuf *local_mbuf =
@@ -601,11 +602,10 @@ af_xdp_tx_zc(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
desc->addr = addr | offset;
rte_memcpy(pkt, rte_pktmbuf_mtod(mbuf, void *),
desc->len);
+ tx_bytes += mbuf->pkt_len;
rte_pktmbuf_free(mbuf);
count++;
}
-
- tx_bytes += mbuf->pkt_len;
}
out:
--
2.30.2
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 2/2] net/af_xdp: Refactor af_xdp_tx_zc()
2025-01-16 19:56 [PATCH 0/2] Fix use after free, and refactor af_xdp_tx_zc() Ariel Otilibili
2025-01-16 19:56 ` [PATCH 1/2] net/af_xdp: fix use after free in af_xdp_tx_zc() Ariel Otilibili
@ 2025-01-16 19:56 ` Ariel Otilibili
2025-01-16 21:47 ` Stephen Hemminger
2025-01-16 22:51 ` [PATCH v2 0/2] Fix use after free, and refactor af_xdp_tx_zc() Ariel Otilibili
2 siblings, 1 reply; 10+ messages in thread
From: Ariel Otilibili @ 2025-01-16 19:56 UTC (permalink / raw)
To: dev
Cc: stable, Stephen Hemminger, Thomas Monjalon, David Marchand,
Ariel Otilibili, Ciara Loftus, Maryam Tahhan
Both branches of the loop share the same logic. Now each one is a
goto dispatcher; either to out (end of function), or to
stats (continuation of the loop).
Bugzilla ID: 1440
Depends-on: patch-1 ("net/af_xdp: fix use after free in af_xdp_tx_zc()")
Signed-off-by: Ariel Otilibili <ariel.otilibili@6wind.com>
---
drivers/net/af_xdp/rte_eth_af_xdp.c | 57 ++++++++++++++---------------
1 file changed, 27 insertions(+), 30 deletions(-)
diff --git a/drivers/net/af_xdp/rte_eth_af_xdp.c b/drivers/net/af_xdp/rte_eth_af_xdp.c
index 4326a29f7042..8b42704b6d9f 100644
--- a/drivers/net/af_xdp/rte_eth_af_xdp.c
+++ b/drivers/net/af_xdp/rte_eth_af_xdp.c
@@ -551,6 +551,7 @@ af_xdp_tx_zc(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
uint64_t addr, offset;
struct xsk_ring_cons *cq = &txq->pair->cq;
uint32_t free_thresh = cq->size >> 1;
+ struct rte_mbuf *local_mbuf = NULL;
if (xsk_cons_nb_avail(cq, free_thresh) >= free_thresh)
pull_umem_cq(umem, XSK_RING_CONS__DEFAULT_NUM_DESCS, cq);
@@ -565,21 +566,10 @@ af_xdp_tx_zc(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
&idx_tx))
goto out;
}
- desc = xsk_ring_prod__tx_desc(&txq->tx, idx_tx);
- desc->len = mbuf->pkt_len;
- addr = (uint64_t)mbuf - (uint64_t)umem->buffer -
- umem->mb_pool->header_size;
- offset = rte_pktmbuf_mtod(mbuf, uint64_t) -
- (uint64_t)mbuf +
- umem->mb_pool->header_size;
- offset = offset << XSK_UNALIGNED_BUF_OFFSET_SHIFT;
- desc->addr = addr | offset;
- tx_bytes += mbuf->pkt_len;
- count++;
+
+ goto stats;
} else {
- struct rte_mbuf *local_mbuf =
- rte_pktmbuf_alloc(umem->mb_pool);
- void *pkt;
+ local_mbuf = rte_pktmbuf_alloc(umem->mb_pool);
if (local_mbuf == NULL)
goto out;
@@ -589,23 +579,30 @@ af_xdp_tx_zc(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
goto out;
}
- desc = xsk_ring_prod__tx_desc(&txq->tx, idx_tx);
- desc->len = mbuf->pkt_len;
-
- addr = (uint64_t)local_mbuf - (uint64_t)umem->buffer -
- umem->mb_pool->header_size;
- offset = rte_pktmbuf_mtod(local_mbuf, uint64_t) -
- (uint64_t)local_mbuf +
- umem->mb_pool->header_size;
- pkt = xsk_umem__get_data(umem->buffer, addr + offset);
- offset = offset << XSK_UNALIGNED_BUF_OFFSET_SHIFT;
- desc->addr = addr | offset;
- rte_memcpy(pkt, rte_pktmbuf_mtod(mbuf, void *),
- desc->len);
- tx_bytes += mbuf->pkt_len;
- rte_pktmbuf_free(mbuf);
- count++;
+ goto stats;
}
+stats:
+ struct rte_mbuf *tmp;
+ void *pkt;
+ tmp = mbuf->pool == umem->mb_pool ? mbuf : local_mbuf;
+
+ desc = xsk_ring_prod__tx_desc(&txq->tx, idx_tx);
+ desc->len = mbuf->pkt_len;
+
+ addr = (uint64_t)tmp - (uint64_t)umem->buffer - umem->mb_pool->header_size;
+ offset = rte_pktmbuf_mtod(tmp, uint64_t) - (uint64_t)tmp + umem->mb_pool->header_size;
+ offset = offset << XSK_UNALIGNED_BUF_OFFSET_SHIFT;
+ desc->addr = addr | offset;
+
+ if (mbuf->pool == umem->mb_pool) {
+ tx_bytes += mbuf->pkt_len;
+ } else {
+ pkt = xsk_umem__get_data(umem->buffer, addr + offset);
+ rte_memcpy(pkt, rte_pktmbuf_mtod(mbuf, void *), desc->len);
+ tx_bytes += mbuf->pkt_len;
+ rte_pktmbuf_free(mbuf);
+ }
+ count++;
}
out:
--
2.30.2
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 2/2] net/af_xdp: Refactor af_xdp_tx_zc()
2025-01-16 19:56 ` [PATCH 2/2] net/af_xdp: Refactor af_xdp_tx_zc() Ariel Otilibili
@ 2025-01-16 21:47 ` Stephen Hemminger
2025-01-16 22:20 ` Ariel Otilibili
0 siblings, 1 reply; 10+ messages in thread
From: Stephen Hemminger @ 2025-01-16 21:47 UTC (permalink / raw)
To: Ariel Otilibili
Cc: dev, stable, Thomas Monjalon, David Marchand, Ciara Loftus,
Maryam Tahhan
On Thu, 16 Jan 2025 20:56:39 +0100
Ariel Otilibili <ariel.otilibili@6wind.com> wrote:
> Both branches of the loop share the same logic. Now each one is a
> goto dispatcher; either to out (end of function), or to
> stats (continuation of the loop).
>
> Bugzilla ID: 1440
> Depends-on: patch-1 ("net/af_xdp: fix use after free in af_xdp_tx_zc()")
> Signed-off-by: Ariel Otilibili <ariel.otilibili@6wind.com>
> ---
> drivers/net/af_xdp/rte_eth_af_xdp.c | 57 ++++++++++++++---------------
> 1 file changed, 27 insertions(+), 30 deletions(-)
>
> diff --git a/drivers/net/af_xdp/rte_eth_af_xdp.c b/drivers/net/af_xdp/rte_eth_af_xdp.c
> index 4326a29f7042..8b42704b6d9f 100644
> --- a/drivers/net/af_xdp/rte_eth_af_xdp.c
> +++ b/drivers/net/af_xdp/rte_eth_af_xdp.c
> @@ -551,6 +551,7 @@ af_xdp_tx_zc(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
> uint64_t addr, offset;
> struct xsk_ring_cons *cq = &txq->pair->cq;
> uint32_t free_thresh = cq->size >> 1;
> + struct rte_mbuf *local_mbuf = NULL;
>
> if (xsk_cons_nb_avail(cq, free_thresh) >= free_thresh)
> pull_umem_cq(umem, XSK_RING_CONS__DEFAULT_NUM_DESCS, cq);
> @@ -565,21 +566,10 @@ af_xdp_tx_zc(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
> &idx_tx))
> goto out;
> }
> - desc = xsk_ring_prod__tx_desc(&txq->tx, idx_tx);
> - desc->len = mbuf->pkt_len;
> - addr = (uint64_t)mbuf - (uint64_t)umem->buffer -
> - umem->mb_pool->header_size;
> - offset = rte_pktmbuf_mtod(mbuf, uint64_t) -
> - (uint64_t)mbuf +
> - umem->mb_pool->header_size;
> - offset = offset << XSK_UNALIGNED_BUF_OFFSET_SHIFT;
> - desc->addr = addr | offset;
> - tx_bytes += mbuf->pkt_len;
> - count++;
> +
> + goto stats;
> } else {
> - struct rte_mbuf *local_mbuf =
> - rte_pktmbuf_alloc(umem->mb_pool);
> - void *pkt;
> + local_mbuf = rte_pktmbuf_alloc(umem->mb_pool);
>
> if (local_mbuf == NULL)
> goto out;
> @@ -589,23 +579,30 @@ af_xdp_tx_zc(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
> goto out;
> }
>
> - desc = xsk_ring_prod__tx_desc(&txq->tx, idx_tx);
> - desc->len = mbuf->pkt_len;
> -
> - addr = (uint64_t)local_mbuf - (uint64_t)umem->buffer -
> - umem->mb_pool->header_size;
> - offset = rte_pktmbuf_mtod(local_mbuf, uint64_t) -
> - (uint64_t)local_mbuf +
> - umem->mb_pool->header_size;
> - pkt = xsk_umem__get_data(umem->buffer, addr + offset);
> - offset = offset << XSK_UNALIGNED_BUF_OFFSET_SHIFT;
> - desc->addr = addr | offset;
> - rte_memcpy(pkt, rte_pktmbuf_mtod(mbuf, void *),
> - desc->len);
> - tx_bytes += mbuf->pkt_len;
> - rte_pktmbuf_free(mbuf);
> - count++;
> + goto stats;
> }
> +stats:
> + struct rte_mbuf *tmp;
> + void *pkt;
> + tmp = mbuf->pool == umem->mb_pool ? mbuf : local_mbuf;
> +
> + desc = xsk_ring_prod__tx_desc(&txq->tx, idx_tx);
> + desc->len = mbuf->pkt_len;
> +
> + addr = (uint64_t)tmp - (uint64_t)umem->buffer - umem->mb_pool->header_size;
> + offset = rte_pktmbuf_mtod(tmp, uint64_t) - (uint64_t)tmp + umem->mb_pool->header_size;
> + offset = offset << XSK_UNALIGNED_BUF_OFFSET_SHIFT;
> + desc->addr = addr | offset;
> +
> + if (mbuf->pool == umem->mb_pool) {
> + tx_bytes += mbuf->pkt_len;
> + } else {
> + pkt = xsk_umem__get_data(umem->buffer, addr + offset);
> + rte_memcpy(pkt, rte_pktmbuf_mtod(mbuf, void *), desc->len);
> + tx_bytes += mbuf->pkt_len;
> + rte_pktmbuf_free(mbuf);
> + }
> + count++;
> }
>
> out:
Indentation here is wrong, and looks suspect.
Either stats tag should be outside of loop
Or stats is inside loop, and both of those goto's are unnecessary
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 2/2] net/af_xdp: Refactor af_xdp_tx_zc()
2025-01-16 21:47 ` Stephen Hemminger
@ 2025-01-16 22:20 ` Ariel Otilibili
2025-01-16 22:26 ` Stephen Hemminger
0 siblings, 1 reply; 10+ messages in thread
From: Ariel Otilibili @ 2025-01-16 22:20 UTC (permalink / raw)
To: stephen
Cc: dev, stable, Thomas Monjalon, David Marchand, Ciara Loftus,
Maryam Tahhan
[-- Attachment #1: Type: text/plain, Size: 5219 bytes --]
Hi Stephen,
On Thu, Jan 16, 2025 at 10:47 PM Stephen Hemminger <
stephen@networkplumber.org> wrote:
> On Thu, 16 Jan 2025 20:56:39 +0100
> Ariel Otilibili <ariel.otilibili@6wind.com> wrote:
>
> > Both branches of the loop share the same logic. Now each one is a
> > goto dispatcher; either to out (end of function), or to
> > stats (continuation of the loop).
> >
> > Bugzilla ID: 1440
> > Depends-on: patch-1 ("net/af_xdp: fix use after free in af_xdp_tx_zc()")
> > Signed-off-by: Ariel Otilibili <ariel.otilibili@6wind.com>
> > ---
> > drivers/net/af_xdp/rte_eth_af_xdp.c | 57 ++++++++++++++---------------
> > 1 file changed, 27 insertions(+), 30 deletions(-)
> >
> > diff --git a/drivers/net/af_xdp/rte_eth_af_xdp.c
> b/drivers/net/af_xdp/rte_eth_af_xdp.c
> > index 4326a29f7042..8b42704b6d9f 100644
> > --- a/drivers/net/af_xdp/rte_eth_af_xdp.c
> > +++ b/drivers/net/af_xdp/rte_eth_af_xdp.c
> > @@ -551,6 +551,7 @@ af_xdp_tx_zc(void *queue, struct rte_mbuf **bufs,
> uint16_t nb_pkts)
> > uint64_t addr, offset;
> > struct xsk_ring_cons *cq = &txq->pair->cq;
> > uint32_t free_thresh = cq->size >> 1;
> > + struct rte_mbuf *local_mbuf = NULL;
> >
> > if (xsk_cons_nb_avail(cq, free_thresh) >= free_thresh)
> > pull_umem_cq(umem, XSK_RING_CONS__DEFAULT_NUM_DESCS, cq);
> > @@ -565,21 +566,10 @@ af_xdp_tx_zc(void *queue, struct rte_mbuf **bufs,
> uint16_t nb_pkts)
> > &idx_tx))
> > goto out;
> > }
> > - desc = xsk_ring_prod__tx_desc(&txq->tx, idx_tx);
> > - desc->len = mbuf->pkt_len;
> > - addr = (uint64_t)mbuf - (uint64_t)umem->buffer -
> > - umem->mb_pool->header_size;
> > - offset = rte_pktmbuf_mtod(mbuf, uint64_t) -
> > - (uint64_t)mbuf +
> > - umem->mb_pool->header_size;
> > - offset = offset << XSK_UNALIGNED_BUF_OFFSET_SHIFT;
> > - desc->addr = addr | offset;
> > - tx_bytes += mbuf->pkt_len;
> > - count++;
> > +
> > + goto stats;
> > } else {
> > - struct rte_mbuf *local_mbuf =
> > - rte_pktmbuf_alloc(umem->mb_pool);
> > - void *pkt;
> > + local_mbuf = rte_pktmbuf_alloc(umem->mb_pool);
> >
> > if (local_mbuf == NULL)
> > goto out;
> > @@ -589,23 +579,30 @@ af_xdp_tx_zc(void *queue, struct rte_mbuf **bufs,
> uint16_t nb_pkts)
> > goto out;
> > }
> >
> > - desc = xsk_ring_prod__tx_desc(&txq->tx, idx_tx);
> > - desc->len = mbuf->pkt_len;
> > -
> > - addr = (uint64_t)local_mbuf -
> (uint64_t)umem->buffer -
> > - umem->mb_pool->header_size;
> > - offset = rte_pktmbuf_mtod(local_mbuf, uint64_t) -
> > - (uint64_t)local_mbuf +
> > - umem->mb_pool->header_size;
> > - pkt = xsk_umem__get_data(umem->buffer, addr +
> offset);
> > - offset = offset << XSK_UNALIGNED_BUF_OFFSET_SHIFT;
> > - desc->addr = addr | offset;
> > - rte_memcpy(pkt, rte_pktmbuf_mtod(mbuf, void *),
> > - desc->len);
> > - tx_bytes += mbuf->pkt_len;
> > - rte_pktmbuf_free(mbuf);
> > - count++;
> > + goto stats;
> > }
> > +stats:
> > + struct rte_mbuf *tmp;
> > + void *pkt;
> > + tmp = mbuf->pool == umem->mb_pool ? mbuf : local_mbuf;
> > +
> > + desc = xsk_ring_prod__tx_desc(&txq->tx, idx_tx);
> > + desc->len = mbuf->pkt_len;
> > +
> > + addr = (uint64_t)tmp - (uint64_t)umem->buffer -
> umem->mb_pool->header_size;
> > + offset = rte_pktmbuf_mtod(tmp, uint64_t) - (uint64_t)tmp +
> umem->mb_pool->header_size;
> > + offset = offset << XSK_UNALIGNED_BUF_OFFSET_SHIFT;
> > + desc->addr = addr | offset;
> > +
> > + if (mbuf->pool == umem->mb_pool) {
> > + tx_bytes += mbuf->pkt_len;
> > + } else {
> > + pkt = xsk_umem__get_data(umem->buffer, addr + offset);
> > + rte_memcpy(pkt, rte_pktmbuf_mtod(mbuf, void *), desc->len);
> > + tx_bytes += mbuf->pkt_len;
> > + rte_pktmbuf_free(mbuf);
> > + }
> > + count++;
> > }
> >
> > out:
>
> Indentation here is wrong, and looks suspect.
> Either stats tag should be outside of loop
> Or stats is inside loop, and both of those goto's are unnecessary
>
Thanks for the feedback; I am pushing a new series with an extra tab.
So it be obvious that stats belongs to the the loop.
[-- Attachment #2: Type: text/html, Size: 7024 bytes --]
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 2/2] net/af_xdp: Refactor af_xdp_tx_zc()
2025-01-16 22:20 ` Ariel Otilibili
@ 2025-01-16 22:26 ` Stephen Hemminger
2025-01-16 22:36 ` Ariel Otilibili
0 siblings, 1 reply; 10+ messages in thread
From: Stephen Hemminger @ 2025-01-16 22:26 UTC (permalink / raw)
To: Ariel Otilibili
Cc: dev, stable, Thomas Monjalon, David Marchand, Ciara Loftus,
Maryam Tahhan
On Thu, 16 Jan 2025 23:20:06 +0100
Ariel Otilibili <ariel.otilibili@6wind.com> wrote:
> Hi Stephen,
>
> On Thu, Jan 16, 2025 at 10:47 PM Stephen Hemminger <
> stephen@networkplumber.org> wrote:
>
> > On Thu, 16 Jan 2025 20:56:39 +0100
> > Ariel Otilibili <ariel.otilibili@6wind.com> wrote:
> >
> > > Both branches of the loop share the same logic. Now each one is a
> > > goto dispatcher; either to out (end of function), or to
> > > stats (continuation of the loop).
> > >
> > > Bugzilla ID: 1440
> > > Depends-on: patch-1 ("net/af_xdp: fix use after free in af_xdp_tx_zc()")
> > > Signed-off-by: Ariel Otilibili <ariel.otilibili@6wind.com>
> > > ---
> > > drivers/net/af_xdp/rte_eth_af_xdp.c | 57 ++++++++++++++---------------
> > > 1 file changed, 27 insertions(+), 30 deletions(-)
> > >
> > > diff --git a/drivers/net/af_xdp/rte_eth_af_xdp.c
> > b/drivers/net/af_xdp/rte_eth_af_xdp.c
> > > index 4326a29f7042..8b42704b6d9f 100644
> > > --- a/drivers/net/af_xdp/rte_eth_af_xdp.c
> > > +++ b/drivers/net/af_xdp/rte_eth_af_xdp.c
> > > @@ -551,6 +551,7 @@ af_xdp_tx_zc(void *queue, struct rte_mbuf **bufs,
> > uint16_t nb_pkts)
> > > uint64_t addr, offset;
> > > struct xsk_ring_cons *cq = &txq->pair->cq;
> > > uint32_t free_thresh = cq->size >> 1;
> > > + struct rte_mbuf *local_mbuf = NULL;
> > >
> > > if (xsk_cons_nb_avail(cq, free_thresh) >= free_thresh)
> > > pull_umem_cq(umem, XSK_RING_CONS__DEFAULT_NUM_DESCS, cq);
> > > @@ -565,21 +566,10 @@ af_xdp_tx_zc(void *queue, struct rte_mbuf **bufs,
> > uint16_t nb_pkts)
> > > &idx_tx))
> > > goto out;
> > > }
> > > - desc = xsk_ring_prod__tx_desc(&txq->tx, idx_tx);
> > > - desc->len = mbuf->pkt_len;
> > > - addr = (uint64_t)mbuf - (uint64_t)umem->buffer -
> > > - umem->mb_pool->header_size;
> > > - offset = rte_pktmbuf_mtod(mbuf, uint64_t) -
> > > - (uint64_t)mbuf +
> > > - umem->mb_pool->header_size;
> > > - offset = offset << XSK_UNALIGNED_BUF_OFFSET_SHIFT;
> > > - desc->addr = addr | offset;
> > > - tx_bytes += mbuf->pkt_len;
> > > - count++;
> > > +
> > > + goto stats;
> > > } else {
> > > - struct rte_mbuf *local_mbuf =
> > > - rte_pktmbuf_alloc(umem->mb_pool);
> > > - void *pkt;
> > > + local_mbuf = rte_pktmbuf_alloc(umem->mb_pool);
> > >
> > > if (local_mbuf == NULL)
> > > goto out;
> > > @@ -589,23 +579,30 @@ af_xdp_tx_zc(void *queue, struct rte_mbuf **bufs,
> > uint16_t nb_pkts)
> > > goto out;
> > > }
> > >
> > > - desc = xsk_ring_prod__tx_desc(&txq->tx, idx_tx);
> > > - desc->len = mbuf->pkt_len;
> > > -
> > > - addr = (uint64_t)local_mbuf -
> > (uint64_t)umem->buffer -
> > > - umem->mb_pool->header_size;
> > > - offset = rte_pktmbuf_mtod(local_mbuf, uint64_t) -
> > > - (uint64_t)local_mbuf +
> > > - umem->mb_pool->header_size;
> > > - pkt = xsk_umem__get_data(umem->buffer, addr +
> > offset);
> > > - offset = offset << XSK_UNALIGNED_BUF_OFFSET_SHIFT;
> > > - desc->addr = addr | offset;
> > > - rte_memcpy(pkt, rte_pktmbuf_mtod(mbuf, void *),
> > > - desc->len);
> > > - tx_bytes += mbuf->pkt_len;
> > > - rte_pktmbuf_free(mbuf);
> > > - count++;
> > > + goto stats;
> > > }
> > > +stats:
> > > + struct rte_mbuf *tmp;
> > > + void *pkt;
> > > + tmp = mbuf->pool == umem->mb_pool ? mbuf : local_mbuf;
> > > +
> > > + desc = xsk_ring_prod__tx_desc(&txq->tx, idx_tx);
> > > + desc->len = mbuf->pkt_len;
> > > +
> > > + addr = (uint64_t)tmp - (uint64_t)umem->buffer -
> > umem->mb_pool->header_size;
> > > + offset = rte_pktmbuf_mtod(tmp, uint64_t) - (uint64_t)tmp +
> > umem->mb_pool->header_size;
> > > + offset = offset << XSK_UNALIGNED_BUF_OFFSET_SHIFT;
> > > + desc->addr = addr | offset;
> > > +
> > > + if (mbuf->pool == umem->mb_pool) {
> > > + tx_bytes += mbuf->pkt_len;
> > > + } else {
> > > + pkt = xsk_umem__get_data(umem->buffer, addr + offset);
> > > + rte_memcpy(pkt, rte_pktmbuf_mtod(mbuf, void *), desc->len);
> > > + tx_bytes += mbuf->pkt_len;
> > > + rte_pktmbuf_free(mbuf);
> > > + }
> > > + count++;
> > > }
> > >
> > > out:
> >
> > Indentation here is wrong, and looks suspect.
> > Either stats tag should be outside of loop
> > Or stats is inside loop, and both of those goto's are unnecessary
> >
> Thanks for the feedback; I am pushing a new series with an extra tab.
> So it be obvious that stats belongs to the the loop.
But the the goto;s aren't needed? Both legs of the If would fall through
to that location.
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 2/2] net/af_xdp: Refactor af_xdp_tx_zc()
2025-01-16 22:26 ` Stephen Hemminger
@ 2025-01-16 22:36 ` Ariel Otilibili
0 siblings, 0 replies; 10+ messages in thread
From: Ariel Otilibili @ 2025-01-16 22:36 UTC (permalink / raw)
To: Stephen Hemminger
Cc: dev, stable, Thomas Monjalon, David Marchand, Ciara Loftus,
Maryam Tahhan
[-- Attachment #1: Type: text/plain, Size: 6144 bytes --]
On Thu, Jan 16, 2025 at 11:26 PM Stephen Hemminger <
stephen@networkplumber.org> wrote:
> On Thu, 16 Jan 2025 23:20:06 +0100
> Ariel Otilibili <ariel.otilibili@6wind.com> wrote:
>
> > Hi Stephen,
> >
> > On Thu, Jan 16, 2025 at 10:47 PM Stephen Hemminger <
> > stephen@networkplumber.org> wrote:
> >
> > > On Thu, 16 Jan 2025 20:56:39 +0100
> > > Ariel Otilibili <ariel.otilibili@6wind.com> wrote:
> > >
> > > > Both branches of the loop share the same logic. Now each one is a
> > > > goto dispatcher; either to out (end of function), or to
> > > > stats (continuation of the loop).
> > > >
> > > > Bugzilla ID: 1440
> > > > Depends-on: patch-1 ("net/af_xdp: fix use after free in
> af_xdp_tx_zc()")
> > > > Signed-off-by: Ariel Otilibili <ariel.otilibili@6wind.com>
> > > > ---
> > > > drivers/net/af_xdp/rte_eth_af_xdp.c | 57
> ++++++++++++++---------------
> > > > 1 file changed, 27 insertions(+), 30 deletions(-)
> > > >
> > > > diff --git a/drivers/net/af_xdp/rte_eth_af_xdp.c
> > > b/drivers/net/af_xdp/rte_eth_af_xdp.c
> > > > index 4326a29f7042..8b42704b6d9f 100644
> > > > --- a/drivers/net/af_xdp/rte_eth_af_xdp.c
> > > > +++ b/drivers/net/af_xdp/rte_eth_af_xdp.c
> > > > @@ -551,6 +551,7 @@ af_xdp_tx_zc(void *queue, struct rte_mbuf
> **bufs,
> > > uint16_t nb_pkts)
> > > > uint64_t addr, offset;
> > > > struct xsk_ring_cons *cq = &txq->pair->cq;
> > > > uint32_t free_thresh = cq->size >> 1;
> > > > + struct rte_mbuf *local_mbuf = NULL;
> > > >
> > > > if (xsk_cons_nb_avail(cq, free_thresh) >= free_thresh)
> > > > pull_umem_cq(umem, XSK_RING_CONS__DEFAULT_NUM_DESCS,
> cq);
> > > > @@ -565,21 +566,10 @@ af_xdp_tx_zc(void *queue, struct rte_mbuf
> **bufs,
> > > uint16_t nb_pkts)
> > > > &idx_tx))
> > > > goto out;
> > > > }
> > > > - desc = xsk_ring_prod__tx_desc(&txq->tx,
> idx_tx);
> > > > - desc->len = mbuf->pkt_len;
> > > > - addr = (uint64_t)mbuf - (uint64_t)umem->buffer
> -
> > > > - umem->mb_pool->header_size;
> > > > - offset = rte_pktmbuf_mtod(mbuf, uint64_t) -
> > > > - (uint64_t)mbuf +
> > > > - umem->mb_pool->header_size;
> > > > - offset = offset <<
> XSK_UNALIGNED_BUF_OFFSET_SHIFT;
> > > > - desc->addr = addr | offset;
> > > > - tx_bytes += mbuf->pkt_len;
> > > > - count++;
> > > > +
> > > > + goto stats;
> > > > } else {
> > > > - struct rte_mbuf *local_mbuf =
> > > > -
> rte_pktmbuf_alloc(umem->mb_pool);
> > > > - void *pkt;
> > > > + local_mbuf = rte_pktmbuf_alloc(umem->mb_pool);
> > > >
> > > > if (local_mbuf == NULL)
> > > > goto out;
> > > > @@ -589,23 +579,30 @@ af_xdp_tx_zc(void *queue, struct rte_mbuf
> **bufs,
> > > uint16_t nb_pkts)
> > > > goto out;
> > > > }
> > > >
> > > > - desc = xsk_ring_prod__tx_desc(&txq->tx,
> idx_tx);
> > > > - desc->len = mbuf->pkt_len;
> > > > -
> > > > - addr = (uint64_t)local_mbuf -
> > > (uint64_t)umem->buffer -
> > > > - umem->mb_pool->header_size;
> > > > - offset = rte_pktmbuf_mtod(local_mbuf,
> uint64_t) -
> > > > - (uint64_t)local_mbuf +
> > > > - umem->mb_pool->header_size;
> > > > - pkt = xsk_umem__get_data(umem->buffer, addr +
> > > offset);
> > > > - offset = offset <<
> XSK_UNALIGNED_BUF_OFFSET_SHIFT;
> > > > - desc->addr = addr | offset;
> > > > - rte_memcpy(pkt, rte_pktmbuf_mtod(mbuf, void *),
> > > > - desc->len);
> > > > - tx_bytes += mbuf->pkt_len;
> > > > - rte_pktmbuf_free(mbuf);
> > > > - count++;
> > > > + goto stats;
> > > > }
> > > > +stats:
> > > > + struct rte_mbuf *tmp;
> > > > + void *pkt;
> > > > + tmp = mbuf->pool == umem->mb_pool ? mbuf : local_mbuf;
> > > > +
> > > > + desc = xsk_ring_prod__tx_desc(&txq->tx, idx_tx);
> > > > + desc->len = mbuf->pkt_len;
> > > > +
> > > > + addr = (uint64_t)tmp - (uint64_t)umem->buffer -
> > > umem->mb_pool->header_size;
> > > > + offset = rte_pktmbuf_mtod(tmp, uint64_t) - (uint64_t)tmp +
> > > umem->mb_pool->header_size;
> > > > + offset = offset << XSK_UNALIGNED_BUF_OFFSET_SHIFT;
> > > > + desc->addr = addr | offset;
> > > > +
> > > > + if (mbuf->pool == umem->mb_pool) {
> > > > + tx_bytes += mbuf->pkt_len;
> > > > + } else {
> > > > + pkt = xsk_umem__get_data(umem->buffer, addr + offset);
> > > > + rte_memcpy(pkt, rte_pktmbuf_mtod(mbuf, void *),
> desc->len);
> > > > + tx_bytes += mbuf->pkt_len;
> > > > + rte_pktmbuf_free(mbuf);
> > > > + }
> > > > + count++;
> > > > }
> > > >
> > > > out:
> > >
> > > Indentation here is wrong, and looks suspect.
> > > Either stats tag should be outside of loop
> > > Or stats is inside loop, and both of those goto's are unnecessary
> > >
> > Thanks for the feedback; I am pushing a new series with an extra tab.
> > So it be obvious that stats belongs to the the loop.
>
>
> But the the goto;s aren't needed? Both legs of the If would fall through
> to that location.
>
You are right, Stephen; thanks for the heads up. I am pushing that change,
without any goto in each leg, so fall through.
Bear with me for some time.
[-- Attachment #2: Type: text/html, Size: 8903 bytes --]
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v2 0/2] Fix use after free, and refactor af_xdp_tx_zc()
2025-01-16 19:56 [PATCH 0/2] Fix use after free, and refactor af_xdp_tx_zc() Ariel Otilibili
2025-01-16 19:56 ` [PATCH 1/2] net/af_xdp: fix use after free in af_xdp_tx_zc() Ariel Otilibili
2025-01-16 19:56 ` [PATCH 2/2] net/af_xdp: Refactor af_xdp_tx_zc() Ariel Otilibili
@ 2025-01-16 22:51 ` Ariel Otilibili
2025-01-16 22:51 ` [PATCH v2 1/2] net/af_xdp: fix use after free in af_xdp_tx_zc() Ariel Otilibili
2025-01-16 22:51 ` [PATCH v2 2/2] net/af_xdp: Refactor af_xdp_tx_zc() Ariel Otilibili
2 siblings, 2 replies; 10+ messages in thread
From: Ariel Otilibili @ 2025-01-16 22:51 UTC (permalink / raw)
To: dev
Cc: stable, Stephen Hemminger, Thomas Monjalon, David Marchand,
Ariel Otilibili, Ciara Loftus, Maryam Tahhan
Hello,
The series addresses Bugzilla ID 1440 in two steps;
1. Fix use after free.
2. Refactor af_xdp_tx_zc().
Thank you,
---
v2
* reworded commit messages
* addressed feedback from Stephen Hemminger
v1 (http://inbox.dpdk.org/dev/20250116195640.68885-1-ariel.otilibili@6wind.com/)
Ariel Otilibili (2):
net/af_xdp: fix use after free in af_xdp_tx_zc()
net/af_xdp: Refactor af_xdp_tx_zc()
drivers/net/af_xdp/rte_eth_af_xdp.c | 49 +++++++++++++----------------
1 file changed, 22 insertions(+), 27 deletions(-)
--
2.30.2
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v2 1/2] net/af_xdp: fix use after free in af_xdp_tx_zc()
2025-01-16 22:51 ` [PATCH v2 0/2] Fix use after free, and refactor af_xdp_tx_zc() Ariel Otilibili
@ 2025-01-16 22:51 ` Ariel Otilibili
2025-01-16 22:51 ` [PATCH v2 2/2] net/af_xdp: Refactor af_xdp_tx_zc() Ariel Otilibili
1 sibling, 0 replies; 10+ messages in thread
From: Ariel Otilibili @ 2025-01-16 22:51 UTC (permalink / raw)
To: dev
Cc: stable, Stephen Hemminger, Thomas Monjalon, David Marchand,
Ariel Otilibili, Ciara Loftus, Maryam Tahhan
tx_bytes is computed after both legs are tested. This might
produce a use after memory free.
The computation is now moved into each leg.
Bugzilla ID: 1440
Fixes: d8a210774e1d ("net/af_xdp: support unaligned umem chunks")
Signed-off-by: Ariel Otilibili <ariel.otilibili@6wind.com>
---
drivers/net/af_xdp/rte_eth_af_xdp.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/af_xdp/rte_eth_af_xdp.c b/drivers/net/af_xdp/rte_eth_af_xdp.c
index 814398ba4b44..4326a29f7042 100644
--- a/drivers/net/af_xdp/rte_eth_af_xdp.c
+++ b/drivers/net/af_xdp/rte_eth_af_xdp.c
@@ -574,6 +574,7 @@ af_xdp_tx_zc(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
umem->mb_pool->header_size;
offset = offset << XSK_UNALIGNED_BUF_OFFSET_SHIFT;
desc->addr = addr | offset;
+ tx_bytes += mbuf->pkt_len;
count++;
} else {
struct rte_mbuf *local_mbuf =
@@ -601,11 +602,10 @@ af_xdp_tx_zc(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
desc->addr = addr | offset;
rte_memcpy(pkt, rte_pktmbuf_mtod(mbuf, void *),
desc->len);
+ tx_bytes += mbuf->pkt_len;
rte_pktmbuf_free(mbuf);
count++;
}
-
- tx_bytes += mbuf->pkt_len;
}
out:
--
2.30.2
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v2 2/2] net/af_xdp: Refactor af_xdp_tx_zc()
2025-01-16 22:51 ` [PATCH v2 0/2] Fix use after free, and refactor af_xdp_tx_zc() Ariel Otilibili
2025-01-16 22:51 ` [PATCH v2 1/2] net/af_xdp: fix use after free in af_xdp_tx_zc() Ariel Otilibili
@ 2025-01-16 22:51 ` Ariel Otilibili
1 sibling, 0 replies; 10+ messages in thread
From: Ariel Otilibili @ 2025-01-16 22:51 UTC (permalink / raw)
To: dev
Cc: stable, Stephen Hemminger, Thomas Monjalon, David Marchand,
Ariel Otilibili, Ciara Loftus, Maryam Tahhan
Both legs of the loop share the same logic: either to go out of the
function, or to fall through to the next instructions.
Depends-on: patch-1 ("net/af_xdp: fix use after free in af_xdp_tx_zc()")
Bugzilla ID: 1440
Signed-off-by: Ariel Otilibili <ariel.otilibili@6wind.com>
---
drivers/net/af_xdp/rte_eth_af_xdp.c | 47 +++++++++++++----------------
1 file changed, 21 insertions(+), 26 deletions(-)
diff --git a/drivers/net/af_xdp/rte_eth_af_xdp.c b/drivers/net/af_xdp/rte_eth_af_xdp.c
index 4326a29f7042..b1de47a41eb3 100644
--- a/drivers/net/af_xdp/rte_eth_af_xdp.c
+++ b/drivers/net/af_xdp/rte_eth_af_xdp.c
@@ -551,6 +551,7 @@ af_xdp_tx_zc(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
uint64_t addr, offset;
struct xsk_ring_cons *cq = &txq->pair->cq;
uint32_t free_thresh = cq->size >> 1;
+ struct rte_mbuf *local_mbuf = NULL;
if (xsk_cons_nb_avail(cq, free_thresh) >= free_thresh)
pull_umem_cq(umem, XSK_RING_CONS__DEFAULT_NUM_DESCS, cq);
@@ -565,21 +566,8 @@ af_xdp_tx_zc(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
&idx_tx))
goto out;
}
- desc = xsk_ring_prod__tx_desc(&txq->tx, idx_tx);
- desc->len = mbuf->pkt_len;
- addr = (uint64_t)mbuf - (uint64_t)umem->buffer -
- umem->mb_pool->header_size;
- offset = rte_pktmbuf_mtod(mbuf, uint64_t) -
- (uint64_t)mbuf +
- umem->mb_pool->header_size;
- offset = offset << XSK_UNALIGNED_BUF_OFFSET_SHIFT;
- desc->addr = addr | offset;
- tx_bytes += mbuf->pkt_len;
- count++;
} else {
- struct rte_mbuf *local_mbuf =
- rte_pktmbuf_alloc(umem->mb_pool);
- void *pkt;
+ local_mbuf = rte_pktmbuf_alloc(umem->mb_pool);
if (local_mbuf == NULL)
goto out;
@@ -588,24 +576,31 @@ af_xdp_tx_zc(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
rte_pktmbuf_free(local_mbuf);
goto out;
}
+ }
- desc = xsk_ring_prod__tx_desc(&txq->tx, idx_tx);
- desc->len = mbuf->pkt_len;
+ struct rte_mbuf *tmp;
+ void *pkt;
+ tmp = mbuf->pool == umem->mb_pool ? mbuf : local_mbuf;
+
+ desc = xsk_ring_prod__tx_desc(&txq->tx, idx_tx);
+ desc->len = mbuf->pkt_len;
- addr = (uint64_t)local_mbuf - (uint64_t)umem->buffer -
- umem->mb_pool->header_size;
- offset = rte_pktmbuf_mtod(local_mbuf, uint64_t) -
- (uint64_t)local_mbuf +
- umem->mb_pool->header_size;
+ addr = (uint64_t)tmp - (uint64_t)umem->buffer
+ - umem->mb_pool->header_size;
+ offset = rte_pktmbuf_mtod(tmp, uint64_t) - (uint64_t)tmp
+ + umem->mb_pool->header_size;
+ offset = offset << XSK_UNALIGNED_BUF_OFFSET_SHIFT;
+ desc->addr = addr | offset;
+
+ if (mbuf->pool == umem->mb_pool) {
+ tx_bytes += mbuf->pkt_len;
+ } else {
pkt = xsk_umem__get_data(umem->buffer, addr + offset);
- offset = offset << XSK_UNALIGNED_BUF_OFFSET_SHIFT;
- desc->addr = addr | offset;
- rte_memcpy(pkt, rte_pktmbuf_mtod(mbuf, void *),
- desc->len);
+ rte_memcpy(pkt, rte_pktmbuf_mtod(mbuf, void *), desc->len);
tx_bytes += mbuf->pkt_len;
rte_pktmbuf_free(mbuf);
- count++;
}
+ count++;
}
out:
--
2.30.2
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2025-01-16 22:52 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-01-16 19:56 [PATCH 0/2] Fix use after free, and refactor af_xdp_tx_zc() Ariel Otilibili
2025-01-16 19:56 ` [PATCH 1/2] net/af_xdp: fix use after free in af_xdp_tx_zc() Ariel Otilibili
2025-01-16 19:56 ` [PATCH 2/2] net/af_xdp: Refactor af_xdp_tx_zc() Ariel Otilibili
2025-01-16 21:47 ` Stephen Hemminger
2025-01-16 22:20 ` Ariel Otilibili
2025-01-16 22:26 ` Stephen Hemminger
2025-01-16 22:36 ` Ariel Otilibili
2025-01-16 22:51 ` [PATCH v2 0/2] Fix use after free, and refactor af_xdp_tx_zc() Ariel Otilibili
2025-01-16 22:51 ` [PATCH v2 1/2] net/af_xdp: fix use after free in af_xdp_tx_zc() Ariel Otilibili
2025-01-16 22:51 ` [PATCH v2 2/2] net/af_xdp: Refactor af_xdp_tx_zc() Ariel Otilibili
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).