]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
ipmr: Annotate access to mrt->mroute_do_{pim,assert,wrvifwhole}.
authorKuniyuki Iwashima <kuniyu@google.com>
Sat, 28 Feb 2026 22:17:20 +0000 (22:17 +0000)
committerJakub Kicinski <kuba@kernel.org>
Tue, 3 Mar 2026 02:49:39 +0000 (18:49 -0800)
These fields in struct mr_table are updated in ip_mroute_setsockopt()
under RTNL:

  * mroute_do_pim
  * mroute_do_assert
  * mroute_do_wrvifwhole

However, ip_mroute_getsockopt() does not hold RTNL and read the first
two fields locklessly, and ip_mr_forward() reads all the three under
RCU.  pim_rcv_v1() also reads mroute_do_pim locklessly.

Let's use WRITE_ONCE() and READ_ONCE() for them.

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

index 131382c388e95707f27dd7d43be9b9ee2f62c85d..970f173654c7f6496604a819c28fd72a7d1f93ec 100644 (file)
@@ -1506,7 +1506,7 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, sockptr_t optval,
                        ret = -EFAULT;
                        break;
                }
-               mrt->mroute_do_assert = val;
+               WRITE_ONCE(mrt->mroute_do_assert, val);
                break;
        case MRT_PIM:
                if (!ipmr_pimsm_enabled()) {
@@ -1525,9 +1525,9 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, sockptr_t optval,
                do_wrvifwhole = (val == IGMPMSG_WRVIFWHOLE);
                val = !!val;
                if (val != mrt->mroute_do_pim) {
-                       mrt->mroute_do_pim = val;
-                       mrt->mroute_do_assert = val;
-                       mrt->mroute_do_wrvifwhole = do_wrvifwhole;
+                       WRITE_ONCE(mrt->mroute_do_pim, val);
+                       WRITE_ONCE(mrt->mroute_do_assert, val);
+                       WRITE_ONCE(mrt->mroute_do_wrvifwhole, do_wrvifwhole);
                }
                break;
        case MRT_TABLE:
@@ -1610,10 +1610,10 @@ int ip_mroute_getsockopt(struct sock *sk, int optname, sockptr_t optval,
        case MRT_PIM:
                if (!ipmr_pimsm_enabled())
                        return -ENOPROTOOPT;
-               val = mrt->mroute_do_pim;
+               val = READ_ONCE(mrt->mroute_do_pim);
                break;
        case MRT_ASSERT:
-               val = mrt->mroute_do_assert;
+               val = READ_ONCE(mrt->mroute_do_assert);
                break;
        default:
                return -ENOPROTOOPT;
@@ -2037,20 +2037,20 @@ static void ip_mr_forward(struct net *net, struct mr_table *mrt,
 
                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;
                        ipmr_cache_report(mrt, skb, true_vifi, IGMPMSG_WRONGVIF);
-                       if (mrt->mroute_do_wrvifwhole)
+                       if (READ_ONCE(mrt->mroute_do_wrvifwhole))
                                ipmr_cache_report(mrt, skb, true_vifi,
                                                  IGMPMSG_WRVIFWHOLE);
                }
@@ -2358,7 +2358,7 @@ int pim_rcv_v1(struct sk_buff *skb)
        mrt = ipmr_rt_fib_lookup(net, skb);
        if (IS_ERR(mrt))
                goto drop;
-       if (!mrt->mroute_do_pim ||
+       if (!READ_ONCE(mrt->mroute_do_pim) ||
            pim->group != PIM_V1_VERSION || pim->code != PIM_V1_REGISTER)
                goto drop;