summaryrefslogtreecommitdiff
path: root/include/linux
diff options
context:
space:
mode:
authorStanislav Fomichev <sdf@fomichev.me>2025-08-18 18:40:26 +0300
committerSasha Levin <sashal@kernel.org>2026-03-04 15:19:53 +0300
commit31ca4fbf56d1007b4dd57a0e1790fae75c9fbf4f (patch)
tree624197097480c4a773ef6023e9555aba59f70a0e /include/linux
parentdea1465394fff73c4c1636bb6c764b3889c1a7d6 (diff)
downloadlinux-31ca4fbf56d1007b4dd57a0e1790fae75c9fbf4f.tar.xz
net: Add skb_dstref_steal and skb_dstref_restore
[ Upstream commit c3f0c02997c7f8489fec259e28e0e04e9811edac ] Going forward skb_dst_set will assert that skb dst_entry is empty during skb_dst_set to prevent potential leaks. There are few places that still manually manage dst_entry not using the helpers. Convert them to the following new helpers: - skb_dstref_steal that resets dst_entry and returns previous dst_entry value - skb_dstref_restore that restores dst_entry previously reset via skb_dstref_steal Signed-off-by: Stanislav Fomichev <sdf@fomichev.me> Link: https://patch.msgid.link/20250818154032.3173645-2-sdf@fomichev.me Signed-off-by: Jakub Kicinski <kuba@kernel.org> Stable-dep-of: 81b84de32bb2 ("xfrm: fix ip_rt_bug race in icmp_route_lookup reverse path") Signed-off-by: Sasha Levin <sashal@kernel.org>
Diffstat (limited to 'include/linux')
-rw-r--r--include/linux/skbuff.h32
1 files changed, 32 insertions, 0 deletions
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 69b392dc10aa..1a91645fa249 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -1123,6 +1123,38 @@ static inline struct dst_entry *skb_dst(const struct sk_buff *skb)
}
/**
+ * skb_dstref_steal() - return current dst_entry value and clear it
+ * @skb: buffer
+ *
+ * Resets skb dst_entry without adjusting its reference count. Useful in
+ * cases where dst_entry needs to be temporarily reset and restored.
+ * Note that the returned value cannot be used directly because it
+ * might contain SKB_DST_NOREF bit.
+ *
+ * When in doubt, prefer skb_dst_drop() over skb_dstref_steal() to correctly
+ * handle dst_entry reference counting.
+ *
+ * Returns: original skb dst_entry.
+ */
+static inline unsigned long skb_dstref_steal(struct sk_buff *skb)
+{
+ unsigned long refdst = skb->_skb_refdst;
+
+ skb->_skb_refdst = 0;
+ return refdst;
+}
+
+/**
+ * skb_dstref_restore() - restore skb dst_entry removed via skb_dstref_steal()
+ * @skb: buffer
+ * @refdst: dst entry from a call to skb_dstref_steal()
+ */
+static inline void skb_dstref_restore(struct sk_buff *skb, unsigned long refdst)
+{
+ skb->_skb_refdst = refdst;
+}
+
+/**
* skb_dst_set - sets skb dst
* @skb: buffer
* @dst: dst entry