This is a note to let you know that I've just added the patch titled net: fix a memleak when uncloning an skb dst and its metadata to the 4.9-stable tree which can be found at: http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary The filename of the patch is: net-fix-a-memleak-when-uncloning-an-skb-dst-and-its-.patch and it can be found in the queue-4.9 subdirectory. If you, or anyone else, feels it should not be added to the stable tree, please let <stable@xxxxxxxxxxxxxxx> know about it. commit 3b5e08d1761978ba8e8fe6bdae407f1640be7ebd Author: Antoine Tenart <atenart@xxxxxxxxxx> Date: Mon Feb 7 18:13:19 2022 +0100 net: fix a memleak when uncloning an skb dst and its metadata [ Upstream commit 9eeabdf17fa0ab75381045c867c370f4cc75a613 ] When uncloning an skb dst and its associated metadata, a new dst+metadata is allocated and later replaces the old one in the skb. This is helpful to have a non-shared dst+metadata attached to a specific skb. The issue is the uncloned dst+metadata is initialized with a refcount of 1, which is increased to 2 before attaching it to the skb. When tun_dst_unclone returns, the dst+metadata is only referenced from a single place (the skb) while its refcount is 2. Its refcount will never drop to 0 (when the skb is consumed), leading to a memory leak. Fix this by removing the call to dst_hold in tun_dst_unclone, as the dst+metadata refcount is already 1. Fixes: fc4099f17240 ("openvswitch: Fix egress tunnel info.") Cc: Pravin B Shelar <pshelar@xxxxxxx> Reported-by: Vlad Buslov <vladbu@xxxxxxxxxx> Tested-by: Vlad Buslov <vladbu@xxxxxxxxxx> Signed-off-by: Antoine Tenart <atenart@xxxxxxxxxx> Signed-off-by: David S. Miller <davem@xxxxxxxxxxxxx> Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx> diff --git a/include/net/dst_metadata.h b/include/net/dst_metadata.h index 33ca53057f318..6a6f1d3bf8538 100644 --- a/include/net/dst_metadata.h +++ b/include/net/dst_metadata.h @@ -111,7 +111,6 @@ static inline struct metadata_dst *tun_dst_unclone(struct sk_buff *skb) #endif skb_dst_drop(skb); - dst_hold(&new_md->dst); skb_dst_set(skb, &new_md->dst); return new_md; }