Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

xfrm: Switch to skb_dstref_steal to clear dst_entry

Going forward skb_dst_set will assert that skb dst_entry
is empty during skb_dst_set. skb_dstref_steal is added to reset
existing entry without doing refcnt. Switch to skb_dstref_steal
in __xfrm_route_forward and add a comment on why it's safe
to skip skb_dstref_restore.

Signed-off-by: Stanislav Fomichev <sdf@fomichev.me>
Link: https://patch.msgid.link/20250818154032.3173645-3-sdf@fomichev.me
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Stanislav Fomichev and committed by
Jakub Kicinski
c829aab2 c3f0c029

+8 -2
+8 -2
net/xfrm/xfrm_policy.c
··· 3881 3881 } 3882 3882 3883 3883 skb_dst_force(skb); 3884 - if (!skb_dst(skb)) { 3884 + dst = skb_dst(skb); 3885 + if (!dst) { 3885 3886 XFRM_INC_STATS(net, LINUX_MIB_XFRMFWDHDRERROR); 3886 3887 return 0; 3887 3888 } 3888 3889 3889 - dst = xfrm_lookup(net, skb_dst(skb), &fl, NULL, XFRM_LOOKUP_QUEUE); 3890 + /* ignore return value from skb_dstref_steal, xfrm_lookup takes 3891 + * care of dropping the refcnt if needed. 3892 + */ 3893 + skb_dstref_steal(skb); 3894 + 3895 + dst = xfrm_lookup(net, dst, &fl, NULL, XFRM_LOOKUP_QUEUE); 3890 3896 if (IS_ERR(dst)) { 3891 3897 res = 0; 3892 3898 dst = NULL;