]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
ipv6: anycast: Don't use rtnl_dereference().
authorKuniyuki Iwashima <kuniyu@google.com>
Wed, 2 Jul 2025 23:01:28 +0000 (16:01 -0700)
committerJakub Kicinski <kuba@kernel.org>
Wed, 9 Jul 2025 01:32:39 +0000 (18:32 -0700)
inet6_dev->ac_list is protected by inet6_dev->lock, so rtnl_dereference()
is a bit rough annotation.

As done in mcast.c, we can use ac_dereference() that checks if
inet6_dev->lock is held.

Let's replace rtnl_dereference() with a new helper ac_dereference().

Note that now addrconf_join_solict() / addrconf_leave_solict() in
__ipv6_dev_ac_inc() / __ipv6_dev_ac_dec() does not need RTNL, so we
can remove ASSERT_RTNL() there.

Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com>
Reviewed-by: Eric Dumazet <edumazet@google.com>
Link: https://patch.msgid.link/20250702230210.3115355-12-kuni1840@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
net/ipv6/addrconf.c
net/ipv6/anycast.c

index 8451014457dd94a80667ea187ee5e5a8843f0164..3c200157634e106b41c67a560ace552134c52a42 100644 (file)
@@ -2252,7 +2252,6 @@ void addrconf_leave_solict(struct inet6_dev *idev, const struct in6_addr *addr)
        __ipv6_dev_mc_dec(idev, &maddr);
 }
 
-/* caller must hold RTNL */
 static void addrconf_join_anycast(struct inet6_ifaddr *ifp)
 {
        struct in6_addr addr;
@@ -2265,7 +2264,6 @@ static void addrconf_join_anycast(struct inet6_ifaddr *ifp)
        __ipv6_dev_ac_inc(ifp->idev, &addr);
 }
 
-/* caller must hold RTNL */
 static void addrconf_leave_anycast(struct inet6_ifaddr *ifp)
 {
        struct in6_addr addr;
index 21e01695b48cde49f36ee466d75d97842c16f652..f510df93b1e9549c1fa160b6f8260eacdd7616de 100644 (file)
@@ -47,6 +47,9 @@
 static struct hlist_head inet6_acaddr_lst[IN6_ADDR_HSIZE];
 static DEFINE_SPINLOCK(acaddr_hash_lock);
 
+#define ac_dereference(a, idev)                                                \
+       rcu_dereference_protected(a, lockdep_is_held(&(idev)->lock))
+
 static int ipv6_dev_ac_dec(struct net_device *dev, const struct in6_addr *addr);
 
 static u32 inet6_acaddr_hash(const struct net *net,
@@ -319,16 +322,14 @@ int __ipv6_dev_ac_inc(struct inet6_dev *idev, const struct in6_addr *addr)
        struct net *net;
        int err;
 
-       ASSERT_RTNL();
-
        write_lock_bh(&idev->lock);
        if (idev->dead) {
                err = -ENODEV;
                goto out;
        }
 
-       for (aca = rtnl_dereference(idev->ac_list); aca;
-            aca = rtnl_dereference(aca->aca_next)) {
+       for (aca = ac_dereference(idev->ac_list, idev); aca;
+            aca = ac_dereference(aca->aca_next, idev)) {
                if (ipv6_addr_equal(&aca->aca_addr, addr)) {
                        aca->aca_users++;
                        err = 0;
@@ -380,12 +381,10 @@ int __ipv6_dev_ac_dec(struct inet6_dev *idev, const struct in6_addr *addr)
 {
        struct ifacaddr6 *aca, *prev_aca;
 
-       ASSERT_RTNL();
-
        write_lock_bh(&idev->lock);
        prev_aca = NULL;
-       for (aca = rtnl_dereference(idev->ac_list); aca;
-            aca = rtnl_dereference(aca->aca_next)) {
+       for (aca = ac_dereference(idev->ac_list, idev); aca;
+            aca = ac_dereference(aca->aca_next, idev)) {
                if (ipv6_addr_equal(&aca->aca_addr, addr))
                        break;
                prev_aca = aca;
@@ -429,7 +428,7 @@ void ipv6_ac_destroy_dev(struct inet6_dev *idev)
        struct ifacaddr6 *aca;
 
        write_lock_bh(&idev->lock);
-       while ((aca = rtnl_dereference(idev->ac_list)) != NULL) {
+       while ((aca = ac_dereference(idev->ac_list, idev)) != NULL) {
                rcu_assign_pointer(idev->ac_list, aca->aca_next);
                write_unlock_bh(&idev->lock);