Re: [PATCH net v6 09/10] ip6mr: Lock RCU before ip6mr_get_table() call in ip6mr_rtm_getroute()
flat view
From: Florian Westphal <fw@strlen.de>
Date: 2024-10-18 11:52:41
Also in:
lkml
Stefan Wiehler [off-list ref] wrote:
quoted
quoted
When IPV6_MROUTE_MULTIPLE_TABLES is enabled, multicast routing tables must be read under RCU or RTNL lock. Fixes: d1db275dd3f6 ("ipv6: ip6mr: support multiple tables") Signed-off-by: Stefan Wiehler <redacted> --- net/ipv6/ip6mr.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-)diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index b169b27de7e1..39aac81a30f1 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c@@ -2633,27 +2633,31 @@ static int ip6mr_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh, grp = nla_get_in6_addr(tb[RTA_DST]); tableid = tb[RTA_TABLE] ? nla_get_u32(tb[RTA_TABLE]) : 0; + rcu_read_lock();AFAICS ip6mr_rtm_getroute() runs with RTNL held, so I don't see why this patch is needed.That's true, but it's called neither with RCU nor RTNL lock when RTNL_FLAG_DOIT_UNLOCKED is set in rtnetlink_rcv_msg():
Sure, but RTNL_FLAG_DOIT_UNLOCKED is not set for this function:
err = rtnl_register_module(THIS_MODULE, RTNL_FAMILY_IP6MR, RTM_GETROUTE,
ip6mr_rtm_getroute, ip6mr_rtm_dumproute, 0);
(0 == flag field). So RNTL is held. Would of course be nice to convert it to RCU
eventually but thats an enhancement, not a bug fix, so this must be in
separate changesets, targetting net and net-next, respectively.
I realized now that I completely misunderstood how ip6mr_rtm_dumproute() gets called - it should be still safe though because mpls_netconf_dump_devconf() and getaddr_dumpit() hold the RCU lock while mpls_dump_routes() asserts that the RTNL lock is held. Is that observation correct?
{THIS_MODULE, PF_PHONET, RTM_GETADDR, NULL, getaddr_dumpit, 0},
{THIS_MODULE, PF_MPLS, RTM_GETROUTE, mpls_getroute, mpls_dump_routes, 0},
Both get called with RTNL mutex held, but not within an RCU read side
section.
but:
{THIS_MODULE, PF_MPLS, RTM_GETNETCONF, [..] mpls_netconf_dump_devconf,
RTNL_FLAG_DUMP_UNLOCKED}, // == no RTNL held
Means: dump callback is invoked without RTNL mutex. Those functions
are also called without and RCU read-side section.
Both the get (doit) and the dumper function callbacks need to
explicitly opt-in for RTNL-less invocation at register time.