Commit a74fc62e authored by Eric Dumazet's avatar Eric Dumazet Committed by Jakub Kicinski
Browse files

ipv4: adopt dst_dev, skb_dst_dev and skb_dst_dev_net[_rcu]



Use the new helpers as a first step to deal with
potential dst->dev races.

Signed-off-by: default avatarEric Dumazet <edumazet@google.com>
Reviewed-by: default avatarKuniyuki Iwashima <kuniyu@google.com>
Link: https://patch.msgid.link/20250630121934.3399505-8-edumazet@google.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 88fe1425
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -481,7 +481,7 @@ static inline struct sock *__inet_lookup_skb(struct inet_hashinfo *hashinfo,
					     const int sdif,
					     bool *refcounted)
{
	struct net *net = dev_net_rcu(skb_dst(skb)->dev);
	struct net *net = skb_dst_dev_net_rcu(skb);
	const struct iphdr *iph = ip_hdr(skb);
	struct sock *sk;

+6 −5
Original line number Diff line number Diff line
@@ -472,7 +472,7 @@ static inline unsigned int ip_dst_mtu_maybe_forward(const struct dst_entry *dst,

	rcu_read_lock();

	net = dev_net_rcu(dst->dev);
	net = dev_net_rcu(dst_dev(dst));
	if (READ_ONCE(net->ipv4.sysctl_ip_fwd_use_pmtu) ||
	    ip_mtu_locked(dst) ||
	    !forwarding) {
@@ -486,7 +486,7 @@ static inline unsigned int ip_dst_mtu_maybe_forward(const struct dst_entry *dst,
	if (mtu)
		goto out;

	mtu = READ_ONCE(dst->dev->mtu);
	mtu = READ_ONCE(dst_dev(dst)->mtu);

	if (unlikely(ip_mtu_locked(dst))) {
		if (rt->rt_uses_gateway && mtu > 576)
@@ -506,16 +506,17 @@ static inline unsigned int ip_dst_mtu_maybe_forward(const struct dst_entry *dst,
static inline unsigned int ip_skb_dst_mtu(struct sock *sk,
					  const struct sk_buff *skb)
{
	const struct dst_entry *dst = skb_dst(skb);
	unsigned int mtu;

	if (!sk || !sk_fullsock(sk) || ip_sk_use_pmtu(sk)) {
		bool forwarding = IPCB(skb)->flags & IPSKB_FORWARDED;

		return ip_dst_mtu_maybe_forward(skb_dst(skb), forwarding);
		return ip_dst_mtu_maybe_forward(dst, forwarding);
	}

	mtu = min(READ_ONCE(skb_dst(skb)->dev->mtu), IP_MAX_MTU);
	return mtu - lwtunnel_headroom(skb_dst(skb)->lwtstate, mtu);
	mtu = min(READ_ONCE(dst_dev(dst)->mtu), IP_MAX_MTU);
	return mtu - lwtunnel_headroom(dst->lwtstate, mtu);
}

struct dst_metrics *ip_fib_metrics_init(struct nlattr *fc_mx, int fc_mx_len,
+1 −1
Original line number Diff line number Diff line
@@ -390,7 +390,7 @@ static inline int ip4_dst_hoplimit(const struct dst_entry *dst)
		const struct net *net;

		rcu_read_lock();
		net = dev_net_rcu(dst->dev);
		net = dev_net_rcu(dst_dev(dst));
		hoplimit = READ_ONCE(net->ipv4.sysctl_ip_default_ttl);
		rcu_read_unlock();
	}
+13 −11
Original line number Diff line number Diff line
@@ -311,18 +311,20 @@ static bool icmpv4_xrlim_allow(struct net *net, struct rtable *rt,
{
	struct dst_entry *dst = &rt->dst;
	struct inet_peer *peer;
	struct net_device *dev;
	bool rc = true;

	if (!apply_ratelimit)
		return true;

	/* No rate limit on loopback */
	if (dst->dev && (dst->dev->flags&IFF_LOOPBACK))
	dev = dst_dev(dst);
	if (dev && (dev->flags & IFF_LOOPBACK))
		goto out;

	rcu_read_lock();
	peer = inet_getpeer_v4(net->ipv4.peers, fl4->daddr,
			       l3mdev_master_ifindex_rcu(dst->dev));
			       l3mdev_master_ifindex_rcu(dev));
	rc = inet_peer_xrlim_allow(peer,
				   READ_ONCE(net->ipv4.sysctl_icmp_ratelimit));
	rcu_read_unlock();
@@ -466,13 +468,13 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb)
 */
static struct net_device *icmp_get_route_lookup_dev(struct sk_buff *skb)
{
	struct net_device *route_lookup_dev = NULL;
	struct net_device *dev = skb->dev;
	const struct dst_entry *dst;

	if (skb->dev)
		route_lookup_dev = skb->dev;
	else if (skb_dst(skb))
		route_lookup_dev = skb_dst(skb)->dev;
	return route_lookup_dev;
	if (dev)
		return dev;
	dst = skb_dst(skb);
	return dst ? dst_dev(dst) : NULL;
}

static struct rtable *icmp_route_lookup(struct net *net, struct flowi4 *fl4,
@@ -869,7 +871,7 @@ static enum skb_drop_reason icmp_unreach(struct sk_buff *skb)
	struct net *net;
	u32 info = 0;

	net = dev_net_rcu(skb_dst(skb)->dev);
	net = skb_dst_dev_net_rcu(skb);

	/*
	 *	Incomplete header ?
@@ -1012,7 +1014,7 @@ static enum skb_drop_reason icmp_echo(struct sk_buff *skb)
	struct icmp_bxm icmp_param;
	struct net *net;

	net = dev_net_rcu(skb_dst(skb)->dev);
	net = skb_dst_dev_net_rcu(skb);
	/* should there be an ICMP stat for ignored echos? */
	if (READ_ONCE(net->ipv4.sysctl_icmp_echo_ignore_all))
		return SKB_NOT_DROPPED_YET;
@@ -1182,7 +1184,7 @@ static enum skb_drop_reason icmp_timestamp(struct sk_buff *skb)
	return SKB_NOT_DROPPED_YET;

out_err:
	__ICMP_INC_STATS(dev_net_rcu(skb_dst(skb)->dev), ICMP_MIB_INERRORS);
	__ICMP_INC_STATS(skb_dst_dev_net_rcu(skb), ICMP_MIB_INERRORS);
	return SKB_DROP_REASON_PKT_TOO_SMALL;
}

+1 −1
Original line number Diff line number Diff line
@@ -427,7 +427,7 @@ static int igmpv3_sendpack(struct sk_buff *skb)

	pig->csum = ip_compute_csum(igmp_hdr(skb), igmplen);

	return ip_local_out(dev_net(skb_dst(skb)->dev), skb->sk, skb);
	return ip_local_out(skb_dst_dev_net(skb), skb->sk, skb);
}

static int grec_size(struct ip_mc_list *pmc, int type, int gdel, int sdel)
Loading