From 34ea2499389e7a2f1522682e003b257eccda26be Mon Sep 17 00:00:00 2001 From: Kuniyuki Iwashima Date: Mon, 29 Jun 2026 18:11:00 +0000 Subject: [PATCH] net: fib_rules: Use dev_get_by_name_rcu(). We will no longer hold RTNL for RTM_NEWRULE and RMT_DELRULE except for the first IPv4 RTM_NEWRULE. Let's covnert __dev_get_by_name() in fib_nl2rule_rtnl() to dev_get_by_name_rcu() and rename it to fib_nl2rule_locked(). Note that dev_get_by_name_rcu() must be called inside ops->lock to serialise fib_rules_event() by __dev_change_net_namespace(). Signed-off-by: Kuniyuki Iwashima Link: https://patch.msgid.link/20260629181226.1929658-9-kuniyu@google.com Reviewed-by: Ido Schimmel Signed-off-by: Paolo Abeni --- net/core/fib_rules.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c index 5eef5d6ace82..2b652dd83241 100644 --- a/net/core/fib_rules.c +++ b/net/core/fib_rules.c @@ -734,10 +734,10 @@ static int fib_nl2rule(struct net *net, struct nlmsghdr *nlh, return err; } -static int fib_nl2rule_rtnl(struct fib_rule *nlrule, - struct fib_rules_ops *ops, - struct nlattr *tb[], - struct netlink_ext_ack *extack) +static int fib_nl2rule_locked(struct fib_rule *nlrule, + struct fib_rules_ops *ops, + struct nlattr *tb[], + struct netlink_ext_ack *extack) { if (!tb[FRA_PRIORITY]) nlrule->pref = fib_default_rule_pref(ops); @@ -748,12 +748,14 @@ static int fib_nl2rule_rtnl(struct fib_rule *nlrule, return -EINVAL; } + rcu_read_lock(); + if (tb[FRA_IIFNAME]) { struct net_device *dev; - dev = __dev_get_by_name(nlrule->fr_net, nlrule->iifname); + dev = dev_get_by_name_rcu(nlrule->fr_net, nlrule->iifname); if (dev) { - nlrule->iifindex = dev->ifindex; + nlrule->iifindex = READ_ONCE(dev->ifindex); nlrule->iif_is_l3_master = netif_is_l3_master(dev); } } @@ -761,13 +763,15 @@ static int fib_nl2rule_rtnl(struct fib_rule *nlrule, if (tb[FRA_OIFNAME]) { struct net_device *dev; - dev = __dev_get_by_name(nlrule->fr_net, nlrule->oifname); + dev = dev_get_by_name_rcu(nlrule->fr_net, nlrule->oifname); if (dev) { - nlrule->oifindex = dev->ifindex; + nlrule->oifindex = READ_ONCE(dev->ifindex); nlrule->oif_is_l3_master = netif_is_l3_master(dev); } } + rcu_read_unlock(); + return 0; } @@ -906,7 +910,7 @@ int fib_newrule(struct net *net, struct sk_buff *skb, struct nlmsghdr *nlh, rtnl_net_lock(net); mutex_lock(&ops->lock); - err = fib_nl2rule_rtnl(rule, ops, tb, extack); + err = fib_nl2rule_locked(rule, ops, tb, extack); if (err) goto errout_free; @@ -1038,7 +1042,7 @@ int fib_delrule(struct net *net, struct sk_buff *skb, struct nlmsghdr *nlh, rtnl_net_lock(net); mutex_lock(&ops->lock); - err = fib_nl2rule_rtnl(nlrule, ops, tb, extack); + err = fib_nl2rule_locked(nlrule, ops, tb, extack); if (err) goto errout_free;