Subject: Re: [PATCH net 1/2] net: airoha: Fix use-after-free in metadata dst teardown

From: Jacob Keller <[email-masked]>
Date: Thu, 4 Jun 2026 10:38:33 -0700

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 <[email-masked]>
> ---
>  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?