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.

ipmr: Don't hold RTNL for ipmr_rtm_route().

ipmr_mfc_add() and ipmr_mfc_delete() are already protected
by a dedicated mutex.

rtm_to_ipmr_mfcc() calls __ipmr_get_table(), __dev_get_by_index(),
amd ipmr_find_vif().

Once __dev_get_by_index() is converted to dev_get_by_index_rcu(),
we can move the other two functions under that same RCU section
and drop RTNL for ipmr_rtm_route().

Let's do that conversion and drop ASSERT_RTNL() in
mr_call_mfc_notifiers().

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

authored by

Kuniyuki Iwashima and committed by
Jakub Kicinski
bddafc06 3c1e53e5

+21 -14
-1
include/linux/mroute_base.h
··· 208 208 .tb_id = tb_id 209 209 }; 210 210 211 - ASSERT_RTNL(); 212 211 atomic_inc(ipmr_seq); 213 212 return call_fib_notifiers(net, event_type, &info.info); 214 213 }
+21 -13
net/ipv4/ipmr.c
··· 1211 1211 struct net *net = read_pnet(&mrt->net); 1212 1212 struct mfc_cache *c; 1213 1213 1214 - /* The entries are added/deleted only under RTNL */ 1215 1214 rcu_read_lock(); 1216 1215 c = ipmr_cache_find_parent(mrt, mfc->mfcc_origin.s_addr, 1217 1216 mfc->mfcc_mcastgrp.s_addr, parent); ··· 1237 1238 if (mfc->mfcc_parent >= MAXVIFS) 1238 1239 return -ENFILE; 1239 1240 1240 - /* The entries are added/deleted only under RTNL */ 1241 1241 rcu_read_lock(); 1242 1242 c = ipmr_cache_find_parent(mrt, mfc->mfcc_origin.s_addr, 1243 1243 mfc->mfcc_mcastgrp.s_addr, parent); ··· 2851 2853 { 2852 2854 struct net_device *dev = NULL; 2853 2855 u32 tblid = RT_TABLE_DEFAULT; 2856 + int ret, rem, iif = 0; 2854 2857 struct mr_table *mrt; 2855 2858 struct nlattr *attr; 2856 2859 struct rtmsg *rtm; 2857 - int ret, rem; 2858 2860 2859 2861 ret = nlmsg_validate_deprecated(nlh, sizeof(*rtm), RTA_MAX, 2860 2862 rtm_ipmr_policy, extack); ··· 2881 2883 mfcc->mfcc_mcastgrp.s_addr = nla_get_be32(attr); 2882 2884 break; 2883 2885 case RTA_IIF: 2884 - dev = __dev_get_by_index(net, nla_get_u32(attr)); 2885 - if (!dev) { 2886 - ret = -ENODEV; 2887 - goto out; 2888 - } 2886 + iif = nla_get_u32(attr); 2889 2887 break; 2890 2888 case RTA_MULTIPATH: 2891 2889 if (ipmr_nla_get_ttls(attr, mfcc) < 0) { ··· 2897 2903 break; 2898 2904 } 2899 2905 } 2906 + 2907 + rcu_read_lock(); 2908 + 2900 2909 mrt = __ipmr_get_table(net, tblid); 2901 2910 if (!mrt) { 2902 2911 ret = -ENOENT; 2903 - goto out; 2912 + goto unlock; 2904 2913 } 2914 + 2915 + if (iif) { 2916 + dev = dev_get_by_index_rcu(net, iif); 2917 + if (!dev) { 2918 + ret = -ENODEV; 2919 + goto unlock; 2920 + } 2921 + 2922 + mfcc->mfcc_parent = ipmr_find_vif(mrt, dev); 2923 + } 2924 + 2905 2925 *mrtret = mrt; 2906 2926 *mrtsock = rtm->rtm_protocol == RTPROT_MROUTED ? 1 : 0; 2907 - if (dev) 2908 - mfcc->mfcc_parent = ipmr_find_vif(mrt, dev); 2909 2927 2928 + unlock: 2929 + rcu_read_unlock(); 2910 2930 out: 2911 2931 return ret; 2912 2932 } ··· 3351 3343 {.protocol = RTNL_FAMILY_IPMR, .msgtype = RTM_GETLINK, 3352 3344 .dumpit = ipmr_rtm_dumplink, .flags = RTNL_FLAG_DUMP_UNLOCKED}, 3353 3345 {.protocol = RTNL_FAMILY_IPMR, .msgtype = RTM_NEWROUTE, 3354 - .doit = ipmr_rtm_route}, 3346 + .doit = ipmr_rtm_route, .flags = RTNL_FLAG_DOIT_UNLOCKED}, 3355 3347 {.protocol = RTNL_FAMILY_IPMR, .msgtype = RTM_DELROUTE, 3356 - .doit = ipmr_rtm_route}, 3348 + .doit = ipmr_rtm_route, .flags = RTNL_FLAG_DOIT_UNLOCKED}, 3357 3349 {.protocol = RTNL_FAMILY_IPMR, .msgtype = RTM_GETROUTE, 3358 3350 .doit = ipmr_rtm_getroute, .dumpit = ipmr_rtm_dumproute, 3359 3351 .flags = RTNL_FLAG_DOIT_UNLOCKED | RTNL_FLAG_DUMP_UNLOCKED},