summaryrefslogtreecommitdiff
path: root/net/ipv6
diff options
context:
space:
mode:
authorKuniyuki Iwashima <kuniyu@google.com>2026-06-04 22:46:20 +0000
committerJakub Kicinski <kuba@kernel.org>2026-06-08 17:06:22 -0700
commit364568de4e7f8a5a0f0e12a0ba8812377f53c07a (patch)
treee43a4e67a820c9237519b136b6f8443f1f07289c /net/ipv6
parente02bf5e7aa4af4e5e063d6a1bf1de6dded69fe5b (diff)
downloadlinux-next-364568de4e7f8a5a0f0e12a0ba8812377f53c07a.tar.gz
linux-next-364568de4e7f8a5a0f0e12a0ba8812377f53c07a.zip
ip6mr: Annotate access to mrt->mroute_do_{pim,assert,wrvifwhole}.
These fields in struct mr_table are updated in ip6_mroute_setsockopt() under RTNL: * mroute_do_pim * mroute_do_assert (MRT6_PIM is under RTNL while MRT6_ASSERT is lockless) * mroute_do_wrvifwhole However, ip6_mroute_getsockopt() does not hold RTNL and read the first two fields locklessly, and ip6_mr_forward() reads all the three under RCU. Let's use WRITE_ONCE() and READ_ONCE() for them. Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com> Link: https://patch.msgid.link/20260604224712.3209821-3-kuniyu@google.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Diffstat (limited to 'net/ipv6')
-rw-r--r--net/ipv6/ip6mr.c18
1 files changed, 9 insertions, 9 deletions
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
index 9d748f4c44e9..e3dd5851b879 100644
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
@@ -1778,7 +1778,7 @@ int ip6_mroute_setsockopt(struct sock *sk, int optname, sockptr_t optval,
return -EINVAL;
if (copy_from_sockptr(&v, optval, sizeof(v)))
return -EFAULT;
- mrt->mroute_do_assert = v;
+ WRITE_ONCE(mrt->mroute_do_assert, v);
return 0;
}
@@ -1798,9 +1798,9 @@ int ip6_mroute_setsockopt(struct sock *sk, int optname, sockptr_t optval,
rtnl_lock();
ret = 0;
if (v != mrt->mroute_do_pim) {
- mrt->mroute_do_pim = v;
- mrt->mroute_do_assert = v;
- mrt->mroute_do_wrvifwhole = do_wrmifwhole;
+ WRITE_ONCE(mrt->mroute_do_pim, v);
+ WRITE_ONCE(mrt->mroute_do_assert, v);
+ WRITE_ONCE(mrt->mroute_do_wrvifwhole, do_wrmifwhole);
}
rtnl_unlock();
return ret;
@@ -1868,11 +1868,11 @@ int ip6_mroute_getsockopt(struct sock *sk, int optname, sockptr_t optval,
break;
#ifdef CONFIG_IPV6_PIMSM_V2
case MRT6_PIM:
- val = mrt->mroute_do_pim;
+ val = READ_ONCE(mrt->mroute_do_pim);
break;
#endif
case MRT6_ASSERT:
- val = mrt->mroute_do_assert;
+ val = READ_ONCE(mrt->mroute_do_assert);
break;
default:
return -ENOPROTOOPT;
@@ -2175,20 +2175,20 @@ static void ip6_mr_forward(struct net *net, struct mr_table *mrt,
if (rcu_access_pointer(mrt->vif_table[vif].dev) != dev) {
atomic_long_inc(&c->_c.mfc_un.res.wrong_if);
- if (true_vifi >= 0 && mrt->mroute_do_assert &&
+ if (true_vifi >= 0 && READ_ONCE(mrt->mroute_do_assert) &&
/* pimsm uses asserts, when switching from RPT to SPT,
so that we cannot check that packet arrived on an oif.
It is bad, but otherwise we would need to move pretty
large chunk of pimd to kernel. Ough... --ANK
*/
- (mrt->mroute_do_pim ||
+ (READ_ONCE(mrt->mroute_do_pim) ||
c->_c.mfc_un.res.ttls[true_vifi] < 255) &&
time_after(jiffies,
c->_c.mfc_un.res.last_assert +
MFC_ASSERT_THRESH)) {
c->_c.mfc_un.res.last_assert = jiffies;
ip6mr_cache_report(mrt, skb, true_vifi, MRT6MSG_WRONGMIF);
- if (mrt->mroute_do_wrvifwhole)
+ if (READ_ONCE(mrt->mroute_do_wrvifwhole))
ip6mr_cache_report(mrt, skb, true_vifi,
MRT6MSG_WRMIFWHOLE);
}