Skip to content

Commit 6ad8de3

Browse files
edumazetkuba-moo
authored andcommitted
ipv4: start using dst_dev_rcu()
Change icmpv4_xrlim_allow(), ip_defrag() to prevent possible UAF. Change ipmr_prepare_xmit(), ipmr_queue_fwd_xmit(), ip_mr_output(), ipv4_neigh_lookup() to use lockdep enabled dst_dev_rcu(). Fixes: 4a6ce2b ("net: introduce a new function dst_dev_put()") Signed-off-by: Eric Dumazet <[email protected]> Reviewed-by: David Ahern <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent b62a59c commit 6ad8de3

File tree

4 files changed

+12
-10
lines changed

4 files changed

+12
-10
lines changed

net/ipv4/icmp.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -319,17 +319,17 @@ static bool icmpv4_xrlim_allow(struct net *net, struct rtable *rt,
319319
return true;
320320

321321
/* No rate limit on loopback */
322-
dev = dst_dev(dst);
322+
rcu_read_lock();
323+
dev = dst_dev_rcu(dst);
323324
if (dev && (dev->flags & IFF_LOOPBACK))
324325
goto out;
325326

326-
rcu_read_lock();
327327
peer = inet_getpeer_v4(net->ipv4.peers, fl4->daddr,
328328
l3mdev_master_ifindex_rcu(dev));
329329
rc = inet_peer_xrlim_allow(peer,
330330
READ_ONCE(net->ipv4.sysctl_icmp_ratelimit));
331-
rcu_read_unlock();
332331
out:
332+
rcu_read_unlock();
333333
if (!rc)
334334
__ICMP_INC_STATS(net, ICMP_MIB_RATELIMITHOST);
335335
else

net/ipv4/ip_fragment.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -476,14 +476,16 @@ static int ip_frag_reasm(struct ipq *qp, struct sk_buff *skb,
476476
/* Process an incoming IP datagram fragment. */
477477
int ip_defrag(struct net *net, struct sk_buff *skb, u32 user)
478478
{
479-
struct net_device *dev = skb->dev ? : skb_dst_dev(skb);
480-
int vif = l3mdev_master_ifindex_rcu(dev);
479+
struct net_device *dev;
481480
struct ipq *qp;
481+
int vif;
482482

483483
__IP_INC_STATS(net, IPSTATS_MIB_REASMREQDS);
484484

485485
/* Lookup (or create) queue header */
486486
rcu_read_lock();
487+
dev = skb->dev ? : skb_dst_dev_rcu(skb);
488+
vif = l3mdev_master_ifindex_rcu(dev);
487489
qp = ip_find(net, ip_hdr(skb), user, vif);
488490
if (qp) {
489491
int ret, refs = 0;

net/ipv4/ipmr.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1905,7 +1905,7 @@ static int ipmr_prepare_xmit(struct net *net, struct mr_table *mrt,
19051905
return -1;
19061906
}
19071907

1908-
encap += LL_RESERVED_SPACE(rt->dst.dev) + rt->dst.header_len;
1908+
encap += LL_RESERVED_SPACE(dst_dev_rcu(&rt->dst)) + rt->dst.header_len;
19091909

19101910
if (skb_cow(skb, encap)) {
19111911
ip_rt_put(rt);
@@ -1958,7 +1958,7 @@ static void ipmr_queue_fwd_xmit(struct net *net, struct mr_table *mrt,
19581958
* result in receiving multiple packets.
19591959
*/
19601960
NF_HOOK(NFPROTO_IPV4, NF_INET_FORWARD,
1961-
net, NULL, skb, skb->dev, rt->dst.dev,
1961+
net, NULL, skb, skb->dev, dst_dev_rcu(&rt->dst),
19621962
ipmr_forward_finish);
19631963
return;
19641964

@@ -2302,7 +2302,7 @@ int ip_mr_output(struct net *net, struct sock *sk, struct sk_buff *skb)
23022302

23032303
guard(rcu)();
23042304

2305-
dev = rt->dst.dev;
2305+
dev = dst_dev_rcu(&rt->dst);
23062306

23072307
if (IPCB(skb)->flags & IPSKB_FORWARDED)
23082308
goto mc_output;

net/ipv4/route.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -414,11 +414,11 @@ static struct neighbour *ipv4_neigh_lookup(const struct dst_entry *dst,
414414
const void *daddr)
415415
{
416416
const struct rtable *rt = container_of(dst, struct rtable, dst);
417-
struct net_device *dev = dst_dev(dst);
417+
struct net_device *dev;
418418
struct neighbour *n;
419419

420420
rcu_read_lock();
421-
421+
dev = dst_dev_rcu(dst);
422422
if (likely(rt->rt_gw_family == AF_INET)) {
423423
n = ip_neigh_gw4(dev, rt->rt_gw4);
424424
} else if (rt->rt_gw_family == AF_INET6) {

0 commit comments

Comments
 (0)