mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-12-27 10:01:39 -05:00
net: Switch to skb_dstref_steal/skb_dstref_restore for ip_route_input callers
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. skb_dstref_restore should be used to restore the previous entry. Convert icmp_route_lookup and ip_options_rcv_srr to these helpers. Add extra call to skb_dstref_reset to icmp_route_lookup to clear the ip_route_input entry. Signed-off-by: Stanislav Fomichev <sdf@fomichev.me> Link: https://patch.msgid.link/20250818154032.3173645-5-sdf@fomichev.me Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
committed by
Jakub Kicinski
parent
15488d4d8d
commit
e97e6a1830
@@ -544,14 +544,15 @@ static struct rtable *icmp_route_lookup(struct net *net, struct flowi4 *fl4,
|
||||
goto relookup_failed;
|
||||
}
|
||||
/* Ugh! */
|
||||
orefdst = skb_in->_skb_refdst; /* save old refdst */
|
||||
skb_dst_set(skb_in, NULL);
|
||||
orefdst = skb_dstref_steal(skb_in);
|
||||
err = ip_route_input(skb_in, fl4_dec.daddr, fl4_dec.saddr,
|
||||
dscp, rt2->dst.dev) ? -EINVAL : 0;
|
||||
|
||||
dst_release(&rt2->dst);
|
||||
rt2 = skb_rtable(skb_in);
|
||||
skb_in->_skb_refdst = orefdst; /* restore old refdst */
|
||||
/* steal dst entry from skb_in, don't drop refcnt */
|
||||
skb_dstref_steal(skb_in);
|
||||
skb_dstref_restore(skb_in, orefdst);
|
||||
}
|
||||
|
||||
if (err)
|
||||
|
||||
@@ -615,14 +615,13 @@ int ip_options_rcv_srr(struct sk_buff *skb, struct net_device *dev)
|
||||
}
|
||||
memcpy(&nexthop, &optptr[srrptr-1], 4);
|
||||
|
||||
orefdst = skb->_skb_refdst;
|
||||
skb_dst_set(skb, NULL);
|
||||
orefdst = skb_dstref_steal(skb);
|
||||
err = ip_route_input(skb, nexthop, iph->saddr, ip4h_dscp(iph),
|
||||
dev) ? -EINVAL : 0;
|
||||
rt2 = skb_rtable(skb);
|
||||
if (err || (rt2->rt_type != RTN_UNICAST && rt2->rt_type != RTN_LOCAL)) {
|
||||
skb_dst_drop(skb);
|
||||
skb->_skb_refdst = orefdst;
|
||||
skb_dstref_restore(skb, orefdst);
|
||||
return -EINVAL;
|
||||
}
|
||||
refdst_drop(orefdst);
|
||||
|
||||
Reference in New Issue
Block a user