ipv6: do not abuse GFP_ATOMIC in inet6_netconf_notify_devconf()
authorEric Dumazet <edumazet@google.com>
Fri, 8 Jul 2016 03:46:04 +0000 (05:46 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 10 May 2020 08:26:16 +0000 (10:26 +0200)
commit 927265bc6cd6374c9bafc43408ece4e92311b149 upstream.

All inet6_netconf_notify_devconf() callers are in process context,
so we can use GFP_KERNEL allocations if we take care of not holding
a rwlock while not needed in ip6mr (we hold RTNL there)

Fixes: d67b8c616b48 ("netconf: advertise mc_forwarding status")
Fixes: f3a1bfb11ccb ("rtnl/ipv6: use netconf msg to advertise forwarding status")
Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Acked-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
net/ipv6/addrconf.c
net/ipv6/ip6mr.c

index 01304830fa48e946271efd6a82f288a16f0d6bf0..cd951289a45fda66a4dd59cd4cf4dfa0c67fb70f 100644 (file)
@@ -540,7 +540,7 @@ void inet6_netconf_notify_devconf(struct net *net, int type, int ifindex,
        struct sk_buff *skb;
        int err = -ENOBUFS;
 
-       skb = nlmsg_new(inet6_netconf_msgsize_devconf(type), GFP_ATOMIC);
+       skb = nlmsg_new(inet6_netconf_msgsize_devconf(type), GFP_KERNEL);
        if (!skb)
                goto errout;
 
@@ -552,7 +552,7 @@ void inet6_netconf_notify_devconf(struct net *net, int type, int ifindex,
                kfree_skb(skb);
                goto errout;
        }
-       rtnl_notify(skb, net, 0, RTNLGRP_IPV6_NETCONF, NULL, GFP_ATOMIC);
+       rtnl_notify(skb, net, 0, RTNLGRP_IPV6_NETCONF, NULL, GFP_KERNEL);
        return;
 errout:
        rtnl_set_sk_err(net, RTNLGRP_IPV6_NETCONF, err);
index 91f16e679f63784dd3c6687f77fecad68dbd361d..20812e8b24dd86b270143760d55a004e1c334ac7 100644 (file)
@@ -1594,14 +1594,15 @@ static int ip6mr_sk_init(struct mr6_table *mrt, struct sock *sk)
        if (likely(mrt->mroute6_sk == NULL)) {
                mrt->mroute6_sk = sk;
                net->ipv6.devconf_all->mc_forwarding++;
-               inet6_netconf_notify_devconf(net, NETCONFA_MC_FORWARDING,
-                                            NETCONFA_IFINDEX_ALL,
-                                            net->ipv6.devconf_all);
-       }
-       else
+       } else {
                err = -EADDRINUSE;
+       }
        write_unlock_bh(&mrt_lock);
 
+       if (!err)
+               inet6_netconf_notify_devconf(net, NETCONFA_MC_FORWARDING,
+                                            NETCONFA_IFINDEX_ALL,
+                                            net->ipv6.devconf_all);
        rtnl_unlock();
 
        return err;
@@ -1619,11 +1620,11 @@ int ip6mr_sk_done(struct sock *sk)
                        write_lock_bh(&mrt_lock);
                        mrt->mroute6_sk = NULL;
                        net->ipv6.devconf_all->mc_forwarding--;
+                       write_unlock_bh(&mrt_lock);
                        inet6_netconf_notify_devconf(net,
                                                     NETCONFA_MC_FORWARDING,
                                                     NETCONFA_IFINDEX_ALL,
                                                     net->ipv6.devconf_all);
-                       write_unlock_bh(&mrt_lock);
 
                        mroute_clean_tables(mrt, false);
                        err = 0;