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

ipv6: adopt skb_dst_dev() and skb_dst_dev_net[_rcu]() helpers



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

v2: fix typo in ipv6_rthdr_rcv() (kernel test robot <lkp@intel.com>)

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


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 1caf2729
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -150,7 +150,7 @@ static inline struct sock *__inet6_lookup_skb(struct inet_hashinfo *hashinfo,
					      int iif, 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 ipv6hdr *ip6h = ipv6_hdr(skb);
	struct sock *sk;

+1 −1
Original line number Diff line number Diff line
@@ -159,7 +159,7 @@ static inline void ip6tunnel_xmit(struct sock *sk, struct sk_buff *skb,
	memset(skb->cb, 0, sizeof(struct inet6_skb_parm));
	IP6CB(skb)->flags = ip6cb_flags;
	pkt_len = skb->len - skb_inner_network_offset(skb);
	err = ip6_local_out(dev_net(skb_dst(skb)->dev), sk, skb);
	err = ip6_local_out(skb_dst_dev_net(skb), sk, skb);

	if (dev) {
		if (unlikely(net_xmit_eval(err)))
+4 −4
Original line number Diff line number Diff line
@@ -460,7 +460,7 @@ static int ipv6_srh_rcv(struct sk_buff *skb)
		return -1;
	}

	if (skb_dst(skb)->dev->flags & IFF_LOOPBACK) {
	if (skb_dst_dev(skb)->flags & IFF_LOOPBACK) {
		if (ipv6_hdr(skb)->hop_limit <= 1) {
			__IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS);
			icmpv6_send(skb, ICMPV6_TIME_EXCEED,
@@ -621,7 +621,7 @@ static int ipv6_rpl_srh_rcv(struct sk_buff *skb)
		return -1;
	}

	if (skb_dst(skb)->dev->flags & IFF_LOOPBACK) {
	if (skb_dst_dev(skb)->flags & IFF_LOOPBACK) {
		if (ipv6_hdr(skb)->hop_limit <= 1) {
			__IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS);
			icmpv6_send(skb, ICMPV6_TIME_EXCEED,
@@ -783,7 +783,7 @@ static int ipv6_rthdr_rcv(struct sk_buff *skb)
			kfree_skb(skb);
			return -1;
		}
		if (!ipv6_chk_home_addr(dev_net(skb_dst(skb)->dev), addr)) {
		if (!ipv6_chk_home_addr(skb_dst_dev_net(skb), addr)) {
			__IP6_INC_STATS(net, idev, IPSTATS_MIB_INADDRERRORS);
			kfree_skb(skb);
			return -1;
@@ -809,7 +809,7 @@ static int ipv6_rthdr_rcv(struct sk_buff *skb)
		return -1;
	}

	if (skb_dst(skb)->dev->flags&IFF_LOOPBACK) {
	if (skb_dst_dev(skb)->flags & IFF_LOOPBACK) {
		if (ipv6_hdr(skb)->hop_limit <= 1) {
			__IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS);
			icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT,
+9 −8
Original line number Diff line number Diff line
@@ -696,6 +696,7 @@ static void __ioam6_fill_trace_data(struct sk_buff *skb,
				    struct ioam6_schema *sc,
				    u8 sclen, bool is_input)
{
	struct net_device *dev = skb_dst_dev(skb);
	struct timespec64 ts;
	ktime_t tstamp;
	u64 raw64;
@@ -712,7 +713,7 @@ static void __ioam6_fill_trace_data(struct sk_buff *skb,
		if (is_input)
			byte--;

		raw32 = dev_net(skb_dst(skb)->dev)->ipv6.sysctl.ioam6_id;
		raw32 = dev_net(dev)->ipv6.sysctl.ioam6_id;

		*(__be32 *)data = cpu_to_be32((byte << 24) | raw32);
		data += sizeof(__be32);
@@ -728,10 +729,10 @@ static void __ioam6_fill_trace_data(struct sk_buff *skb,
		*(__be16 *)data = cpu_to_be16(raw16);
		data += sizeof(__be16);

		if (skb_dst(skb)->dev->flags & IFF_LOOPBACK)
		if (dev->flags & IFF_LOOPBACK)
			raw16 = IOAM6_U16_UNAVAILABLE;
		else
			raw16 = (__force u16)READ_ONCE(__in6_dev_get(skb_dst(skb)->dev)->cnf.ioam6_id);
			raw16 = (__force u16)READ_ONCE(__in6_dev_get(dev)->cnf.ioam6_id);

		*(__be16 *)data = cpu_to_be16(raw16);
		data += sizeof(__be16);
@@ -783,10 +784,10 @@ static void __ioam6_fill_trace_data(struct sk_buff *skb,
		struct Qdisc *qdisc;
		__u32 qlen, backlog;

		if (skb_dst(skb)->dev->flags & IFF_LOOPBACK) {
		if (dev->flags & IFF_LOOPBACK) {
			*(__be32 *)data = cpu_to_be32(IOAM6_U32_UNAVAILABLE);
		} else {
			queue = skb_get_tx_queue(skb_dst(skb)->dev, skb);
			queue = skb_get_tx_queue(dev, skb);
			qdisc = rcu_dereference(queue->qdisc);
			qdisc_qstats_qlen_backlog(qdisc, &qlen, &backlog);

@@ -807,7 +808,7 @@ static void __ioam6_fill_trace_data(struct sk_buff *skb,
		if (is_input)
			byte--;

		raw64 = dev_net(skb_dst(skb)->dev)->ipv6.sysctl.ioam6_id_wide;
		raw64 = dev_net(dev)->ipv6.sysctl.ioam6_id_wide;

		*(__be64 *)data = cpu_to_be64(((u64)byte << 56) | raw64);
		data += sizeof(__be64);
@@ -823,10 +824,10 @@ static void __ioam6_fill_trace_data(struct sk_buff *skb,
		*(__be32 *)data = cpu_to_be32(raw32);
		data += sizeof(__be32);

		if (skb_dst(skb)->dev->flags & IFF_LOOPBACK)
		if (dev->flags & IFF_LOOPBACK)
			raw32 = IOAM6_U32_UNAVAILABLE;
		else
			raw32 = READ_ONCE(__in6_dev_get(skb_dst(skb)->dev)->cnf.ioam6_id_wide);
			raw32 = READ_ONCE(__in6_dev_get(dev)->cnf.ioam6_id_wide);

		*(__be32 *)data = cpu_to_be32(raw32);
		data += sizeof(__be32);
+4 −2
Original line number Diff line number Diff line
@@ -187,7 +187,9 @@ static struct sk_buff *ip6_rcv_core(struct sk_buff *skb, struct net_device *dev,
	 * arrived via the sending interface (ethX), because of the
	 * nature of scoping architecture. --yoshfuji
	 */
	IP6CB(skb)->iif = skb_valid_dst(skb) ? ip6_dst_idev(skb_dst(skb))->dev->ifindex : dev->ifindex;
	IP6CB(skb)->iif = skb_valid_dst(skb) ?
				ip6_dst_idev(skb_dst(skb))->dev->ifindex :
				dev->ifindex;

	if (unlikely(!pskb_may_pull(skb, sizeof(*hdr))))
		goto err;
@@ -504,7 +506,7 @@ int ip6_mc_input(struct sk_buff *skb)
	struct net_device *dev;
	bool deliver;

	__IP6_UPD_PO_STATS(dev_net(skb_dst(skb)->dev),
	__IP6_UPD_PO_STATS(skb_dst_dev_net(skb),
			 __in6_dev_get_safely(skb->dev), IPSTATS_MIB_INMCAST,
			 skb->len);

Loading