Commit 3da81cb9 authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files

Merge branch 'net-first-round-to-use-dev_net_rcu'

Eric Dumazet says:

====================
net: first round to use dev_net_rcu()

dev_net(dev) should either be protected by RTNL or RCU.

There is no LOCKDEP support yet for this helper.

Adding it would trigger too many splats.

Instead, add dev_net_rcu() for rcu_read_lock() contexts
and start to use it to fix bugs and clearly document the
safety requirements.

v4: https://lore.kernel.org/CANn89i+AozhFhZNK0Y4e_EqXV1=yKjGuvf43Wa6JJKWMOixWQQ@mail.gmail.com
v3: https://lore.kernel.org/20250203153633.46ce0337@kernel.org/
====================

Link: https://patch.msgid.link/20250205155120.1676781-1-edumazet@google.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 3cf0a98f b768294d
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -2663,6 +2663,12 @@ struct net *dev_net(const struct net_device *dev)
	return read_pnet(&dev->nd_net);
}

static inline
struct net *dev_net_rcu(const struct net_device *dev)
{
	return read_pnet_rcu(&dev->nd_net);
}

static inline
void dev_net_set(struct net_device *dev, struct net *net)
{
+10 −3
Original line number Diff line number Diff line
@@ -471,9 +471,12 @@ static inline unsigned int ip_dst_mtu_maybe_forward(const struct dst_entry *dst,
						    bool forwarding)
{
	const struct rtable *rt = dst_rtable(dst);
	struct net *net = dev_net(dst->dev);
	unsigned int mtu;
	unsigned int mtu, res;
	struct net *net;

	rcu_read_lock();

	net = dev_net_rcu(dst->dev);
	if (READ_ONCE(net->ipv4.sysctl_ip_fwd_use_pmtu) ||
	    ip_mtu_locked(dst) ||
	    !forwarding) {
@@ -497,7 +500,11 @@ static inline unsigned int ip_dst_mtu_maybe_forward(const struct dst_entry *dst,
out:
	mtu = min_t(unsigned int, mtu, IP_MAX_MTU);

	return mtu - lwtunnel_headroom(dst->lwtstate, mtu);
	res = mtu - lwtunnel_headroom(dst->lwtstate, mtu);

	rcu_read_unlock();

	return res;
}

static inline unsigned int ip_skb_dst_mtu(struct sock *sk,
+1 −1
Original line number Diff line number Diff line
@@ -398,7 +398,7 @@ static inline struct net *read_pnet(const possible_net_t *pnet)
#endif
}

static inline struct net *read_pnet_rcu(possible_net_t *pnet)
static inline struct net *read_pnet_rcu(const possible_net_t *pnet)
{
#ifdef CONFIG_NET_NS
	return rcu_dereference(pnet->net);
+7 −2
Original line number Diff line number Diff line
@@ -382,10 +382,15 @@ static inline int inet_iif(const struct sk_buff *skb)
static inline int ip4_dst_hoplimit(const struct dst_entry *dst)
{
	int hoplimit = dst_metric_raw(dst, RTAX_HOPLIMIT);
	struct net *net = dev_net(dst->dev);

	if (hoplimit == 0)
	if (hoplimit == 0) {
		const struct net *net;

		rcu_read_lock();
		net = dev_net_rcu(dst->dev);
		hoplimit = READ_ONCE(net->ipv4.sysctl_ip_default_ttl);
		rcu_read_unlock();
	}
	return hoplimit;
}

+11 −10
Original line number Diff line number Diff line
@@ -1108,10 +1108,12 @@ bool __skb_flow_dissect(const struct net *net,
					      FLOW_DISSECTOR_KEY_BASIC,
					      target_container);

	rcu_read_lock();

	if (skb) {
		if (!net) {
			if (skb->dev)
				net = dev_net(skb->dev);
				net = dev_net_rcu(skb->dev);
			else if (skb->sk)
				net = sock_net(skb->sk);
		}
@@ -1122,7 +1124,6 @@ bool __skb_flow_dissect(const struct net *net,
		enum netns_bpf_attach_type type = NETNS_BPF_FLOW_DISSECTOR;
		struct bpf_prog_array *run_array;

		rcu_read_lock();
		run_array = rcu_dereference(init_net.bpf.run_array[type]);
		if (!run_array)
			run_array = rcu_dereference(net->bpf.run_array[type]);
@@ -1150,16 +1151,16 @@ bool __skb_flow_dissect(const struct net *net,
			prog = READ_ONCE(run_array->items[0].prog);
			result = bpf_flow_dissect(prog, &ctx, n_proto, nhoff,
						  hlen, flags);
			if (result == BPF_FLOW_DISSECTOR_CONTINUE)
				goto dissect_continue;
			if (result != BPF_FLOW_DISSECTOR_CONTINUE) {
				__skb_flow_bpf_to_target(&flow_keys, flow_dissector,
							 target_container);
				rcu_read_unlock();
				return result == BPF_OK;
			}
dissect_continue:
		rcu_read_unlock();
		}
	}

	rcu_read_unlock();

	if (dissector_uses_key(flow_dissector,
			       FLOW_DISSECTOR_KEY_ETH_ADDRS)) {
Loading