Skip to content

Commit 9dfedb8

Browse files
committed
Merge branch 'net-second-round-to-use-dev_net_rcu'
Eric Dumazet says: ==================== net: second 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. This second series fixes some of them. ==================== Link: https://patch.msgid.link/20250207135841.1948589-1-edumazet@google.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2 parents cb6cc8e + 087c1fa commit 9dfedb8

File tree

6 files changed

+48
-33
lines changed

6 files changed

+48
-33
lines changed

include/net/l3mdev.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,10 +198,12 @@ struct sk_buff *l3mdev_l3_out(struct sock *sk, struct sk_buff *skb, u16 proto)
198198
if (netif_is_l3_slave(dev)) {
199199
struct net_device *master;
200200

201+
rcu_read_lock();
201202
master = netdev_master_upper_dev_get_rcu(dev);
202203
if (master && master->l3mdev_ops->l3mdev_l3_out)
203204
skb = master->l3mdev_ops->l3mdev_l3_out(master, sk,
204205
skb, proto);
206+
rcu_read_unlock();
205207
}
206208

207209
return skb;

net/core/neighbour.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3447,10 +3447,12 @@ static const struct seq_operations neigh_stat_seq_ops = {
34473447
static void __neigh_notify(struct neighbour *n, int type, int flags,
34483448
u32 pid)
34493449
{
3450-
struct net *net = dev_net(n->dev);
34513450
struct sk_buff *skb;
34523451
int err = -ENOBUFS;
3452+
struct net *net;
34533453

3454+
rcu_read_lock();
3455+
net = dev_net_rcu(n->dev);
34543456
skb = nlmsg_new(neigh_nlmsg_size(), GFP_ATOMIC);
34553457
if (skb == NULL)
34563458
goto errout;
@@ -3463,9 +3465,11 @@ static void __neigh_notify(struct neighbour *n, int type, int flags,
34633465
goto errout;
34643466
}
34653467
rtnl_notify(skb, net, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC);
3466-
return;
3468+
goto out;
34673469
errout:
34683470
rtnl_set_sk_err(net, RTNLGRP_NEIGH, err);
3471+
out:
3472+
rcu_read_unlock();
34693473
}
34703474

34713475
void neigh_app_ns(struct neighbour *n)

net/ipv4/arp.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -659,10 +659,12 @@ static int arp_xmit_finish(struct net *net, struct sock *sk, struct sk_buff *skb
659659
*/
660660
void arp_xmit(struct sk_buff *skb)
661661
{
662+
rcu_read_lock();
662663
/* Send it off, maybe filter it using firewalling first. */
663664
NF_HOOK(NFPROTO_ARP, NF_ARP_OUT,
664-
dev_net(skb->dev), NULL, skb, NULL, skb->dev,
665+
dev_net_rcu(skb->dev), NULL, skb, NULL, skb->dev,
665666
arp_xmit_finish);
667+
rcu_read_unlock();
666668
}
667669
EXPORT_SYMBOL(arp_xmit);
668670

net/ipv6/mcast.c

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2165,21 +2165,21 @@ static void mld_send_cr(struct inet6_dev *idev)
21652165

21662166
static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
21672167
{
2168-
struct net *net = dev_net(dev);
2169-
struct sock *sk = net->ipv6.igmp_sk;
2168+
const struct in6_addr *snd_addr, *saddr;
2169+
int err, len, payload_len, full_len;
2170+
struct in6_addr addr_buf;
21702171
struct inet6_dev *idev;
21712172
struct sk_buff *skb;
21722173
struct mld_msg *hdr;
2173-
const struct in6_addr *snd_addr, *saddr;
2174-
struct in6_addr addr_buf;
21752174
int hlen = LL_RESERVED_SPACE(dev);
21762175
int tlen = dev->needed_tailroom;
2177-
int err, len, payload_len, full_len;
21782176
u8 ra[8] = { IPPROTO_ICMPV6, 0,
21792177
IPV6_TLV_ROUTERALERT, 2, 0, 0,
21802178
IPV6_TLV_PADN, 0 };
2181-
struct flowi6 fl6;
21822179
struct dst_entry *dst;
2180+
struct flowi6 fl6;
2181+
struct net *net;
2182+
struct sock *sk;
21832183

21842184
if (type == ICMPV6_MGM_REDUCTION)
21852185
snd_addr = &in6addr_linklocal_allrouters;
@@ -2190,19 +2190,21 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
21902190
payload_len = len + sizeof(ra);
21912191
full_len = sizeof(struct ipv6hdr) + payload_len;
21922192

2193-
rcu_read_lock();
2194-
IP6_INC_STATS(net, __in6_dev_get(dev), IPSTATS_MIB_OUTREQUESTS);
2195-
rcu_read_unlock();
2193+
skb = alloc_skb(hlen + tlen + full_len, GFP_KERNEL);
21962194

2197-
skb = sock_alloc_send_skb(sk, hlen + tlen + full_len, 1, &err);
2195+
rcu_read_lock();
21982196

2197+
net = dev_net_rcu(dev);
2198+
idev = __in6_dev_get(dev);
2199+
IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTREQUESTS);
21992200
if (!skb) {
2200-
rcu_read_lock();
2201-
IP6_INC_STATS(net, __in6_dev_get(dev),
2202-
IPSTATS_MIB_OUTDISCARDS);
2201+
IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTDISCARDS);
22032202
rcu_read_unlock();
22042203
return;
22052204
}
2205+
sk = net->ipv6.igmp_sk;
2206+
skb_set_owner_w(skb, sk);
2207+
22062208
skb->priority = TC_PRIO_CONTROL;
22072209
skb_reserve(skb, hlen);
22082210

@@ -2227,9 +2229,6 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
22272229
IPPROTO_ICMPV6,
22282230
csum_partial(hdr, len, 0));
22292231

2230-
rcu_read_lock();
2231-
idev = __in6_dev_get(skb->dev);
2232-
22332232
icmpv6_flow_init(sk, &fl6, type,
22342233
&ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr,
22352234
skb->dev->ifindex);

net/ipv6/ndisc.c

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -418,15 +418,11 @@ static struct sk_buff *ndisc_alloc_skb(struct net_device *dev,
418418
{
419419
int hlen = LL_RESERVED_SPACE(dev);
420420
int tlen = dev->needed_tailroom;
421-
struct sock *sk = dev_net(dev)->ipv6.ndisc_sk;
422421
struct sk_buff *skb;
423422

424423
skb = alloc_skb(hlen + sizeof(struct ipv6hdr) + len + tlen, GFP_ATOMIC);
425-
if (!skb) {
426-
ND_PRINTK(0, err, "ndisc: %s failed to allocate an skb\n",
427-
__func__);
424+
if (!skb)
428425
return NULL;
429-
}
430426

431427
skb->protocol = htons(ETH_P_IPV6);
432428
skb->dev = dev;
@@ -437,7 +433,9 @@ static struct sk_buff *ndisc_alloc_skb(struct net_device *dev,
437433
/* Manually assign socket ownership as we avoid calling
438434
* sock_alloc_send_pskb() to bypass wmem buffer limits
439435
*/
440-
skb_set_owner_w(skb, sk);
436+
rcu_read_lock();
437+
skb_set_owner_w(skb, dev_net_rcu(dev)->ipv6.ndisc_sk);
438+
rcu_read_unlock();
441439

442440
return skb;
443441
}
@@ -473,23 +471,28 @@ static void ip6_nd_hdr(struct sk_buff *skb,
473471
void ndisc_send_skb(struct sk_buff *skb, const struct in6_addr *daddr,
474472
const struct in6_addr *saddr)
475473
{
474+
struct icmp6hdr *icmp6h = icmp6_hdr(skb);
476475
struct dst_entry *dst = skb_dst(skb);
477-
struct net *net = dev_net(skb->dev);
478-
struct sock *sk = net->ipv6.ndisc_sk;
479476
struct inet6_dev *idev;
477+
struct net *net;
478+
struct sock *sk;
480479
int err;
481-
struct icmp6hdr *icmp6h = icmp6_hdr(skb);
482480
u8 type;
483481

484482
type = icmp6h->icmp6_type;
485483

484+
rcu_read_lock();
485+
486+
net = dev_net_rcu(skb->dev);
487+
sk = net->ipv6.ndisc_sk;
486488
if (!dst) {
487489
struct flowi6 fl6;
488490
int oif = skb->dev->ifindex;
489491

490492
icmpv6_flow_init(sk, &fl6, type, saddr, daddr, oif);
491493
dst = icmp6_dst_alloc(skb->dev, &fl6);
492494
if (IS_ERR(dst)) {
495+
rcu_read_unlock();
493496
kfree_skb(skb);
494497
return;
495498
}
@@ -504,7 +507,6 @@ void ndisc_send_skb(struct sk_buff *skb, const struct in6_addr *daddr,
504507

505508
ip6_nd_hdr(skb, saddr, daddr, READ_ONCE(inet6_sk(sk)->hop_limit), skb->len);
506509

507-
rcu_read_lock();
508510
idev = __in6_dev_get(dst->dev);
509511
IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTREQUESTS);
510512

@@ -1694,7 +1696,7 @@ void ndisc_send_redirect(struct sk_buff *skb, const struct in6_addr *target)
16941696
bool ret;
16951697

16961698
if (netif_is_l3_master(skb->dev)) {
1697-
dev = __dev_get_by_index(dev_net(skb->dev), IPCB(skb)->iif);
1699+
dev = dev_get_by_index_rcu(dev_net(skb->dev), IPCB(skb)->iif);
16981700
if (!dev)
16991701
return;
17001702
}

net/openvswitch/datapath.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2101,6 +2101,7 @@ static int ovs_vport_cmd_fill_info(struct vport *vport, struct sk_buff *skb,
21012101
{
21022102
struct ovs_header *ovs_header;
21032103
struct ovs_vport_stats vport_stats;
2104+
struct net *net_vport;
21042105
int err;
21052106

21062107
ovs_header = genlmsg_put(skb, portid, seq, &dp_vport_genl_family,
@@ -2117,12 +2118,15 @@ static int ovs_vport_cmd_fill_info(struct vport *vport, struct sk_buff *skb,
21172118
nla_put_u32(skb, OVS_VPORT_ATTR_IFINDEX, vport->dev->ifindex))
21182119
goto nla_put_failure;
21192120

2120-
if (!net_eq(net, dev_net(vport->dev))) {
2121-
int id = peernet2id_alloc(net, dev_net(vport->dev), gfp);
2121+
rcu_read_lock();
2122+
net_vport = dev_net_rcu(vport->dev);
2123+
if (!net_eq(net, net_vport)) {
2124+
int id = peernet2id_alloc(net, net_vport, GFP_ATOMIC);
21222125

21232126
if (nla_put_s32(skb, OVS_VPORT_ATTR_NETNSID, id))
2124-
goto nla_put_failure;
2127+
goto nla_put_failure_unlock;
21252128
}
2129+
rcu_read_unlock();
21262130

21272131
ovs_vport_get_stats(vport, &vport_stats);
21282132
if (nla_put_64bit(skb, OVS_VPORT_ATTR_STATS,
@@ -2143,6 +2147,8 @@ static int ovs_vport_cmd_fill_info(struct vport *vport, struct sk_buff *skb,
21432147
genlmsg_end(skb, ovs_header);
21442148
return 0;
21452149

2150+
nla_put_failure_unlock:
2151+
rcu_read_unlock();
21462152
nla_put_failure:
21472153
err = -EMSGSIZE;
21482154
error:

0 commit comments

Comments
 (0)