Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

ipv6: adopt dst_dev() helper

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

Signed-off-by: Eric Dumazet <edumazet@google.com>
Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
Link: https://patch.msgid.link/20250630121934.3399505-9-edumazet@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Eric Dumazet and committed by
Jakub Kicinski
1caf2729 a74fc62e

+60 -47
+2 -2
include/net/ip6_route.h
··· 274 274 unsigned int mtu; 275 275 276 276 if (np && READ_ONCE(np->pmtudisc) >= IPV6_PMTUDISC_PROBE) { 277 - mtu = READ_ONCE(dst->dev->mtu); 277 + mtu = READ_ONCE(dst_dev(dst)->mtu); 278 278 mtu -= lwtunnel_headroom(dst->lwtstate, mtu); 279 279 } else { 280 280 mtu = dst_mtu(dst); ··· 337 337 338 338 mtu = IPV6_MIN_MTU; 339 339 rcu_read_lock(); 340 - idev = __in6_dev_get(dst->dev); 340 + idev = __in6_dev_get(dst_dev(dst)); 341 341 if (idev) 342 342 mtu = READ_ONCE(idev->cnf.mtu6); 343 343 rcu_read_unlock();
+1 -1
net/ipv6/exthdrs.c
··· 306 306 if (!pskb_may_pull(skb, skb_transport_offset(skb) + 8) || 307 307 !pskb_may_pull(skb, (skb_transport_offset(skb) + 308 308 ((skb_transport_header(skb)[1] + 1) << 3)))) { 309 - __IP6_INC_STATS(dev_net(dst->dev), idev, 309 + __IP6_INC_STATS(dev_net(dst_dev(dst)), idev, 310 310 IPSTATS_MIB_INHDRERRORS); 311 311 fail_and_free: 312 312 kfree_skb(skb);
+3 -1
net/ipv6/icmp.c
··· 196 196 struct flowi6 *fl6, bool apply_ratelimit) 197 197 { 198 198 struct net *net = sock_net(sk); 199 + struct net_device *dev; 199 200 struct dst_entry *dst; 200 201 bool res = false; 201 202 ··· 209 208 * this lookup should be more aggressive (not longer than timeout). 210 209 */ 211 210 dst = ip6_route_output(net, sk, fl6); 211 + dev = dst_dev(dst); 212 212 if (dst->error) { 213 213 IP6_INC_STATS(net, ip6_dst_idev(dst), 214 214 IPSTATS_MIB_OUTNOROUTES); 215 - } else if (dst->dev && (dst->dev->flags&IFF_LOOPBACK)) { 215 + } else if (dev && (dev->flags & IFF_LOOPBACK)) { 216 216 res = true; 217 217 } else { 218 218 struct rt6_info *rt = dst_rt6_info(dst);
+1 -1
net/ipv6/ila/ila_lwt.c
··· 70 70 */ 71 71 72 72 memset(&fl6, 0, sizeof(fl6)); 73 - fl6.flowi6_oif = orig_dst->dev->ifindex; 73 + fl6.flowi6_oif = dst_dev(orig_dst)->ifindex; 74 74 fl6.flowi6_iif = LOOPBACK_IFINDEX; 75 75 fl6.daddr = *rt6_nexthop(dst_rt6_info(orig_dst), 76 76 &ip6h->daddr);
+2 -2
net/ipv6/ioam6_iptunnel.c
··· 335 335 if (has_tunsrc) 336 336 memcpy(&hdr->saddr, tunsrc, sizeof(*tunsrc)); 337 337 else 338 - ipv6_dev_get_saddr(net, dst->dev, &hdr->daddr, 338 + ipv6_dev_get_saddr(net, dst_dev(dst), &hdr->daddr, 339 339 IPV6_PREFER_SRC_PUBLIC, &hdr->saddr); 340 340 341 341 skb_postpush_rcsum(skb, hdr, len); ··· 442 442 dst_cache_set_ip6(&ilwt->cache, dst, &fl6.saddr); 443 443 local_bh_enable(); 444 444 445 - err = skb_cow_head(skb, LL_RESERVED_SPACE(dst->dev)); 445 + err = skb_cow_head(skb, LL_RESERVED_SPACE(dst_dev(dst))); 446 446 if (unlikely(err)) 447 447 goto drop; 448 448 }
+5 -3
net/ipv6/ip6_gre.c
··· 1085 1085 htonl(atomic_fetch_inc(&t->o_seqno))); 1086 1086 1087 1087 /* TooBig packet may have updated dst->dev's mtu */ 1088 - if (!t->parms.collect_md && dst && dst_mtu(dst) > dst->dev->mtu) 1089 - dst->ops->update_pmtu(dst, NULL, skb, dst->dev->mtu, false); 1090 - 1088 + if (!t->parms.collect_md && dst) { 1089 + mtu = READ_ONCE(dst_dev(dst)->mtu); 1090 + if (dst_mtu(dst) > mtu) 1091 + dst->ops->update_pmtu(dst, NULL, skb, mtu, false); 1092 + } 1091 1093 err = ip6_tnl_xmit(skb, dev, dsfield, &fl6, encap_limit, &mtu, 1092 1094 NEXTHDR_GRE); 1093 1095 if (err != 0) {
+10 -9
net/ipv6/ip6_output.c
··· 60 60 static int ip6_finish_output2(struct net *net, struct sock *sk, struct sk_buff *skb) 61 61 { 62 62 struct dst_entry *dst = skb_dst(skb); 63 - struct net_device *dev = dst->dev; 63 + struct net_device *dev = dst_dev(dst); 64 64 struct inet6_dev *idev = ip6_dst_idev(dst); 65 65 unsigned int hh_len = LL_RESERVED_SPACE(dev); 66 66 const struct in6_addr *daddr, *nexthop; ··· 271 271 const struct ipv6_pinfo *np = inet6_sk(sk); 272 272 struct in6_addr *first_hop = &fl6->daddr; 273 273 struct dst_entry *dst = skb_dst(skb); 274 - struct net_device *dev = dst->dev; 274 + struct net_device *dev = dst_dev(dst); 275 275 struct inet6_dev *idev = ip6_dst_idev(dst); 276 276 struct hop_jumbo_hdr *hop_jumbo; 277 277 int hoplen = sizeof(*hop_jumbo); ··· 503 503 struct dst_entry *dst = skb_dst(skb); 504 504 struct ipv6hdr *hdr = ipv6_hdr(skb); 505 505 struct inet6_skb_parm *opt = IP6CB(skb); 506 - struct net *net = dev_net(dst->dev); 506 + struct net *net = dev_net(dst_dev(dst)); 507 + struct net_device *dev; 507 508 struct inet6_dev *idev; 508 509 SKB_DR(reason); 509 510 u32 mtu; ··· 592 591 goto drop; 593 592 } 594 593 dst = skb_dst(skb); 595 - 594 + dev = dst_dev(dst); 596 595 /* IPv6 specs say nothing about it, but it is clear that we cannot 597 596 send redirects to source routed frames. 598 597 We don't send redirects to frames decapsulated from IPsec. 599 598 */ 600 - if (IP6CB(skb)->iif == dst->dev->ifindex && 599 + if (IP6CB(skb)->iif == dev->ifindex && 601 600 opt->srcrt == 0 && !skb_sec_path(skb)) { 602 601 struct in6_addr *target = NULL; 603 602 struct inet_peer *peer; ··· 645 644 646 645 if (ip6_pkt_too_big(skb, mtu)) { 647 646 /* Again, force OUTPUT device used as source address */ 648 - skb->dev = dst->dev; 647 + skb->dev = dev; 649 648 icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); 650 649 __IP6_INC_STATS(net, idev, IPSTATS_MIB_INTOOBIGERRORS); 651 650 __IP6_INC_STATS(net, ip6_dst_idev(dst), ··· 654 653 return -EMSGSIZE; 655 654 } 656 655 657 - if (skb_cow(skb, dst->dev->hard_header_len)) { 656 + if (skb_cow(skb, dev->hard_header_len)) { 658 657 __IP6_INC_STATS(net, ip6_dst_idev(dst), 659 658 IPSTATS_MIB_OUTDISCARDS); 660 659 goto drop; ··· 667 666 hdr->hop_limit--; 668 667 669 668 return NF_HOOK(NFPROTO_IPV6, NF_INET_FORWARD, 670 - net, NULL, skb, skb->dev, dst->dev, 669 + net, NULL, skb, skb->dev, dev, 671 670 ip6_forward_finish); 672 671 673 672 error: ··· 1094 1093 #ifdef CONFIG_IPV6_SUBTREES 1095 1094 ip6_rt_check(&rt->rt6i_src, &fl6->saddr, np->saddr_cache) || 1096 1095 #endif 1097 - (fl6->flowi6_oif && fl6->flowi6_oif != dst->dev->ifindex)) { 1096 + (fl6->flowi6_oif && fl6->flowi6_oif != dst_dev(dst)->ifindex)) { 1098 1097 dst_release(dst); 1099 1098 dst = NULL; 1100 1099 }
+2 -2
net/ipv6/ip6_tunnel.c
··· 1179 1179 ndst = dst; 1180 1180 } 1181 1181 1182 - tdev = dst->dev; 1182 + tdev = dst_dev(dst); 1183 1183 1184 1184 if (tdev == dev) { 1185 1185 DEV_STATS_INC(dev, collisions); ··· 1255 1255 /* Calculate max headroom for all the headers and adjust 1256 1256 * needed_headroom if necessary. 1257 1257 */ 1258 - max_headroom = LL_RESERVED_SPACE(dst->dev) + sizeof(struct ipv6hdr) 1258 + max_headroom = LL_RESERVED_SPACE(tdev) + sizeof(struct ipv6hdr) 1259 1259 + dst->header_len + t->hlen; 1260 1260 if (max_headroom > READ_ONCE(dev->needed_headroom)) 1261 1261 WRITE_ONCE(dev->needed_headroom, max_headroom);
+1 -1
net/ipv6/ip6_udp_tunnel.c
··· 168 168 netdev_dbg(dev, "no route to %pI6\n", &fl6.daddr); 169 169 return ERR_PTR(-ENETUNREACH); 170 170 } 171 - if (dst->dev == dev) { /* is this necessary? */ 171 + if (dst_dev(dst) == dev) { /* is this necessary? */ 172 172 netdev_dbg(dev, "circular route to %pI6\n", &fl6.daddr); 173 173 dst_release(dst); 174 174 return ERR_PTR(-ELOOP);
+1 -1
net/ipv6/ip6_vti.c
··· 497 497 (const struct in6_addr *)&x->id.daddr)) 498 498 goto tx_err_link_failure; 499 499 500 - tdev = dst->dev; 500 + tdev = dst_dev(dst); 501 501 502 502 if (tdev == dev) { 503 503 DEV_STATS_INC(dev, collisions);
+4 -2
net/ipv6/ndisc.c
··· 473 473 { 474 474 struct icmp6hdr *icmp6h = icmp6_hdr(skb); 475 475 struct dst_entry *dst = skb_dst(skb); 476 + struct net_device *dev; 476 477 struct inet6_dev *idev; 477 478 struct net *net; 478 479 struct sock *sk; ··· 508 507 509 508 ip6_nd_hdr(skb, saddr, daddr, READ_ONCE(inet6_sk(sk)->hop_limit), skb->len); 510 509 511 - idev = __in6_dev_get(dst->dev); 510 + dev = dst_dev(dst); 511 + idev = __in6_dev_get(dev); 512 512 IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTREQUESTS); 513 513 514 514 err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, 515 - net, sk, skb, NULL, dst->dev, 515 + net, sk, skb, NULL, dev, 516 516 dst_output); 517 517 if (!err) { 518 518 ICMP6MSGOUT_INC_STATS(net, idev, type);
+1 -1
net/ipv6/netfilter/nf_dup_ipv6.c
··· 38 38 } 39 39 skb_dst_drop(skb); 40 40 skb_dst_set(skb, dst); 41 - skb->dev = dst->dev; 41 + skb->dev = dst_dev(dst); 42 42 skb->protocol = htons(ETH_P_IPV6); 43 43 44 44 return true;
+1 -1
net/ipv6/output_core.c
··· 105 105 { 106 106 int hoplimit = dst_metric_raw(dst, RTAX_HOPLIMIT); 107 107 if (hoplimit == 0) { 108 - struct net_device *dev = dst->dev; 108 + struct net_device *dev = dst_dev(dst); 109 109 struct inet6_dev *idev; 110 110 111 111 rcu_read_lock();
+12 -8
net/ipv6/route.c
··· 228 228 const struct rt6_info *rt = dst_rt6_info(dst); 229 229 230 230 return ip6_neigh_lookup(rt6_nexthop(rt, &in6addr_any), 231 - dst->dev, skb, daddr); 231 + dst_dev(dst), skb, daddr); 232 232 } 233 233 234 234 static void ip6_confirm_neigh(const struct dst_entry *dst, const void *daddr) 235 235 { 236 236 const struct rt6_info *rt = dst_rt6_info(dst); 237 - struct net_device *dev = dst->dev; 237 + struct net_device *dev = dst_dev(dst); 238 238 239 239 daddr = choose_neigh_daddr(rt6_nexthop(rt, &in6addr_any), NULL, daddr); 240 240 if (!daddr) ··· 2943 2943 2944 2944 if (res.f6i->nh) { 2945 2945 struct fib6_nh_match_arg arg = { 2946 - .dev = dst->dev, 2946 + .dev = dst_dev(dst), 2947 2947 .gw = &rt6->rt6i_gateway, 2948 2948 }; 2949 2949 ··· 3238 3238 3239 3239 static unsigned int ip6_default_advmss(const struct dst_entry *dst) 3240 3240 { 3241 - struct net_device *dev = dst->dev; 3241 + struct net_device *dev = dst_dev(dst); 3242 3242 unsigned int mtu = dst_mtu(dst); 3243 3243 struct net *net; 3244 3244 ··· 4301 4301 4302 4302 if (res.f6i->nh) { 4303 4303 struct fib6_nh_match_arg arg = { 4304 - .dev = dst->dev, 4304 + .dev = dst_dev(dst), 4305 4305 .gw = &rt->rt6i_gateway, 4306 4306 }; 4307 4307 ··· 4587 4587 static int ip6_pkt_drop(struct sk_buff *skb, u8 code, int ipstats_mib_noroutes) 4588 4588 { 4589 4589 struct dst_entry *dst = skb_dst(skb); 4590 - struct net *net = dev_net(dst->dev); 4590 + struct net_device *dev = dst_dev(dst); 4591 + struct net *net = dev_net(dev); 4591 4592 struct inet6_dev *idev; 4592 4593 SKB_DR(reason); 4593 4594 int type; 4594 4595 4595 4596 if (netif_is_l3_master(skb->dev) || 4596 - dst->dev == net->loopback_dev) 4597 + dev == net->loopback_dev) 4597 4598 idev = __in6_dev_get_safely(dev_get_by_index_rcu(net, IP6CB(skb)->iif)); 4598 4599 else 4599 4600 idev = ip6_dst_idev(dst); ··· 5845 5844 * each as a nexthop within RTA_MULTIPATH. 5846 5845 */ 5847 5846 if (rt6) { 5847 + struct net_device *dev; 5848 + 5848 5849 if (rt6_flags & RTF_GATEWAY && 5849 5850 nla_put_in6_addr(skb, RTA_GATEWAY, &rt6->rt6i_gateway)) 5850 5851 goto nla_put_failure; 5851 5852 5852 - if (dst->dev && nla_put_u32(skb, RTA_OIF, dst->dev->ifindex)) 5853 + dev = dst_dev(dst); 5854 + if (dev && nla_put_u32(skb, RTA_OIF, dev->ifindex)) 5853 5855 goto nla_put_failure; 5854 5856 5855 5857 if (lwtunnel_fill_encap(skb, dst->lwtstate, RTA_ENCAP, RTA_ENCAP_TYPE) < 0)
+2 -2
net/ipv6/rpl_iptunnel.c
··· 242 242 local_bh_enable(); 243 243 } 244 244 245 - err = skb_cow_head(skb, LL_RESERVED_SPACE(dst->dev)); 245 + err = skb_cow_head(skb, LL_RESERVED_SPACE(dst_dev(dst))); 246 246 if (unlikely(err)) 247 247 goto drop; 248 248 } ··· 297 297 local_bh_enable(); 298 298 } 299 299 300 - err = skb_cow_head(skb, LL_RESERVED_SPACE(dst->dev)); 300 + err = skb_cow_head(skb, LL_RESERVED_SPACE(dst_dev(dst))); 301 301 if (unlikely(err)) 302 302 goto drop; 303 303 } else {
+11 -9
net/ipv6/seg6_iptunnel.c
··· 128 128 int proto, struct dst_entry *cache_dst) 129 129 { 130 130 struct dst_entry *dst = skb_dst(skb); 131 - struct net *net = dev_net(dst->dev); 131 + struct net_device *dev = dst_dev(dst); 132 + struct net *net = dev_net(dev); 132 133 struct ipv6hdr *hdr, *inner_hdr; 133 134 struct ipv6_sr_hdr *isrh; 134 135 int hdrlen, tot_len, err; ··· 182 181 isrh->nexthdr = proto; 183 182 184 183 hdr->daddr = isrh->segments[isrh->first_segment]; 185 - set_tun_src(net, dst->dev, &hdr->daddr, &hdr->saddr); 184 + set_tun_src(net, dev, &hdr->daddr, &hdr->saddr); 186 185 187 186 #ifdef CONFIG_IPV6_SEG6_HMAC 188 187 if (sr_has_hmac(isrh)) { ··· 213 212 { 214 213 __u8 first_seg = osrh->first_segment; 215 214 struct dst_entry *dst = skb_dst(skb); 216 - struct net *net = dev_net(dst->dev); 215 + struct net_device *dev = dst_dev(dst); 216 + struct net *net = dev_net(dev); 217 217 struct ipv6hdr *hdr, *inner_hdr; 218 218 int hdrlen = ipv6_optlen(osrh); 219 219 int red_tlv_offset, tlv_offset; ··· 272 270 if (skip_srh) { 273 271 hdr->nexthdr = proto; 274 272 275 - set_tun_src(net, dst->dev, &hdr->daddr, &hdr->saddr); 273 + set_tun_src(net, dev, &hdr->daddr, &hdr->saddr); 276 274 goto out; 277 275 } 278 276 ··· 308 306 309 307 srcaddr: 310 308 isrh->nexthdr = proto; 311 - set_tun_src(net, dst->dev, &hdr->daddr, &hdr->saddr); 309 + set_tun_src(net, dev, &hdr->daddr, &hdr->saddr); 312 310 313 311 #ifdef CONFIG_IPV6_SEG6_HMAC 314 312 if (unlikely(!skip_srh && sr_has_hmac(isrh))) { ··· 509 507 local_bh_enable(); 510 508 } 511 509 512 - err = skb_cow_head(skb, LL_RESERVED_SPACE(dst->dev)); 510 + err = skb_cow_head(skb, LL_RESERVED_SPACE(dst_dev(dst))); 513 511 if (unlikely(err)) 514 512 goto drop; 515 513 } else { ··· 520 518 if (static_branch_unlikely(&nf_hooks_lwtunnel_enabled)) 521 519 return NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, 522 520 dev_net(skb->dev), NULL, skb, NULL, 523 - skb_dst(skb)->dev, seg6_input_finish); 521 + skb_dst_dev(skb), seg6_input_finish); 524 522 525 523 return seg6_input_finish(dev_net(skb->dev), NULL, skb); 526 524 drop: ··· 595 593 local_bh_enable(); 596 594 } 597 595 598 - err = skb_cow_head(skb, LL_RESERVED_SPACE(dst->dev)); 596 + err = skb_cow_head(skb, LL_RESERVED_SPACE(dst_dev(dst))); 599 597 if (unlikely(err)) 600 598 goto drop; 601 599 } ··· 605 603 606 604 if (static_branch_unlikely(&nf_hooks_lwtunnel_enabled)) 607 605 return NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, net, sk, skb, 608 - NULL, skb_dst(skb)->dev, dst_output); 606 + NULL, dst_dev(dst), dst_output); 609 607 610 608 return dst_output(net, sk, skb); 611 609 drop:
+1 -1
net/ipv6/seg6_local.c
··· 313 313 if (!local_delivery) 314 314 dev_flags |= IFF_LOOPBACK; 315 315 316 - if (dst && (dst->dev->flags & dev_flags) && !dst->error) { 316 + if (dst && (dst_dev(dst)->flags & dev_flags) && !dst->error) { 317 317 dst_release(dst); 318 318 dst = NULL; 319 319 }