* [PATCH net 0/2] Fix use-after-free in metadata dst teardown in airoha_eth and mtk_eth_soc drivers
@ 2026-06-02 9:21 Lorenzo Bianconi
2026-06-02 9:21 ` [PATCH net 1/2] net: airoha: Fix use-after-free in metadata dst teardown Lorenzo Bianconi
` (2 more replies)
0 siblings, 3 replies; 7+ messages in thread
From: Lorenzo Bianconi @ 2026-06-02 9:21 UTC (permalink / raw)
To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Felix Fietkau, Matthias Brugger,
AngeloGioacchino Del Regno
Cc: Florian Westphal, linux-arm-kernel, linux-mediatek, netdev,
Lorenzo Bianconi
airoha_metadata_dst_free() and mtk_free_dev() call metadata_dst_free()
which frees the metadata_dst with kfree() immediately, bypassing the RCU
grace period.
Replace metadata_dst_free() with dst_release() which properly goes
through the refcount path and runs call_rcu_hurry() if refcount goes to
zero.
---
Lorenzo Bianconi (2):
net: airoha: Fix use-after-free in metadata dst teardown
net: ethernet: mtk_eth_soc: Fix use-after-free in metadata dst teardown
drivers/net/ethernet/airoha/airoha_eth.c | 2 +-
drivers/net/ethernet/mediatek/mtk_eth_soc.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
---
base-commit: 3522b21fd7e1863d0734537737bd59f1b90d0190
change-id: 20260602-airoha-mtk-metadata-uaf-fix-eb03badb1a94
Best regards,
--
Lorenzo Bianconi <lorenzo@kernel.org>
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH net 1/2] net: airoha: Fix use-after-free in metadata dst teardown
2026-06-02 9:21 [PATCH net 0/2] Fix use-after-free in metadata dst teardown in airoha_eth and mtk_eth_soc drivers Lorenzo Bianconi
@ 2026-06-02 9:21 ` Lorenzo Bianconi
2026-06-04 17:38 ` Jacob Keller
2026-06-02 9:21 ` [PATCH net 2/2] net: ethernet: mtk_eth_soc: " Lorenzo Bianconi
2026-06-04 2:30 ` [PATCH net 0/2] Fix use-after-free in metadata dst teardown in airoha_eth and mtk_eth_soc drivers patchwork-bot+netdevbpf
2 siblings, 1 reply; 7+ messages in thread
From: Lorenzo Bianconi @ 2026-06-02 9:21 UTC (permalink / raw)
To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Felix Fietkau, Matthias Brugger,
AngeloGioacchino Del Regno
Cc: Florian Westphal, linux-arm-kernel, linux-mediatek, netdev,
Lorenzo Bianconi
airoha_metadata_dst_free() runs metadata_dst_free() which frees the
metadata_dst with kfree() immediately, bypassing the RCU grace period.
In the RX path, skb_dst_set_noref() sets a non-refcounted pointer from
the skb to the metadata_dst. This function requires RCU read-side
protection and the dst must remain valid until all RCU readers complete.
Since metadata_dst_free() calls kfree() directly, an use-after-free can
occur if any skb still holds a noref pointer to the dst when the driver
tears it down.
Replace metadata_dst_free() with dst_release() which properly goes
through the refcount path: when the refcount drops to zero, it schedules
the actual free via call_rcu_hurry(), ensuring all RCU readers have
completed before the memory is freed.
Fixes: af3cf757d5c9 ("net: airoha: Move DSA tag in DMA descriptor")
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
drivers/net/ethernet/airoha/airoha_eth.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c
index cecd66251dba..eab6a98d62b9 100644
--- a/drivers/net/ethernet/airoha/airoha_eth.c
+++ b/drivers/net/ethernet/airoha/airoha_eth.c
@@ -2936,7 +2936,7 @@ static void airoha_metadata_dst_free(struct airoha_gdm_port *port)
if (!port->dsa_meta[i])
continue;
- metadata_dst_free(port->dsa_meta[i]);
+ dst_release(&port->dsa_meta[i]->dst);
}
}
--
2.54.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH net 2/2] net: ethernet: mtk_eth_soc: Fix use-after-free in metadata dst teardown
2026-06-02 9:21 [PATCH net 0/2] Fix use-after-free in metadata dst teardown in airoha_eth and mtk_eth_soc drivers Lorenzo Bianconi
2026-06-02 9:21 ` [PATCH net 1/2] net: airoha: Fix use-after-free in metadata dst teardown Lorenzo Bianconi
@ 2026-06-02 9:21 ` Lorenzo Bianconi
2026-06-04 2:30 ` [PATCH net 0/2] Fix use-after-free in metadata dst teardown in airoha_eth and mtk_eth_soc drivers patchwork-bot+netdevbpf
2 siblings, 0 replies; 7+ messages in thread
From: Lorenzo Bianconi @ 2026-06-02 9:21 UTC (permalink / raw)
To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Felix Fietkau, Matthias Brugger,
AngeloGioacchino Del Regno
Cc: Florian Westphal, linux-arm-kernel, linux-mediatek, netdev,
Lorenzo Bianconi
mtk_free_dev() calls metadata_dst_free() which frees the metadata_dst
with kfree() immediately, bypassing the RCU grace period.
In the RX path, skb_dst_set_noref() sets a non-refcounted pointer from
the skb to the metadata_dst. This function requires RCU read-side
protection and the dst must remain valid until all RCU readers complete.
Since metadata_dst_free() calls kfree() directly, a use-after-free can
occur if any skb still holds a noref pointer to the dst when the driver
tears it down.
Replace metadata_dst_free() with dst_release() which properly goes
through the refcount path: when the refcount drops to zero, it schedules
the actual free via call_rcu_hurry(), ensuring all RCU readers have
completed before the memory is freed.
Fixes: 2d7605a72906 ("net: ethernet: mtk_eth_soc: enable hardware DSA untagging")
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
drivers/net/ethernet/mediatek/mtk_eth_soc.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index 8d225bc9f063..7d771168b990 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -4491,7 +4491,7 @@ static int mtk_free_dev(struct mtk_eth *eth)
for (i = 0; i < ARRAY_SIZE(eth->dsa_meta); i++) {
if (!eth->dsa_meta[i])
break;
- metadata_dst_free(eth->dsa_meta[i]);
+ dst_release(ð->dsa_meta[i]->dst);
}
return 0;
--
2.54.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH net 0/2] Fix use-after-free in metadata dst teardown in airoha_eth and mtk_eth_soc drivers
2026-06-02 9:21 [PATCH net 0/2] Fix use-after-free in metadata dst teardown in airoha_eth and mtk_eth_soc drivers Lorenzo Bianconi
2026-06-02 9:21 ` [PATCH net 1/2] net: airoha: Fix use-after-free in metadata dst teardown Lorenzo Bianconi
2026-06-02 9:21 ` [PATCH net 2/2] net: ethernet: mtk_eth_soc: " Lorenzo Bianconi
@ 2026-06-04 2:30 ` patchwork-bot+netdevbpf
2 siblings, 0 replies; 7+ messages in thread
From: patchwork-bot+netdevbpf @ 2026-06-04 2:30 UTC (permalink / raw)
To: Lorenzo Bianconi
Cc: andrew+netdev, davem, edumazet, kuba, pabeni, nbd, matthias.bgg,
angelogioacchino.delregno, fw, linux-arm-kernel, linux-mediatek,
netdev
Hello:
This series was applied to netdev/net.git (main)
by Jakub Kicinski <kuba@kernel.org>:
On Tue, 02 Jun 2026 11:21:03 +0200 you wrote:
> airoha_metadata_dst_free() and mtk_free_dev() call metadata_dst_free()
> which frees the metadata_dst with kfree() immediately, bypassing the RCU
> grace period.
> Replace metadata_dst_free() with dst_release() which properly goes
> through the refcount path and runs call_rcu_hurry() if refcount goes to
> zero.
>
> [...]
Here is the summary with links:
- [net,1/2] net: airoha: Fix use-after-free in metadata dst teardown
https://git.kernel.org/netdev/net/c/b38cae85d1c4
- [net,2/2] net: ethernet: mtk_eth_soc: Fix use-after-free in metadata dst teardown
https://git.kernel.org/netdev/net/c/80df409e1a48
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH net 1/2] net: airoha: Fix use-after-free in metadata dst teardown
2026-06-02 9:21 ` [PATCH net 1/2] net: airoha: Fix use-after-free in metadata dst teardown Lorenzo Bianconi
@ 2026-06-04 17:38 ` Jacob Keller
2026-06-04 21:23 ` Lorenzo Bianconi
0 siblings, 1 reply; 7+ messages in thread
From: Jacob Keller @ 2026-06-04 17:38 UTC (permalink / raw)
To: Lorenzo Bianconi, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Felix Fietkau, Matthias Brugger,
AngeloGioacchino Del Regno
Cc: Florian Westphal, linux-arm-kernel, linux-mediatek, netdev
On 6/2/2026 2:21 AM, Lorenzo Bianconi wrote:
> airoha_metadata_dst_free() runs metadata_dst_free() which frees the
> metadata_dst with kfree() immediately, bypassing the RCU grace period.
> In the RX path, skb_dst_set_noref() sets a non-refcounted pointer from
> the skb to the metadata_dst. This function requires RCU read-side
> protection and the dst must remain valid until all RCU readers complete.
> Since metadata_dst_free() calls kfree() directly, an use-after-free can
> occur if any skb still holds a noref pointer to the dst when the driver
> tears it down.
> Replace metadata_dst_free() with dst_release() which properly goes
> through the refcount path: when the refcount drops to zero, it schedules
> the actual free via call_rcu_hurry(), ensuring all RCU readers have
> completed before the memory is freed.
>
> Fixes: af3cf757d5c9 ("net: airoha: Move DSA tag in DMA descriptor")
> Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
> ---
> drivers/net/ethernet/airoha/airoha_eth.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c
> index cecd66251dba..eab6a98d62b9 100644
> --- a/drivers/net/ethernet/airoha/airoha_eth.c
> +++ b/drivers/net/ethernet/airoha/airoha_eth.c
> @@ -2936,7 +2936,7 @@ static void airoha_metadata_dst_free(struct airoha_gdm_port *port)
> if (!port->dsa_meta[i])
> continue;
>
> - metadata_dst_free(port->dsa_meta[i]);
> + dst_release(&port->dsa_meta[i]->dst);
> }
> }
>
>
the port->dsa_meta is allocated using metadata_dst_alloc().. how is it
safe to use dst_release here? Seems like we should be calling dst_alloc
instead of metadata_dst_alloc in order to use dst_release??
metadata_dst_alloc does call __metadata_dst_init which calls dst_init..
I guess the start of the metadata_dst structure is also the same address
as the internal dst_entry struct...
But dst_destroy does a whole lot more than metadata_dst_release so I
don't feel confident in this actually being a drop-in replacement... It
calls netdev_put, it calls the dst->ops->destroy, it releases child
refs.. Or for metadata dst entries is that all basically a no-op??
I feel like I'm missing something here.. The driver also calls
metadata_dst_free in the remove path and that wasn't changed by this
patch either.
Generally it seems like we should be using the same API to allocate as
to release the object... This is confusing. What am I missing?
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH net 1/2] net: airoha: Fix use-after-free in metadata dst teardown
2026-06-04 17:38 ` Jacob Keller
@ 2026-06-04 21:23 ` Lorenzo Bianconi
2026-06-04 21:53 ` Jacob Keller
0 siblings, 1 reply; 7+ messages in thread
From: Lorenzo Bianconi @ 2026-06-04 21:23 UTC (permalink / raw)
To: Jacob Keller
Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Felix Fietkau, Matthias Brugger,
AngeloGioacchino Del Regno, Florian Westphal, linux-arm-kernel,
linux-mediatek, netdev
[-- Attachment #1: Type: text/plain, Size: 3295 bytes --]
> On 6/2/2026 2:21 AM, Lorenzo Bianconi wrote:
> > airoha_metadata_dst_free() runs metadata_dst_free() which frees the
> > metadata_dst with kfree() immediately, bypassing the RCU grace period.
> > In the RX path, skb_dst_set_noref() sets a non-refcounted pointer from
> > the skb to the metadata_dst. This function requires RCU read-side
> > protection and the dst must remain valid until all RCU readers complete.
> > Since metadata_dst_free() calls kfree() directly, an use-after-free can
> > occur if any skb still holds a noref pointer to the dst when the driver
> > tears it down.
> > Replace metadata_dst_free() with dst_release() which properly goes
> > through the refcount path: when the refcount drops to zero, it schedules
> > the actual free via call_rcu_hurry(), ensuring all RCU readers have
> > completed before the memory is freed.
> >
> > Fixes: af3cf757d5c9 ("net: airoha: Move DSA tag in DMA descriptor")
> > Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
> > ---
> > drivers/net/ethernet/airoha/airoha_eth.c | 2 +-
> > 1 file changed, 1 insertion(+), 1 deletion(-)
> >
> > diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c
> > index cecd66251dba..eab6a98d62b9 100644
> > --- a/drivers/net/ethernet/airoha/airoha_eth.c
> > +++ b/drivers/net/ethernet/airoha/airoha_eth.c
> > @@ -2936,7 +2936,7 @@ static void airoha_metadata_dst_free(struct airoha_gdm_port *port)
> > if (!port->dsa_meta[i])
> > continue;
> >
> > - metadata_dst_free(port->dsa_meta[i]);
> > + dst_release(&port->dsa_meta[i]->dst);
> > }
> > }
> >
> >
>
> the port->dsa_meta is allocated using metadata_dst_alloc().. how is it
> safe to use dst_release here? Seems like we should be calling dst_alloc
> instead of metadata_dst_alloc in order to use dst_release??
We need to allocate the metadata_dst using metadata_dst_alloc() since
md_dst->u.port_info.port_id is consumed in dsa_switch_rcv() to get the
switch conduit port.
I guess it is fine to free metadata_dst running dst_release() since dst_init()
sets DST_METADATA flag and so dst_destroy() runs metadata_dst_free() after the
RCU grace period.
>
> metadata_dst_alloc does call __metadata_dst_init which calls dst_init..
>
> I guess the start of the metadata_dst structure is also the same address
> as the internal dst_entry struct...
>
> But dst_destroy does a whole lot more than metadata_dst_release so I
> don't feel confident in this actually being a drop-in replacement... It
> calls netdev_put, it calls the dst->ops->destroy, it releases child
> refs.. Or for metadata dst entries is that all basically a no-op??
__metadata_dst_init() calls dst_init() with dev = NULL so netdev_put() is a
no-op. Same for dst->ops is dst_blackhole_ops and and dst_blackhole_ops has no
destroy callback.
>
> I feel like I'm missing something here.. The driver also calls
> metadata_dst_free in the remove path and that wasn't changed by this
> patch either.
can you please explain what you mean here? we do not run metadata_dst_free()
anymore.
Regards,
Lorenzo
>
> Generally it seems like we should be using the same API to allocate as
> to release the object... This is confusing. What am I missing?
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH net 1/2] net: airoha: Fix use-after-free in metadata dst teardown
2026-06-04 21:23 ` Lorenzo Bianconi
@ 2026-06-04 21:53 ` Jacob Keller
0 siblings, 0 replies; 7+ messages in thread
From: Jacob Keller @ 2026-06-04 21:53 UTC (permalink / raw)
To: Lorenzo Bianconi
Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Felix Fietkau, Matthias Brugger,
AngeloGioacchino Del Regno, Florian Westphal, linux-arm-kernel,
linux-mediatek, netdev
On 6/4/2026 2:23 PM, Lorenzo Bianconi wrote:
>> On 6/2/2026 2:21 AM, Lorenzo Bianconi wrote:
>>> airoha_metadata_dst_free() runs metadata_dst_free() which frees the
>>> metadata_dst with kfree() immediately, bypassing the RCU grace period.
>>> In the RX path, skb_dst_set_noref() sets a non-refcounted pointer from
>>> the skb to the metadata_dst. This function requires RCU read-side
>>> protection and the dst must remain valid until all RCU readers complete.
>>> Since metadata_dst_free() calls kfree() directly, an use-after-free can
>>> occur if any skb still holds a noref pointer to the dst when the driver
>>> tears it down.
>>> Replace metadata_dst_free() with dst_release() which properly goes
>>> through the refcount path: when the refcount drops to zero, it schedules
>>> the actual free via call_rcu_hurry(), ensuring all RCU readers have
>>> completed before the memory is freed.
>>>
>>> Fixes: af3cf757d5c9 ("net: airoha: Move DSA tag in DMA descriptor")
>>> Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
>>> ---
>>> drivers/net/ethernet/airoha/airoha_eth.c | 2 +-
>>> 1 file changed, 1 insertion(+), 1 deletion(-)
>>>
>>> diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c
>>> index cecd66251dba..eab6a98d62b9 100644
>>> --- a/drivers/net/ethernet/airoha/airoha_eth.c
>>> +++ b/drivers/net/ethernet/airoha/airoha_eth.c
>>> @@ -2936,7 +2936,7 @@ static void airoha_metadata_dst_free(struct airoha_gdm_port *port)
>>> if (!port->dsa_meta[i])
>>> continue;
>>>
>>> - metadata_dst_free(port->dsa_meta[i]);
>>> + dst_release(&port->dsa_meta[i]->dst);
>>> }
>>> }
>>>
>>>
>>
>> the port->dsa_meta is allocated using metadata_dst_alloc().. how is it
>> safe to use dst_release here? Seems like we should be calling dst_alloc
>> instead of metadata_dst_alloc in order to use dst_release??
>
> We need to allocate the metadata_dst using metadata_dst_alloc() since
> md_dst->u.port_info.port_id is consumed in dsa_switch_rcv() to get the
> switch conduit port.
> I guess it is fine to free metadata_dst running dst_release() since dst_init()
> sets DST_METADATA flag and so dst_destroy() runs metadata_dst_free() after the
> RCU grace period.
>
Ok. So when would any flow need to call metadata_dst_free()? I guess
some path might happen to know that its already past RCU grace period
for all accesses or something...
I guess mostly my brain would be less confused if we had
metadata_dst_free() call dst_destroy or have a metadata_dst_release() or
something to make the two sides of the naming match... but I guess thats
really just noise on top of the API, since it doesn't really add any value.
Thanks for the explanation and helping un-confuse me at least a little!
>>
>> metadata_dst_alloc does call __metadata_dst_init which calls dst_init..
>>
>> I guess the start of the metadata_dst structure is also the same address
>> as the internal dst_entry struct...
>>
>> But dst_destroy does a whole lot more than metadata_dst_release so I
>> don't feel confident in this actually being a drop-in replacement... It
>> calls netdev_put, it calls the dst->ops->destroy, it releases child
>> refs.. Or for metadata dst entries is that all basically a no-op??
>
> __metadata_dst_init() calls dst_init() with dev = NULL so netdev_put() is a
> no-op. Same for dst->ops is dst_blackhole_ops and and dst_blackhole_ops has no
> destroy callback.
>
Ok. So basically its correct, it just looks odd because the code is
re-used by several other flows.
>>
>> I feel like I'm missing something here.. The driver also calls
>> metadata_dst_free in the remove path and that wasn't changed by this
>> patch either.
>
> can you please explain what you mean here? we do not run metadata_dst_free()
> anymore.
>
I might have been mistaken. I did a search for metadata_dst_free() in
the driver and I think I confused the airoha_metadata_dst_free() call
site while scanning the code.
All of that said, thanks for a quick response and now that I understand
it makes sense:
Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
Regards,
Jake
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2026-06-04 21:53 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-02 9:21 [PATCH net 0/2] Fix use-after-free in metadata dst teardown in airoha_eth and mtk_eth_soc drivers Lorenzo Bianconi
2026-06-02 9:21 ` [PATCH net 1/2] net: airoha: Fix use-after-free in metadata dst teardown Lorenzo Bianconi
2026-06-04 17:38 ` Jacob Keller
2026-06-04 21:23 ` Lorenzo Bianconi
2026-06-04 21:53 ` Jacob Keller
2026-06-02 9:21 ` [PATCH net 2/2] net: ethernet: mtk_eth_soc: " Lorenzo Bianconi
2026-06-04 2:30 ` [PATCH net 0/2] Fix use-after-free in metadata dst teardown in airoha_eth and mtk_eth_soc drivers patchwork-bot+netdevbpf
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox