In genl_bind(), currently genl_lock and write cb_lock are taken
for iteration of genl_fam_idr and processing of static values
stored in struct genl_family. Take just read cb_lock for this task
as it is sufficient to guard the idr and the struct against
concurrent genl_register/unregister_family() calls.
This will allow to run genl command processing in genl_rcv() and
mnl_socket_setsockopt(.., NETLINK_ADD_MEMBERSHIP, ..) in parallel.
Reported-by: Vikas Gupta <vikas.gupta@broadcom.com>
Signed-off-by: Jiri Pirko <jiri@nvidia.com>
Link: https://lore.kernel.org/r/20220825081940.1283335-1-jiri@resnulli.us
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
 
        unsigned int id;
        int ret = 0;
 
-       genl_lock_all();
+       down_read(&cb_lock);
 
        idr_for_each_entry(&genl_fam_idr, family, id) {
                const struct genl_multicast_group *grp;
                break;
        }
 
-       genl_unlock_all();
+       up_read(&cb_lock);
        return ret;
 }